steep 1.5.3 → 1.6.0.pre.2

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 (53) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-windows.yml +1 -2
  3. data/.github/workflows/ruby.yml +1 -2
  4. data/CHANGELOG.md +46 -0
  5. data/Gemfile +3 -1
  6. data/Gemfile.lock +37 -10
  7. data/gemfile_steep/Gemfile.lock +3 -3
  8. data/lib/steep/ast/types/logic.rb +6 -0
  9. data/lib/steep/cli.rb +39 -19
  10. data/lib/steep/diagnostic/ruby.rb +4 -4
  11. data/lib/steep/interface/builder.rb +9 -0
  12. data/lib/steep/path_helper.rb +2 -0
  13. data/lib/steep/project/pattern.rb +1 -1
  14. data/lib/steep/server/change_buffer.rb +9 -0
  15. data/lib/steep/server/delay_queue.rb +41 -0
  16. data/lib/steep/server/interaction_worker.rb +4 -2
  17. data/lib/steep/server/master.rb +106 -10
  18. data/lib/steep/server/type_check_worker.rb +10 -3
  19. data/lib/steep/services/completion_provider.rb +2 -2
  20. data/lib/steep/services/stats_calculator.rb +2 -2
  21. data/lib/steep/services/type_name_completion.rb +86 -15
  22. data/lib/steep/signature/validator.rb +9 -2
  23. data/lib/steep/subtyping/check.rb +24 -18
  24. data/lib/steep/type_construction.rb +61 -17
  25. data/lib/steep/type_inference/logic_type_interpreter.rb +26 -0
  26. data/lib/steep/type_inference/method_params.rb +1 -1
  27. data/lib/steep/version.rb +1 -1
  28. data/lib/steep.rb +1 -3
  29. data/sig/shims/language-server_protocol.rbs +12 -0
  30. data/sig/steep/ast/types/logic.rbs +5 -0
  31. data/sig/steep/ast/types.rbs +1 -1
  32. data/sig/steep/cli.rbs +2 -0
  33. data/sig/steep/diagnostic/ruby.rbs +7 -7
  34. data/sig/steep/project/pattern.rbs +22 -0
  35. data/sig/steep/server/change_buffer.rbs +4 -0
  36. data/sig/steep/server/delay_queue.rbs +37 -0
  37. data/sig/steep/server/master.rbs +4 -0
  38. data/sig/steep/services/stats_calculator.rbs +30 -6
  39. data/sig/steep/services/type_name_completion.rbs +13 -0
  40. data/sig/steep/signature/validator.rbs +5 -0
  41. data/sig/steep/subtyping/check.rbs +1 -1
  42. data/sig/steep/subtyping/relation.rbs +11 -1
  43. data/sig/steep/subtyping/result.rbs +1 -1
  44. data/sig/steep/type_construction.rbs +1 -1
  45. data/smoke/block/test_expectations.yml +10 -14
  46. data/smoke/enumerator/test_expectations.yml +10 -10
  47. data/smoke/integer/test_expectations.yml +5 -16
  48. data/smoke/regression/hello world.rb +1 -0
  49. data/smoke/regression/test_expectations.yml +12 -0
  50. data/steep.gemspec +1 -1
  51. metadata +8 -7
  52. data/lib/steep/shims/filter_map.rb +0 -30
  53. data/lib/steep/shims/symbol_start_with.rb +0 -18
@@ -402,6 +402,7 @@ module Steep
402
402
 
403
403
  attr_reader :initialize_params
404
404
  attr_accessor :typecheck_automatically
405
+ attr_reader :start_type_checking_queue
405
406
 
406
407
  def initialize(project:, reader:, writer:, interaction_worker:, typecheck_workers:, queue: Queue.new)
407
408
  @project = project
@@ -416,6 +417,7 @@ module Steep
416
417
 
417
418
  @controller = TypeCheckController.new(project: project)
418
419
  @result_controller = ResultController.new()
420
+ @start_type_checking_queue = DelayQueue.new(delay: 0.1)
419
421
  end
420
422
 
