rbs 1.7.0.beta.4 → 1.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -1
  3. data/CHANGELOG.md +58 -2
  4. data/Steepfile +0 -1
  5. data/core/array.rbs +3 -3
  6. data/core/binding.rbs +2 -0
  7. data/core/builtin.rbs +4 -0
  8. data/core/complex.rbs +0 -2
  9. data/core/enumerable.rbs +3 -3
  10. data/core/env.rbs +881 -0
  11. data/core/false_class.rbs +2 -0
  12. data/core/float.rbs +0 -2
  13. data/core/integer.rbs +0 -2
  14. data/core/nil_class.rbs +2 -0
  15. data/core/numeric.rbs +7 -0
  16. data/core/object.rbs +1 -1
  17. data/core/proc.rbs +2 -0
  18. data/core/rational.rbs +0 -2
  19. data/core/symbol.rbs +2 -0
  20. data/core/thread.rbs +1 -1
  21. data/core/true_class.rbs +2 -0
  22. data/core/unbound_method.rbs +13 -0
  23. data/docs/rbs_by_example.md +2 -2
  24. data/docs/syntax.md +25 -23
  25. data/ext/rbs_extension/parser.c +99 -95
  26. data/ext/rbs_extension/parserstate.c +0 -1
  27. data/ext/rbs_extension/rbs_extension.h +1 -1
  28. data/ext/rbs_extension/ruby_objs.c +8 -6
  29. data/ext/rbs_extension/ruby_objs.h +2 -4
  30. data/lib/rbs/ast/declarations.rb +6 -2
  31. data/lib/rbs/cli.rb +1 -1
  32. data/lib/rbs/collection/sources/git.rb +6 -1
  33. data/lib/rbs/definition_builder.rb +29 -2
  34. data/lib/rbs/environment.rb +1 -0
  35. data/lib/rbs/environment_walker.rb +4 -1
  36. data/lib/rbs/errors.rb +12 -0
  37. data/lib/rbs/prototype/helpers.rb +113 -0
  38. data/lib/rbs/prototype/rb.rb +2 -105
  39. data/lib/rbs/prototype/runtime.rb +16 -0
  40. data/lib/rbs/test/setup.rb +1 -0
  41. data/lib/rbs/type_alias_regularity.rb +115 -0
  42. data/lib/rbs/types.rb +11 -23
  43. data/lib/rbs/validator.rb +40 -7
  44. data/lib/rbs/variance_calculator.rb +52 -24
  45. data/lib/rbs/version.rb +1 -1
  46. data/lib/rbs/writer.rb +1 -1
  47. data/lib/rbs.rb +2 -0
  48. data/schema/decls.json +13 -1
  49. data/schema/types.json +8 -2
  50. data/sig/collection/collections.rbs +2 -0
  51. data/sig/declarations.rbs +9 -6
  52. data/sig/definition_builder.rbs +29 -0
  53. data/sig/environment_walker.rbs +26 -0
  54. data/sig/errors.rbs +10 -0
  55. data/sig/type_alias_regularity.rbs +92 -0
  56. data/sig/types.rbs +11 -8
  57. data/sig/validator.rbs +7 -0
  58. data/sig/variance_calculator.rbs +50 -0
  59. data/stdlib/bigdecimal/0/big_decimal.rbs +44 -0
  60. data/stdlib/csv/0/csv.rbs +49 -3
  61. data/stdlib/date/0/date.rbs +2 -2
  62. data/stdlib/set/0/set.rbs +3 -3
  63. data/steep/Gemfile.lock +10 -10
  64. metadata +8 -6
  65. data/lib/rbs/parser.y +0 -1805
  66. data/lib/ruby/signature.rb +0 -7
@@ -781,9 +781,36 @@ module RBS
781
781
  end
782
782
 
783
783
  def expand_alias(type_name)
784
- entry = env.alias_decls[type_name] or raise "Unknown name for expand_alias: #{type_name}"
784
+ expand_alias2(type_name, [])
785
+ end
786
+
787
+ def expand_alias1(type_name)
788
+ entry = env.alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
789
+ as = entry.decl.type_params.each.map { Types::Bases::Any.new(location: nil) }
790
+ expand_alias2(type_name, as)
791
+ end
792
+
793
+ def expand_alias2(type_name, args)
794
+ entry = env.alias_decls[type_name] or raise "Unknown alias name: #{type_name}"
795
+
785
796
  ensure_namespace!(type_name.namespace, location: entry.decl.location)
