rbs 1.7.0.beta.4 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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