421
423
  def start
@@ -488,6 +490,8 @@ module Steep
488
490
  Steep.logger.info { "Processing SendMessageJob: dest=#{job.dest.name}, method=#{job.message[:method] || "-"}, id=#{job.message[:id] || "-"}" }
489
491
  job.dest << job.message
490
492
  end
493
+ when Proc
494
+ job.call()
491
495
  end
492
496
  end
493
497
  end
@@ -529,6 +533,10 @@ module Steep
529
533
  initialize_params&.dig(:capabilities, :window, :workDoneProgress) ? true : false
530
534
  end
531
535
 
536
+ def file_system_watcher_supported?
537
+ initialize_params&.dig(:capabilities, :workspace, :didChangeWatchedFiles, :dynamicRegistration) || false
538
+ end
539
+
532
540
  def process_message_from_client(message)
533
541
  Steep.logger.info "Processing message from client: method=#{message[:method]}, id=#{message[:id]}"
534
542
  id = message[:id]
@@ -551,7 +559,6 @@ module Steep
551
559
  capabilities: LSP::Interface::ServerCapabilities.new(
552
560
  text_document_sync: LSP::Interface::TextDocumentSyncOptions.new(
553
561
  change: LSP::Constant::TextDocumentSyncKind::INCREMENTAL,
554
- save: LSP::Interface::SaveOptions.new(include_text: false),
555
562
  open_close: true
556
563
  ),
557
564
  hover_provider: {
@@ -575,6 +582,52 @@ module Steep
575
582
  )
576
583
  }
577
584
  )
585
+
586
+ if file_system_watcher_supported?
587
+ patterns = [] #: Array[String]
588
+ project.targets.each do |target|
589
+ target.source_pattern.patterns.each do |pat|
590
+ path = project.base_dir + pat
591
+ patterns << path.to_s unless path.directory?
592
+ end
593
+ target.source_pattern.prefixes.each do |pat|
594
+ path = project.base_dir + pat
595
+ patterns << (path + "**/*.rb").to_s unless path.file?
596
+ end
597
+ target.signature_pattern.patterns.each do |pat|
598
+ path = project.base_dir + pat
599
+ patterns << path.to_s unless path.directory?
600
+ end
601
+ target.signature_pattern.prefixes.each do |pat|
602
+ path = project.base_dir + pat
603
+ patterns << (path + "**/*.rbs").to_s unless path.file?
604
+ end
605
+ end
606
+ patterns.sort!
607
+ patterns.uniq!
608
+
609
+ Steep.logger.info { "Setting up didChangeWatchedFiles with pattern: #{patterns.inspect}" }
610
+
611
+ job_queue << SendMessageJob.to_client(
612
+ message: {
613
+ id: SecureRandom.uuid,
614
+ method: "client/registerCapability",
615
+ params: {
616
+ registrations: [
617
+ {
618
+ id: SecureRandom.uuid,
619
+ method: "workspace/didChangeWatchedFiles",
620
+ registerOptions: {
621
+ watchers: patterns.map do |pattern|
622
+ { globPattern: pattern }
623
+ end
624
+ }
625
+ }
626
+ ]
627
+ }
628
+ }
629
+ )
630
+ end
578
631
  end
579
632
  end
580
633
 
@@ -585,28 +638,71 @@ module Steep
585
638
  end
586
639
  end
587
640
 
641
+ when "workspace/didChangeWatchedFiles"
642
+ message[:params][:changes].each do |change|
643
+ uri = change[:uri]
644
+ type = change[:type]
645
+
646
+ path = PathHelper.to_pathname(uri) or next
647
+
648
+ controller.push_changes(path)
649
+
650
+ case type
651
+ when 1, 2
652
+ content = path.read
653
+ when 4
654
+ # Deleted
655
+ content = ""
656
+ end
657
+
658
+ broadcast_notification({
659
+ method: "$/file/reset",
660
+ params: { uri: uri, content: content }
661
+ })
662
+ end
663
+
664
+ if typecheck_automatically
665
+ start_type_checking_queue.execute do
666
+ job_queue.push(
667
+ -> do
668
+ last_request = current_type_check_request
669
+ if request = controller.make_request(last_request: last_request)
670
+ start_type_check(request, last_request: last_request, start_progress: request.total > 10)
671
+ end
672
+ end
673
+ )
674
+ end
675
+ end
676
+
588
677
  when "textDocument/didChange"