786
- entry.decl.type
797
+ params = entry.decl.type_params.each.map(&:name)
798
+
799
+ unless params.size == args.size
800
+ as = "[#{args.join(", ")}]" unless args.empty?
801
+ ps = "[#{params.join(", ")}]" unless params.empty?
802
+
803
+ raise "Invalid type application: type = #{type_name}#{as}, decl = #{type_name}#{ps}"
804
+ end
805
+
806
+ type = entry.decl.type
807
+
808
+ unless params.empty?
809
+ subst = Substitution.build(params, args)
810
+ type = type.sub(subst)
811
+ end
812
+
813
+ type
787
814
  end
788
815
 
789
816
  def update(env:, except:, ancestor_builder:)
@@ -319,6 +319,7 @@ module RBS
319
319
  when AST::Declarations::Alias
320
320
  AST::Declarations::Alias.new(
321
321
  name: decl.name.with_prefix(prefix),
322
+ type_params: decl.type_params,
322
323
  type: absolute_type(resolver, decl.type, context: context),
323
324
  location: decl.location,
324
325
  annotations: decl.annotations,
@@ -57,7 +57,7 @@ module RBS
57
57
  end
58
58
  end
59
59
  when name.alias?
60
- each_type_node builder.expand_alias(name), &block
60
+ each_type_node builder.expand_alias1(name), &block
61
61
  else
62
62
  raise "Unexpected TypeNameNode with type_name=#{name}"
63
63
  end
@@ -126,6 +126,9 @@ module RBS
126
126
  end
127
127
  when RBS::Types::Alias
128
128
  yield TypeNameNode.new(type_name: type.name)
129
+ type.args.each do |ty|
130
+ each_type_node(ty, &block)
131
+ end
129
132
  when RBS::Types::Union, RBS::Types::Intersection, RBS::Types::Tuple
130
133
  type.types.each do |ty|
131
134
  each_type_node ty, &block
data/lib/rbs/errors.rb CHANGED
@@ -431,4 +431,16 @@ module RBS
431
431
  @alias_names.map(&:name).join(', ')
432
432
  end
433
433
  end
434
+
435
+ class NonregularTypeAliasError < LoadingError
436
+ attr_reader :diagnostic
437
+ attr_reader :location
438
+
439
+ def initialize(diagnostic:, location:)
440
+ @diagnostic = diagnostic
441
+ @location = location
442
+
443
+ super "#{Location.to_string location}: Nonregular generic type alias is prohibited: #{diagnostic.type_name}, #{diagnostic.nonregular_type}"
444
+ end
445
+ end
434
446
  end
@@ -0,0 +1,113 @@
1
+ module RBS
2
+ module Prototype
3
+ module Helpers
4
+ private
5
+
6
+ def block_from_body(node)
7
+ _, args_node, body_node = node.children
8
+
9
+ _pre_num, _pre_init, _opt, _first_post, _post_num, _post_init, _rest, _kw, _kwrest, block = args_from_node(args_node)
10
+
11
+ method_block = nil
12
+
13
+ if block
14
+ method_block = Types::Block.new(
15
+ # HACK: The `block` is :& on `def m(...)` syntax.
16
+ # In this case the block looks optional in most cases, so it marks optional.
17
+ # In other cases, we can't determine which is required or optional, so it marks required.
18
+ required: block != :&,
19
+ type: Types::Function.empty(untyped)
20
+ )
21
+ end
22
+
23
+ if body_node
24
+ if (yields = any_node?(body_node) {|n| n.type == :YIELD })
25
+ method_block = Types::Block.new(
26
+ required: true,
27
+ type: Types::Function.empty(untyped)
28
+ )
29
+
30
+ yields.each do |yield_node|
31
+ array_content = yield_node.children[0]&.children&.compact || []
32
+
33
+ positionals, keywords = if keyword_hash?(array_content.last)
34
+ [array_content.take(array_content.size - 1), array_content.last]
35
+ else
36
+ [array_content, nil]
37
+ end
38
+
39
+ if (diff = positionals.size - method_block.type.required_positionals.size) > 0
40
+ diff.times do
41
+ method_block.type.required_positionals << Types::Function::Param.new(
42
+ type: untyped,
43
+ name: nil
44
+ )
45
+ end
46
+ end
47
+
48
+ if keywords
49
+ keywords.children[0].children.each_slice(2) do |key_node, value_node|
50
+ if key_node
51
+ key = key_node.children[0]
52
+ method_block.type.required_keywords[key] ||=
53
+ Types::Function::Param.new(
54
+ type: untyped,
55
+ name: nil
56
+ )
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+
64
+ method_block
65
+ end
66
+
67
+ def each_child(node, &block)
68
+ each_node node.children, &block
69
+ end
70
+
71
+ def each_node(nodes)
72
+ nodes.each do |child|
73
+ if child.is_a?(RubyVM::AbstractSyntaxTree::Node)
74
+ yield child
75
+ end
76
+ end
77
+ end
78
+
79
+
80
+ def any_node?(node, nodes: [], &block)
81
+ if yield(node)
82
+ nodes << node
83
+ end
84
+
85
+ each_child node do |child|
86
+ any_node? child, nodes: nodes, &block
87
+ end
88
+
89
+ nodes.empty? ? nil : nodes
90
+ end
91
+
92
+ def keyword_hash?(node)
93
+ if node
94
+ if node.type == :HASH
95
+ node.children[0].children.compact.each_slice(2).all? {|key, _|
96
+ key.type == :LIT && key.children[0].is_a?(Symbol)
97
+ }
98
+ end
99
+ end
100
+ end
101
+
102
+ # NOTE: args_node may be a nil by a bug
103
+ # https://bugs.ruby-lang.org/issues/17495
104
+ def args_from_node(args_node)
105
+ args_node&.children || [0, nil, nil, nil, 0, nil, nil, nil, nil, nil]
106
+ end
107
+
108
+ def untyped
109
+ @untyped ||= Types::Bases::Any.new(location: nil)
110
+ end
111
+ end
112
+ end
113
+ end
@@ -1,6 +1,8 @@
1
1
  module RBS
2
2
  module Prototype
3
3
  class RB
4
+ include Helpers
5
+
4
6
  Context = Struct.new(:module_function, :singleton, :namespace, keyword_init: true) do
5
7
  def self.initial(namespace: Namespace.root)
6
8
  self.new(module_function: false, singleton: false, namespace: namespace)
@@ -372,18 +374,6 @@ module RBS
372
374
  end
373
375
  end
374
376
 
375
- def each_node(nodes)
376
- nodes.each do |child|
377
- if child.is_a?(RubyVM::AbstractSyntaxTree::Node)
378
- yield child
379
- end
380
- end
381
- end
382
-
383
- def each_child(node, &block)
384
- each_node node.children, &block
385
- end
386
-
387
377
  def function_type_from_body(node, def_name)
388
378
  table_node, args_node, *_ = node.children
389
379
 
@@ -568,95 +558,6 @@ module RBS
568
558
  end
569
559
  end
570
560
 
571
- def block_from_body(node)
572
- _, args_node, body_node = node.children
573
-
574
- _pre_num, _pre_init, _opt, _first_post, _post_num, _post_init, _rest, _kw, _kwrest, block = args_from_node(args_node)
575
-
576
- method_block = nil
577
-
578
- if block
579
- method_block = Types::Block.new(
580
- # HACK: The `block` is :& on `def m(...)` syntax.
581
- # In this case the block looks optional in most cases, so it marks optional.
582
- # In other cases, we can't determine which is required or optional, so it marks required.
583
- required: block != :&,
584
- type: Types::Function.empty(untyped)
585
- )
586
- end
587
-
588
- if body_node
589
- if (yields = any_node?(body_node) {|n| n.type == :YIELD })
590
- method_block = Types::Block.new(
591
- required: true,
592
- type: Types::Function.empty(untyped)
593
- )
594
-
595
- yields.each do |yield_node|
596
- array_content = yield_node.children[0]&.children&.compact || []
597
-
598
- positionals, keywords = if keyword_hash?(array_content.last)
599
- [array_content.take(array_content.size - 1), array_content.last]
600
- else
601
- [array_content, nil]
602
- end
603
-
604
- if (diff = positionals.size - method_block.type.required_positionals.size) > 0
605
- diff.times do
606
- method_block.type.required_positionals << Types::Function::Param.new(
607
- type: untyped,
608
- name: nil
609
- )
610
- end
611
- end
612
-
613
- if keywords
614
- keywords.children[0].children.each_slice(2) do |key_node, value_node|
615
- if key_node
616
- key = key_node.children[0]
617
- method_block.type.required_keywords[key] ||=
618
- Types::Function::Param.new(
619
- type: untyped,
620
- name: nil
621
- )
622
- end
623
- end
624
- end
625
- end
626
- end
627
- end
628
-
629
- method_block
630
- end
631
-
632
- # NOTE: args_node may be a nil by a bug
633
- # https://bugs.ruby-lang.org/issues/17495
634
- def args_from_node(args_node)
635
- args_node&.children || [0, nil, nil, nil, 0, nil, nil, nil, nil, nil]
636
- end
637
-
638
- def keyword_hash?(node)
639
- if node
640
- if node.type == :HASH
641
- node.children[0].children.compact.each_slice(2).all? {|key, _|
642
- key.type == :LIT && key.children[0].is_a?(Symbol)
643
- }
644
- end
645
- end
646
- end
647
-
648
- def any_node?(node, nodes: [], &block)
649
- if yield(node)
650
- nodes << node
651
- end
652
-
653
- each_child node do |child|
654
- any_node? child, nodes: nodes, &block
655
- end
656
-
657
- nodes.empty? ? nil : nodes
658
- end
659
-
660
561
  def node_type(node, default: Types::Bases::Any.new(location: nil))
661
562
  case node.type
662
563
  when :LIT
@@ -689,10 +590,6 @@ module RBS
689
590
  end
690
591
  end
691
592
 
692
- def untyped
693
- @untyped ||= Types::Bases::Any.new(location: nil)
694
- end
695
-
696
593
  def private
697
594
  @private ||= AST::Members::Private.new(location: nil)
698
595
  end
@@ -1,6 +1,8 @@
1
1
  module RBS
2
2
  module Prototype
3
3
  class Runtime
4
+ include Helpers
5
+
4
6
  attr_reader :patterns
5
7
  attr_reader :env
6
8
  attr_reader :merge
@@ -138,6 +140,8 @@ module RBS
138
140
  end
139
141
  end
140
142
 
143
+ block ||= block_from_ast_of(method)
144
+
141
145
  return_type = if method.name == :initialize
142
146
  Types::Bases::Void.new(location: nil)
143
147
  else
@@ -522,6 +526,18 @@ module RBS
522
526
  []
523
527
  end
524
528
  end
529
+
530
+ def block_from_ast_of(method)
531
+ return nil if RUBY_VERSION < '3.1'
532
+
533
+ begin
534
+ ast = RubyVM::AbstractSyntaxTree.of(method)
535
+ rescue ArgumentError
536
+ return # When the method is defined in eval
537
+ end
538
+
539
+ block_from_body(ast) if ast&.type == :SCOPE
540
+ end
525
541
  end
526
542
  end
527
543
  end
@@ -13,6 +13,7 @@ begin
13
13
  filter = ENV.fetch('RBS_TEST_TARGET', "").split(',').map! { |e| e.strip }
14
14
  skips = (ENV['RBS_TEST_SKIP'] || '').split(',').map! { |e| e.strip }
15
15
  RBS.logger_level = (ENV["RBS_TEST_LOGLEVEL"] || "info")
16
+ logger.level = RBS.logger_level
16
17
  sample_size = get_sample_size(ENV['RBS_TEST_SAMPLE_SIZE'] || '')
17
18
  double_class = to_double_class(ENV['RBS_TEST_DOUBLE_SUITE'])
18
19
  unchecked_classes = (ENV['RBS_TEST_UNCHECKED_CLASSES'] || '').split(',').map! { |unchecked_class| unchecked_class.strip }.push(*double_class)
@@ -0,0 +1,115 @@
1
+ module RBS
2
+ class TypeAliasRegularity
3
+ class Diagnostic
4
+ attr_reader :type_name, :nonregular_type
5
+
6
+ def initialize(type_name:, nonregular_type:)
7
+ @type_name = type_name
8
+ @nonregular_type = nonregular_type
9
+ end
10
+ end
11
+
12
+ attr_reader :env, :builder, :diagnostics
13
+
14
+ def initialize(env:)
15
+ @env = env
16
+ @builder = DefinitionBuilder.new(env: env)
17
+ @diagnostics = {}
18
+ end
19
+
20
+ def validate
21
+ diagnostics.clear
22
+
23
+ each_mutual_alias_defs do |names|
24
+ # Find the first generic type alias in strongly connected component.
25
+ # This is to skip the regularity check when the alias is not generic.
26
+ names.each do |name|
27
+ # @type break: nil
28
+ if type = build_alias_type(name)
29
+ # Running validation only once from the first generic type is enough, because they are mutual recursive definition.
30
+ validate_alias_type(type, names, {})
31
+ break
32
+ end
33
+ end
34
+ end
35
+ end
36
+
37
+ def validate_alias_type(alias_type, names, types)
38
+ if names.include?(alias_type.name)
39
+ if ex_type = types[alias_type.name]
40
+ unless compatible_args?(ex_type.args, alias_type.args)
41
+ diagnostics[alias_type.name] ||=
42
+ Diagnostic.new(type_name: alias_type.name, nonregular_type: alias_type)
43
+ end
44
+
45
+ return
46
+ else
47
+ types[alias_type.name] = alias_type
48
+ end
49
+
50
+ expanded = builder.expand_alias2(alias_type.name, alias_type.args)
51
+ each_alias_type(expanded) do |at|
52
+ validate_alias_type(at, names, types)
53
+ end
54
+ end
55
+ end
56
+
57
+ def build_alias_type(name)
58
+ entry = env.alias_decls[name] or raise "Unknown alias name: #{name}"
59
+ unless entry.decl.type_params.empty?
60
+ as = entry.decl.type_params.each.map {|param| Types::Variable.new(name: param.name, location: nil) }
61
+ Types::Alias.new(name: name, args: as, location: nil)
62
+ end
63
+ end
64
+
65
+ def compatible_args?(args1, args2)
66
+ if args1.size == args2.size
67
+ args1.zip(args2).all? do |t1, t2|
68
+ t1.is_a?(Types::Bases::Any) ||
69
+ t2.is_a?(Types::Bases::Any) ||
70
+ t1 == t2
71
+ end
72
+ end
73
+ end
74
+
75
+ def nonregular?(type_name)
76
+ diagnostics[type_name]
77
+ end
78
+
79
+ def each_mutual_alias_defs(&block)
80
+ # @type var each_node: TSort::_EachNode[TypeName]
81
+ each_node = __skip__ = -> (&block) do
82
+ env.alias_decls.each_value do |decl|
83
+ block[decl.name]
84
+ end
85
+ end
86
+ # @type var each_child: TSort::_EachChild[TypeName]
87
+ each_child = __skip__ = -> (name, &block) do
88
+ type = builder.expand_alias1(name)
89
+ each_alias_type(type) do |ty|
90
+ block[ty.name]
91
+ end
92
+ end
93
+
94
+ TSort.each_strongly_connected_component(each_node, each_child) do |names|
95
+ yield Set.new(names)
96
+ end
97
+ end
98
+
99
+ def each_alias_type(type, &block)
100
+ if type.is_a?(RBS::Types::Alias)
101
+ yield type
102
+ end
103
+
104
+ type.each_type do |ty|
105
+ each_alias_type(ty, &block)
106
+ end
107
+ end
108
+
109
+ def self.validate(env:)
110
+ self.new(env: env).tap do |validator|
111
+ validator.validate()
112
+ end
113
+ end
114
+ end
115
+ end
data/lib/rbs/types.rb CHANGED
@@ -295,39 +295,27 @@ module RBS
295
295
 
296
296
  class Alias
297
297
  attr_reader :location
298
- attr_reader :name
299
298
 
300
- def initialize(name:, location:)
299
+ include Application
300
+
301
+ def initialize(name:, args:, location:)
301
302
  @name = name
303
+ @args = args
302
304
  @location = location
303
305
  end
304
306
 
305
- def ==(other)
306
- other.is_a?(Alias) && other.name == name
307
- end
308
-
309
- alias eql? ==
310
-
311
- def hash
312
- self.class.hash ^ name.hash
313
- end
314
-
315
- include NoFreeVariables
316
- include NoSubst
317
-
318
307
  def to_json(state = _ = nil)
319
- { class: :alias, name: name, location: location }.to_json(state)
308
+ { class: :alias, name: name, args: args, location: location }.to_json(state)
320
309
  end
321
310
 
322
- def to_s(level = 0)
323
- name.to_s
311
+ def sub(s)
312
+ Alias.new(name: name, args: args.map {|ty| ty.sub(s) }, location: location)
324
313
  end
325
314
 
326
- include EmptyEachType
327
-
328
- def map_type_name
315
+ def map_type_name(&block)
329
316
  Alias.new(
330
317
  name: yield(name, location, self),
318
+ args: args.map {|arg| arg.map_type_name(&block) },
331
319
  location: location
332
320
  )
333
321
  end
@@ -433,7 +421,7 @@ module RBS
433
421
  return "{ }" if self.fields.empty?
434
422
 
435
423
  fields = self.fields.map do |key, type|
436
- if key.is_a?(Symbol) && key.match?(/\A[A-Za-z_][A-Za-z_]*\z/) && !Parser::KEYWORDS.include?(key)
424
+ if key.is_a?(Symbol) && key.match?(/\A[A-Za-z_][A-Za-z_]*\z/)
437
425
  "#{key}: #{type}"
438
426
  else
439
427
  "#{key.inspect} => #{type}"
@@ -690,7 +678,7 @@ module RBS
690
678
 
691
679
  def to_s
692
680
  if name
693
- if Parser::KEYWORDS.include?(name)
681
+ if Parser::KEYWORDS.include?(name.to_s)
694
682
  "#{type} `#{name}`"
695
683
  else
696
684
  "#{type} #{name}"
data/lib/rbs/validator.rb CHANGED
@@ -2,10 +2,12 @@ module RBS
2
2
  class Validator
3
3
  attr_reader :env
4
4
  attr_reader :resolver
5
+ attr_reader :definition_builder
5
6
 
6
7
  def initialize(env:, resolver:)
7
8
  @env = env
8
9
  @resolver = resolver
10
+ @definition_builder = DefinitionBuilder.new(env: env)
9
11
  end
10
12
 
11
13
  def absolute_type(type, context:)
@@ -17,8 +19,8 @@ module RBS
17
19
  # Validates presence of the relative type, and application arity match.
18
20
  def validate_type(type, context:)
19
21
  case type
20
- when Types::ClassInstance, Types::Interface
21
- # @type var type: Types::ClassInstance | Types::Interface
22
+ when Types::ClassInstance, Types::Interface, Types::Alias
23
+ # @type var type: Types::ClassInstance | Types::Interface | Types::Alias
22
24
  if type.name.namespace.relative?
23
25
  type = _ = absolute_type(type, context: context) do |_|
24
26
  NoTypeFoundError.check!(type.name.absolute!, env: env, location: type.location)
@@ -30,6 +32,8 @@ module RBS
30
32
  env.class_decls[type.name]&.type_params
31
33
  when Types::Interface
32
34
  env.interface_decls[type.name]&.decl&.type_params
35
+ when Types::Alias
36
+ env.alias_decls[type.name]&.decl&.type_params
33
37
  end
34
38
 
35
39
  unless type_params
@@ -43,8 +47,8 @@ module RBS
43
47
  location: type.location
44
48
  )