589
678
  if path = pathname(message[:params][:textDocument][:uri])
590
679
  broadcast_notification(message)
591
680
  controller.push_changes(path)
592
- end
593
681
 
594
- when "textDocument/didSave"
595
- if path = pathname(message[:params][:textDocument][:uri])
596
682
  if typecheck_automatically
597
- if request = controller.make_request(last_request: current_type_check_request)
598
- start_type_check(
599
- request,
600
- last_request: current_type_check_request,
601
- start_progress: request.total > 10
683
+ start_type_checking_queue.execute do
684
+ job_queue.push(
685
+ -> do
686
+ last_request = current_type_check_request
687
+ if request = controller.make_request(last_request: last_request)
688
+ start_type_check(request, last_request: last_request, start_progress: request.total > 10)
689
+ end
690
+ end
602
691
  )
603
692
  end
604
693
  end
605
694
  end
606
695
 
607
696
  when "textDocument/didOpen"
608
- if path = pathname(message[:params][:textDocument][:uri])
697
+ uri = message[:params][:textDocument][:uri]
698
+ text = message[:params][:textDocument][:text]
699
+
700
+ if path = pathname(uri)
609
701
  controller.update_priority(open: path)
702
+ broadcast_notification({
703
+ method: "$/file/reset",
704
+ params: { uri: uri, content: text }
705
+ })
610
706
  end
611
707
 
612
708
  when "textDocument/didClose"
@@ -70,8 +70,15 @@ module Steep
70
70
  when "initialize"
71
71
  load_files(project: project, commandline_args: commandline_args)
72
72
  writer.write({ id: request[:id], result: nil})
73
+
73
74
  when "textDocument/didChange"
74
75
  collect_changes(request)
76
+
77
+ when "$/file/reset"
78
+ uri = request[:params][:uri]
79
+ text = request[:params][:content]
80
+ reset_change(uri: uri, text: text)
81
+
75
82
  when "workspace/symbol"
76
83
  query = request[:params][:query]
77
84
  queue << WorkspaceSymbolJob.new(id: request[:id], query: query)
@@ -165,7 +172,7 @@ module Steep
165
172
  writer.write(
166
173
  method: :"textDocument/publishDiagnostics",
167
174
  params: LSP::Interface::PublishDiagnosticsParams.new(
168
- uri: Steep::PathHelper.to_uri(job.path),
175
+ uri: Steep::PathHelper.to_uri(job.path).to_s,
169
176
  diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq
170
177
  )
171
178
  )
@@ -183,7 +190,7 @@ module Steep
183
190
  writer.write(
184
191
  method: :"textDocument/publishDiagnostics",
185
192
  params: LSP::Interface::PublishDiagnosticsParams.new(
186
- uri: Steep::PathHelper.to_uri(job.path),
193
+ uri: Steep::PathHelper.to_uri(job.path).to_s,
187
194
  diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
188
195
  )
189
196
  )
@@ -202,7 +209,7 @@ module Steep
202
209
  writer.write(
203
210
  method: :"textDocument/publishDiagnostics",
204
211
  params: LSP::Interface::PublishDiagnosticsParams.new(
205
- uri: Steep::PathHelper.to_uri(job.path),
212
+ uri: Steep::PathHelper.to_uri(job.path).to_s,
206
213
  diagnostics: diagnostics.map {|diagnostic| formatter.format(diagnostic) }.uniq.compact
207
214
  )
208
215
  )
@@ -115,7 +115,7 @@ module Steep
115
115
  when RBS::Environment::ClassAliasEntry, RBS::Environment::ModuleAliasEntry
116
116
  entry.decl
117
117
  else
118
- raise
118
+ raise "absolute_type_name=#{absolute_type_name}, relative_type_name=#{relative_type_name}"
119
119
  end
120
120
  else
121
121
  raise
@@ -663,7 +663,7 @@ module Steep
663
663
  if parent
664
664
  case parent.type
665
665
  when :const
666
- const_name = typing.source_index.reference(constant_node: parent)
666
+ const_name = typing.source_index.reference(constant_node: parent) or raise "Unknown node in source_index: #{parent}"
667
667
  consts = context.type_env.constant_env.children(const_name)
668
668
  end
669
669
  else
@@ -1,7 +1,7 @@
1
1
  module Steep
2
2
  module Services
3
3
  class StatsCalculator
4
- SuccessStats = Struct.new(:target, :path, :typed_calls_count, :untyped_calls_count, :error_calls_count, keyword_init: true) do
4
+ class SuccessStats < Struct.new(:target, :path, :typed_calls_count, :untyped_calls_count, :error_calls_count, keyword_init: true)
5
5
  def as_json
6
6
  {
7
7
  type: "success",
@@ -14,7 +14,7 @@ module Steep
14
14
  }
15
15
  end
16
16
  end
17
- ErrorStats = Struct.new(:target, :path, keyword_init: true) do
17
+ class ErrorStats < Struct.new(:target, :path, keyword_init: true)
18
18
  def as_json
19
19
  {
20
20
  type: "error",
@@ -31,15 +31,20 @@ module Steep
31
31
 
32
32
  case prefix
33
33
  when /\A((::\w+[A-Z])+(::)?)/
34
- NamespacePrefix.new(RBS::Namespace.parse($1.reverse), $1.size)
34
+ namespace = $1 or raise
35
+ NamespacePrefix.new(RBS::Namespace.parse(namespace.reverse), namespace.size)
35
36
  when /\A::/
36
37
  NamespacePrefix.new(RBS::Namespace.root, 2)
37
38
  when /\A(\w*[A-Za-z_])((::\w+[A-Z])+(::)?)/
38
- NamespacedIdentPrefix.new(RBS::Namespace.parse($2.reverse), $1.reverse, $1.size + $2.size)
39
+ namespace = $1 or raise
40
+ identifier = $2 or raise
41
+ NamespacedIdentPrefix.new(RBS::Namespace.parse(identifier.reverse), namespace.reverse, namespace.size + identifier.size)
39
42
  when /\A(\w*[A-Za-z_])::/
40
- NamespacedIdentPrefix.new(RBS::Namespace.root, $1.reverse, $1.size + 2)
43
+ namespace = $1 or raise
44
+ NamespacedIdentPrefix.new(RBS::Namespace.root, namespace.reverse, namespace.size + 2)
41
45
  when /\A(\w*[A-Za-z_])/
42
- RawIdentPrefix.new($1.reverse)
46
+ identifier = $1 or raise
47
+ RawIdentPrefix.new(identifier.reverse)
43
48
  end
44
49
  end
45
50
  end
@@ -92,36 +97,97 @@ module Steep
92
97
  if block
93
98
  env = self.env
94
99
 
100
+ table = {} #: Hash[RBS::Namespace, Array[RBS::TypeName]]
101
+ env.class_decls.each_key do |type_name|
102
+ yield(type_name)
103
+ (table[type_name.namespace] ||= []) << type_name
104
+ end
105
+ env.type_alias_decls.each_key do |type_name|
106
+ yield(type_name)
107
+ (table[type_name.namespace] ||= []) << type_name
108
+ end
109
+ env.interface_decls.each_key do |type_name|
110
+ yield(type_name)
111
+ (table[type_name.namespace] ||= []) << type_name
112
+ end
113
+ env.class_alias_decls.each_key do |type_name|
114
+ yield(type_name)
115
+ (table[type_name.namespace] ||= []) << type_name
116
+ end
117
+
118
+ env.class_alias_decls.each_key do |alias_name|
119
+ normalized_name = env.normalize_module_name?(alias_name) or next
120
+ each_type_name_under(alias_name, normalized_name, table: table, &block)
121
+ end
122
+
123
+ resolve_pairs = [] #: Array[[RBS::TypeName, RBS::TypeName]]
124
+
95
125
  map.instance_eval do
96
126
  @map.each_key do |name|
97
127
  relative_name = RBS::TypeName.new(name: name, namespace: RBS::Namespace.empty)
98
128
  if absolute_name = resolve?(relative_name)
99
129
  if env.type_name?(absolute_name)
100
130
  # Yields only if the relative type name resolves to existing absolute type name
101
- yield relative_name
131
+ resolve_pairs << [relative_name, absolute_name]
102
132
  end
103
133
  end
104
134
  end
105
135
  end
106
- env.class_decls.each_key(&block)
107
- env.class_alias_decls.each_key(&block)
108
- env.type_alias_decls.each_key(&block)
109
- env.interface_decls.each_key(&block)
136
+
137
+ resolve_pairs.each do |use_name, absolute_name|
138
+ yield use_name
139
+ each_type_name_under(use_name, absolute_name, table: table, &block)
140
+ end
110
141
  else
111
142
  enum_for :each_type_name
112
143
  end
113
144
  end
114
145
 
146
+ def each_type_name_under(module_name, normalized_name, table:, &block)
147
+ if children = table.fetch(normalized_name.to_namespace, nil)
148
+ module_namespace = module_name.to_namespace
149
+
150
+ children.each do |normalized_child_name|
151
+ child_name = RBS::TypeName.new(namespace: module_namespace, name: normalized_child_name.name)
152
+
153
+ yield child_name
154
+
155
+ if normalized_child_name.class?
156
+ each_type_name_under(child_name, env.normalize_module_name(normalized_child_name), table: table, &block)
157
+ end
158
+ end
159
+ end
160
+ end
161
+
162
+ def resolve_used_name(name)
163
+ return nil if name.absolute?
164
+
165
+ case
166
+ when resolved = map.resolve?(name)
167
+ resolved
168
+ when name.namespace.empty?
169
+ nil
170
+ else
171
+ if resolved_parent = resolve_used_name(name.namespace.to_type_name)
172
+ resolved_name = RBS::TypeName.new(namespace: resolved_parent.to_namespace, name: name.name)
173
+ if env.normalize_type_name?(resolved_name)
174
+ resolved_name
175
+ end
176
+ end
177
+ end
178
+ end
179
+
115
180
  def resolve_name_in_context(name)
116
- if resolved_name = map.resolve?(name)
181
+ if resolved_name = resolve_used_name(name)
117
182
  return [resolved_name, name]
118
183
  end
119
184
 
120
185
  name.absolute? or raise
186
+ normalized_name = env.normalize_type_name?(name) or raise "Cannot normalize given type name `#{name}`"
121
187
 
122
188
  name.namespace.path.reverse_each.inject(RBS::TypeName.new(namespace: RBS::Namespace.empty, name: name.name)) do |relative_name, component|
123
189
  if type_name_resolver.resolve(relative_name, context: context) == name
124
- return [name, relative_name]
190
+ return [normalized_name, relative_name]
125
191
  end
126
192
 
127
193
  RBS::TypeName.new(
@@ -130,10 +196,10 @@ module Steep
130
196
  )
131
197
  end
132
198
 
133
- if type_name_resolver.resolve(name.relative!, context: context) == name && !map.resolve?(name.relative!)
134
- [name, name.relative!]
199
+ if type_name_resolver.resolve(name.relative!, context: context) == name && !resolve_used_name(name.relative!)
200
+ [normalized_name, name.relative!]
135
201
  else
136
- [name, name]
202
+ [normalized_name, name]
137
203
  end
138
204
  end
139
205
 
@@ -144,7 +210,12 @@ module Steep
144
210
  type_name.split.any? {|sym| sym.to_s.downcase.include?(prefix.ident.downcase) }
145
211
  end
146
212
  when Prefix::NamespacedIdentPrefix
147
- absolute_namespace = type_name_resolver.resolve(prefix.namespace.to_type_name, context: context)&.to_namespace || prefix.namespace
213
+ absolute_namespace =
214
+ if prefix.namespace.empty?
215
+ RBS::Namespace.root
216
+ else
217
+ type_name_resolver.resolve(prefix.namespace.to_type_name, context: context)&.to_namespace || prefix.namespace
218
+ end
148
219
 
149
220
  each_type_name.filter do|name|
150
221
  name.namespace == absolute_namespace &&
@@ -112,10 +112,11 @@ module Steep
112
112
  type.args
113
113
  ]
114
114
  when RBS::Types::Alias
115
- entry = env.type_alias_decls[type.name]
115
+ type_name = env.normalize_type_name?(type.name) or return
116
+ entry = env.type_alias_decls[type_name]
116
117
 
117
118
  [
118
- type.name,
119
+ type_name,
119
120
  entry.decl.type_params,
120
121
  type.args
121
122
  ]
@@ -520,6 +521,12 @@ module Steep
520
521
  def validate_one_alias(name, entry = env.type_alias_decls[name])
521
522
  rescue_validation_errors(name) do
522
523
  Steep.logger.debug "Validating alias `#{name}`..."
524
+
525
+ unless name.namespace.empty?
526
+ outer = name.namespace.to_type_name
527
+ builder.validate_type_name(outer, entry.decl.location&.aref(:name))
528
+ end
529
+
523
530
  upper_bounds = entry.decl.type_params.each.with_object({}) do |param, bounds|
524
531
  bounds[param.name] = factory.type_opt(param.upper_bound)
525
532
  end
@@ -79,11 +79,11 @@ module Steep
79
79
  end
80
80
 
81
81
  def instance_type
82
- @instance_type
82
+ @instance_type || AST::Types::Instance.instance
83
83
  end
84
84
 
85
85
  def class_type
86
- @class_type
86
+ @class_type || AST::Types::Class.instance
87
87
  end
88
88
 
89
89
  def constraints
@@ -193,7 +193,7 @@ module Steep
193
193
  bounds = cache_bounds(relation)
194
194
  fvs = relation.sub_type.free_variables + relation.super_type.free_variables
195
195
  cached = cache[relation, @self_type, @instance_type, @class_type, bounds]
196
- if cached && fvs.none? {|var| constraints.unknown?(var) }
196
+ if cached && fvs.none? {|var| var.is_a?(Symbol) && constraints.unknown?(var) }
197
197
  cached
198
198
  else
199
199
  if assumptions.member?(relation)
@@ -212,7 +212,8 @@ module Steep
212
212
 
213
213
  def cache_bounds(relation)
214
214
  vars = relation.sub_type.free_variables + relation.super_type.free_variables
215
- vars.each.with_object({}) do |var, hash|
215
+ vars.each.with_object({}) do |var, hash| #$ Hash[Symbol, AST::Types::t]
216
+ next unless var.is_a?(Symbol)
216
217
  if upper_bound = variable_upper_bound(var)
217
218
  hash[var] = upper_bound
218
219
  end
@@ -232,7 +233,7 @@ module Steep
232
233
  when AST::Types::Literal
233
234
  type.value == true
234
235
  else
235
- AST::Builtin::TrueClass.instance_type?(type)
236
+ AST::Builtin::TrueClass.instance_type?(type) ? true : false
236
237
  end
237
238
  end
238
239
 
@@ -241,7 +242,7 @@ module Steep
241
242
  when AST::Types::Literal
242
243
  type.value == false
243
244
  else
244
- AST::Builtin::FalseClass.instance_type?(type)
245
+ AST::Builtin::FalseClass.instance_type?(type) ? true : false
245
246
  end
246
247
  end
247
248
 
@@ -410,7 +411,7 @@ module Steep
410
411
  class_type: class_type,
411
412
  variable_bounds: variable_upper_bounds
412
413
  )