45
49
 
46
- when Types::Alias, Types::ClassSingleton
47
- # @type var type: Types::Alias | Types::ClassSingleton
50
+ when Types::ClassSingleton
51
+ # @type var type: Types::ClassSingleton
48
52
  type = _ = absolute_type(type, context: context) { type.name.absolute! }
49
53
  NoTypeFoundError.check!(type.name, env: env, location: type.location)
50
54
  end
@@ -55,11 +59,40 @@ module RBS
55
59
  end
56
60
 
57
61
  def validate_type_alias(entry:)
58
- @type_alias_dependency ||= TypeAliasDependency.new(env: env)
59
- if @type_alias_dependency.circular_definition?(entry.decl.name)
62
+ type_name = entry.decl.name
63
+
64
+ if type_alias_dependency.circular_definition?(type_name)
60
65
  location = entry.decl.location or raise
61
- raise RecursiveTypeAliasError.new(alias_names: [entry.decl.name], location: location)
66
+ raise RecursiveTypeAliasError.new(alias_names: [type_name], location: location)
67
+ end
68
+
69
+ if diagnostic = type_alias_regularity.nonregular?(type_name)
70
+ location = entry.decl.location or raise
71
+ raise NonregularTypeAliasError.new(diagnostic: diagnostic, location: location)
72
+ end
73
+
74
+ unless entry.decl.type_params.empty?
75
+ calculator = VarianceCalculator.new(builder: definition_builder)
76
+ result = calculator.in_type_alias(name: type_name)
77
+ if set = result.incompatible?(entry.decl.type_params)
78
+ set.each do |param_name|
79
+ param = entry.decl.type_params[param_name] or raise
80
+ raise InvalidVarianceAnnotationError.new(
81
+ type_name: type_name,
82
+ param: param,
83
+ location: entry.decl.type.location
84
+ )
85
+ end
86
+ end
62
87
  end
63
88
  end
89
+
90
+ def type_alias_dependency
91
+ @type_alias_dependency ||= TypeAliasDependency.new(env: env)
92
+ end
93
+
94
+ def type_alias_regularity
95
+ @type_alias_regularity ||= TypeAliasRegularity.validate(env: env)
96
+ end
64
97
  end
65
98
  end