413
- ) or raise
414
+ ) or return Failure(relation, Result::Failure::UnknownPairError.new(relation: relation))
414
415
  }
415
416
  )
416
417
  end
@@ -492,7 +493,7 @@ module Steep
492
493
  Failure(relation, Result::Failure::UnknownPairError.new(relation: relation))
493
494
  end
494
495
 
495
- when relation.sub_type.is_a?(AST::Types::Tuple) && AST::Builtin::Array.instance_type?(relation.super_type)
496
+ when relation.sub_type.is_a?(AST::Types::Tuple) && (super_type = AST::Builtin::Array.instance_type?(relation.super_type))
496
497
  Expand(relation) do
497
498
  tuple_element_type =
498
499
  AST::Types::Union.build(
@@ -500,7 +501,7 @@ module Steep
500
501
  location: relation.sub_type.location
501
502
  )
502
503
 
503
- check_type(Relation.new(sub_type: tuple_element_type, super_type: relation.super_type.args[0]))
504
+ check_type(Relation.new(sub_type: tuple_element_type, super_type: super_type.args[0]))
504
505
  end
505
506
 
506
507
  when relation.sub_type.is_a?(AST::Types::Record) && relation.super_type.is_a?(AST::Types::Record)
@@ -549,9 +550,7 @@ module Steep
549
550
  end
550
551
 
551
552
  when relation.super_type.is_a?(AST::Types::Nil) && AST::Builtin::NilClass.instance_type?(relation.sub_type)
552
- Success(relation)
553
-
554
- when relation.sub_type.is_a?(AST::Types::Nil) && AST::Builtin::NilClass.instance_type?(relation.super_type)
553
+ # NilClass <: nil
555
554
  Success(relation)
556
555
 
557
556
  when relation.sub_type.is_a?(AST::Types::Literal)
@@ -742,10 +741,17 @@ module Steep
742
741
  args = sub_type.type_params.map {|type_param| AST::Types::Var.fresh(type_param.name) }
743
742
  args.each {|arg| constraints.unknown!(arg.name) }
744
743
 
745
- upper_bounds = {}
746
- relations = [] #: Array[Relation]
744
+ upper_bounds = {} #: Hash[Symbol, AST::Types::t]
745
+ relations = [] #: Array[Relation[AST::Types::t]]
747
746
 
748
747
  args.zip(sub_type.type_params, super_type.type_params).each do |arg, sub_param, sup_param|
748
+ # @type var arg: AST::Types::Var
749
+ # @type var sub_param: Interface::TypeParam?
750
+ # @type var super_param: Interface::TypeParam?
751
+
752
+ sub_param or raise
753
+ sup_param or raise
754
+
749
755
  sub_ub = sub_param.upper_bound
750
756
  sup_ub = sup_param.upper_bound
751
757
 
@@ -927,7 +933,7 @@ module Steep
927
933
 
928
934
  sub_params, super_params = relation
929
935
 
930
- pairs = []
936
+ pairs = [] #: Array[[AST::Types::t, AST::Types::t]]
931
937
 
932
938
  sub_flat = sub_params.flat_unnamed_params
933
939
  sup_flat = super_params.flat_unnamed_params
@@ -939,7 +945,7 @@ module Steep
939
945
  return failure unless sub_params.rest
940
946
 
941
947
  while sub_flat.size > 0
942
- sub_type = sub_flat.shift
948
+ sub_type = sub_flat.shift or raise
943
949
  sup_type = sup_flat.shift
944
950
 
945
951
  if sup_type
@@ -955,7 +961,7 @@ module Steep
955
961
 
956
962
  when sub_params.rest
957
963
  while sub_flat.size > 0
958
- sub_type = sub_flat.shift
964
+ sub_type = sub_flat.shift or raise
959
965
  sup_type = sup_flat.shift
960
966
 
961
967
  if sup_type
@@ -972,7 +978,7 @@ module Steep
972
978
  end
973
979
  when sub_params.required.size + sub_params.optional.size >= super_params.required.size + super_params.optional.size
974
980
  while sub_flat.size > 0
975
- sub_type = sub_flat.shift
981
+ sub_type = sub_flat.shift or raise
976
982
  sup_type = sup_flat.shift
977
983
 
978
984
  if sup_type