steep 1.0.0 → 1.1.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby-windows.yml +34 -0
  3. data/.github/workflows/ruby.yml +7 -2
  4. data/.gitignore +1 -0
  5. data/CHANGELOG.md +59 -0
  6. data/Gemfile +7 -4
  7. data/Gemfile.lock +17 -21
  8. data/Gemfile.steep +3 -0
  9. data/Gemfile.steep.lock +49 -0
  10. data/Rakefile +5 -0
  11. data/Steepfile +6 -1
  12. data/bin/setup +2 -0
  13. data/bin/steep +19 -0
  14. data/lib/steep/ast/builtin.rb +2 -2
  15. data/lib/steep/ast/types/factory.rb +7 -3
  16. data/lib/steep/ast/types/proc.rb +2 -0
  17. data/lib/steep/cli.rb +3 -1
  18. data/lib/steep/diagnostic/ruby.rb +50 -4
  19. data/lib/steep/diagnostic/signature.rb +18 -0
  20. data/lib/steep/drivers/check.rb +3 -3
  21. data/lib/steep/drivers/watch.rb +3 -1
  22. data/lib/steep/method_name.rb +9 -3
  23. data/lib/steep/node_helper.rb +49 -0
  24. data/lib/steep/path_helper.rb +22 -0
  25. data/lib/steep/project.rb +3 -15
  26. data/lib/steep/server/base_worker.rb +1 -0
  27. data/lib/steep/server/change_buffer.rb +1 -1
  28. data/lib/steep/server/interaction_worker.rb +3 -5
  29. data/lib/steep/server/master.rb +61 -45
  30. data/lib/steep/server/type_check_worker.rb +10 -25
  31. data/lib/steep/services/completion_provider.rb +25 -18
  32. data/lib/steep/services/goto_service.rb +2 -4
  33. data/lib/steep/services/hover_provider/rbs.rb +1 -1
  34. data/lib/steep/services/hover_provider/ruby.rb +30 -12
  35. data/lib/steep/services/stats_calculator.rb +0 -1
  36. data/lib/steep/services/type_check_service.rb +15 -12
  37. data/lib/steep/shims/symbol_start_with.rb +18 -0
  38. data/lib/steep/signature/validator.rb +25 -1
  39. data/lib/steep/source.rb +1 -1
  40. data/lib/steep/subtyping/check.rb +0 -3
  41. data/lib/steep/subtyping/constraints.rb +43 -14
  42. data/lib/steep/type_construction.rb +721 -764
  43. data/lib/steep/type_inference/constant_env.rb +0 -2
  44. data/lib/steep/type_inference/context.rb +23 -17
  45. data/lib/steep/type_inference/logic_type_interpreter.rb +210 -117
  46. data/lib/steep/type_inference/method_call.rb +80 -6
  47. data/lib/steep/type_inference/multiple_assignment.rb +189 -0
  48. data/lib/steep/type_inference/send_args.rb +1 -2
  49. data/lib/steep/type_inference/type_env.rb +273 -116
  50. data/lib/steep/type_inference/type_env_builder.rb +138 -0
  51. data/lib/steep/typing.rb +2 -0
  52. data/lib/steep/version.rb +1 -1
  53. data/lib/steep.rb +7 -5
  54. data/rbs_collection.steep.lock.yaml +112 -0
  55. data/rbs_collection.steep.yaml +19 -0
  56. data/sample/sig/conference.rbs +8 -0
  57. data/sig/shims/parser/source/map.rbs +146 -0
  58. data/sig/shims/parser/source/range.rbs +237 -0
  59. data/sig/shims/parser.rbs +17 -0
  60. data/sig/steep/ast/annotation/collection.rbs +75 -0
  61. data/sig/steep/ast/annotation.rbs +126 -0
  62. data/sig/steep/ast/builtin.rbs +69 -0
  63. data/sig/steep/ast/type_params.rbs +11 -0
  64. data/sig/steep/ast/types/any.rbs +29 -0
  65. data/sig/steep/ast/types/boolean.rbs +31 -0
  66. data/sig/steep/ast/types/bot.rbs +29 -0
  67. data/sig/steep/ast/types/class.rbs +29 -0
  68. data/sig/steep/ast/types/factory.rbs +76 -0
  69. data/sig/steep/ast/types/helper.rbs +19 -0
  70. data/sig/steep/ast/types/instance.rbs +29 -0
  71. data/sig/steep/ast/types/intersection.rbs +35 -0
  72. data/sig/steep/ast/types/literal.rbs +33 -0
  73. data/sig/steep/ast/types/logic.rbs +78 -0
  74. data/sig/steep/ast/types/name.rbs +71 -0
  75. data/sig/steep/ast/types/nil.rbs +31 -0
  76. data/sig/steep/ast/types/proc.rbs +46 -0
  77. data/sig/steep/ast/types/record.rbs +38 -0
  78. data/sig/steep/ast/types/self.rbs +29 -0
  79. data/sig/steep/ast/types/top.rbs +29 -0
  80. data/sig/steep/ast/types/tuple.rbs +34 -0
  81. data/sig/steep/ast/types/union.rbs +38 -0
  82. data/sig/steep/ast/types/var.rbs +37 -0
  83. data/sig/steep/ast/types/void.rbs +29 -0
  84. data/sig/steep/ast/types.rbs +37 -0
  85. data/sig/steep/diagnostic/deprecated/unknown_constant_assigned.rbs +15 -0
  86. data/sig/steep/diagnostic/helper.rbs +9 -0
  87. data/sig/steep/diagnostic/lsp_formatter.rbs +29 -0
  88. data/sig/steep/diagnostic/ruby.rbs +494 -0
  89. data/sig/steep/diagnostic/signature.rbs +215 -0
  90. data/sig/steep/interface/block.rbs +35 -0
  91. data/sig/steep/interface/function.rbs +253 -0
  92. data/sig/steep/interface/interface.rbs +23 -0
  93. data/sig/steep/interface/method_type.rbs +55 -0
  94. data/sig/steep/interface/substitution.rbs +53 -0
  95. data/sig/steep/interface/type_param.rbs +35 -0
  96. data/sig/steep/method_name.rbs +26 -0
  97. data/sig/steep/module_helper.rbs +7 -0
  98. data/sig/steep/node_helper.rbs +11 -0
  99. data/sig/steep/project/dsl.rbs +94 -0
  100. data/sig/steep/project/options.rbs +15 -0
  101. data/sig/steep/project/pattern.rbs +25 -0
  102. data/sig/steep/project/target.rbs +25 -0
  103. data/sig/steep/project.rbs +19 -0
  104. data/sig/steep/services/completion_provider.rbs +123 -0
  105. data/sig/steep/services/content_change.rbs +35 -0
  106. data/sig/steep/services/file_loader.rbs +13 -0
  107. data/sig/steep/services/goto_service.rbs +45 -0
  108. data/sig/steep/services/hover_provider/rbs.rbs +21 -0
  109. data/sig/steep/services/hover_provider/ruby.rbs +109 -0
  110. data/sig/steep/services/hover_provider/singleton_methods.rbs +11 -0
  111. data/sig/steep/services/path_assignment.rbs +21 -0
  112. data/sig/steep/services/signature_service.rbs +91 -0
  113. data/sig/steep/services/stats_calculator.rbs +17 -0
  114. data/sig/steep/services/type_check_service.rbs +93 -0
  115. data/sig/steep/source.rbs +55 -0
  116. data/sig/steep/subtyping/cache.rbs +17 -0
  117. data/sig/steep/subtyping/check.rbs +93 -0
  118. data/sig/steep/subtyping/constraints.rbs +111 -0
  119. data/sig/steep/subtyping/relation.rbs +51 -0
  120. data/sig/steep/subtyping/result.rbs +157 -0
  121. data/sig/steep/subtyping/variable_variance.rbs +23 -0
  122. data/sig/steep/type_construction.rbs +285 -0
  123. data/sig/steep/type_inference/block_params.rbs +52 -0
  124. data/sig/steep/type_inference/constant_env.rbs +27 -0
  125. data/sig/steep/type_inference/context.rbs +137 -0
  126. data/sig/steep/type_inference/logic_type_interpreter.rbs +72 -0
  127. data/sig/steep/type_inference/method_call.rbs +124 -0
  128. data/sig/steep/type_inference/method_params.rbs +104 -0
  129. data/sig/steep/type_inference/multiple_assignment.rbs +76 -0
  130. data/sig/steep/type_inference/type_env.rbs +158 -0
  131. data/sig/steep/type_inference/type_env_builder.rbs +77 -0
  132. data/sig/steep/typing.rbs +68 -0
  133. data/sig/steep.rbs +31 -0
  134. data/smoke/class/f.rb +1 -0
  135. data/smoke/class/test_expectations.yml +2 -2
  136. data/smoke/diagnostics/test_expectations.yml +4 -2
  137. data/smoke/regression/lambda.rb +3 -0
  138. data/smoke/regression/test_expectations.yml +12 -0
  139. data/steep.gemspec +1 -1
  140. metadata +95 -9
  141. data/lib/steep/subtyping/variable_occurrence.rb +0 -51
  142. data/lib/steep/type_inference/local_variable_type_env.rb +0 -249
  143. data/lib/steep/type_inference/logic.rb +0 -161
@@ -30,6 +30,13 @@ module Steep
30
30
  end
31
31
  end
32
32
 
33
+ include NodeHelper
34
+
35
+ def inspect
36
+ s = "#<%s:%#018x " % [self.class, object_id]
37
+ s + ">"
38
+ end
39
+
33
40
  include ModuleHelper
34
41
 
35
42
  attr_reader :checker
@@ -59,10 +66,6 @@ module Steep
59
66
  context.self_type
60
67
  end
61
68
 
62
- def type_env
63
- context.type_env
64
- end
65
-
66
69
  def variable_context
67
70
  context.variable_context
68
71
  end
@@ -85,9 +88,9 @@ module Steep
85
88
  )
86
89
  end
87
90
 
88
- def with_updated_context(lvar_env: self.context.lvar_env)
89
- if lvar_env != self.context.lvar_env
90
- with(context: self.context.with(lvar_env: lvar_env))
91
+ def with_updated_context(type_env: self.context.type_env)
92
+ unless type_env.equal?(self.context.type_env)
93
+ with(context: self.context.with(type_env: type_env))
91
94
  else
92
95
  self
93
96
  end
@@ -111,8 +114,8 @@ module Steep
111
114
  with(context: yield(self.context))
112
115
  end
113
116
 
114
- def update_lvar_env
115
- with_updated_context(lvar_env: yield(context.lvar_env))
117
+ def update_type_env
118
+ with_updated_context(type_env: yield(context.type_env))
116
119
  end
117
120
 
118
121
  def check_relation(sub_type:, super_type:, constraints: Subtyping::Constraints.empty)
@@ -129,14 +132,15 @@ module Steep
129
132
  end
130
133
  end
131
134
 
132
- def for_new_method(method_name, node, args:, self_type:, definition:)
133
- annots = source.annotations(block: node, factory: checker.factory, context: nesting)
134
- type_env = TypeInference::TypeEnv.new(subtyping: checker, const_env: module_context&.const_env || self.type_env.const_env)
135
-
136
- self.type_env.const_types.each do |name, type|
137
- type_env.set(const: name, type: type)
135
+ def no_subtyping?(sub_type:, super_type:, constraints: Subtyping::Constraints.empty)
136
+ result = check_relation(sub_type: sub_type, super_type: super_type, constraints: constraints)
137
+ if result.failure?
138
+ result
138
139
  end
140
+ end
139
141
 
142
+ def for_new_method(method_name, node, args:, self_type:, definition:)
143
+ annots = source.annotations(block: node, factory: checker.factory, context: nesting)
140
144
  definition_method_type = if definition
141
145
  definition.methods[method_name]&.yield_self do |method|
142
146
  method.method_types
@@ -189,27 +193,6 @@ module Steep
189
193
  super_method: super_method
190
194
  )
191
195
 
192
- if definition
193
- definition.instance_variables.each do |name, decl|
194
- type_env.set(ivar: name, type: checker.factory.type(decl.type))
195
- end
196
- end
197
-
198
- type_env = type_env.with_annotations(
199
- ivar_types: annots.ivar_types,
200
- const_types: annots.const_types,
201
- self_type: annots.self_type || self_type,
202
- instance_type: module_context.instance_type,
203
- class_type: module_context.module_type
204
- )
205
-
206
- lvar_env = TypeInference::LocalVariableTypeEnv.empty(
207
- subtyping: checker,
208
- self_type: annots.self_type || self_type,
209
- instance_type: module_context.instance_type,
210
- class_type: module_context.module_type
211
- )
212
-
213
196
  method_params =
214
197
  if method_type
215
198
  TypeInference::MethodParams.build(node: node, method_type: method_type)
@@ -217,18 +200,33 @@ module Steep
217
200
  TypeInference::MethodParams.empty(node: node)
218
201
  end
219
202
 
220
- method_params.each_param do |param|
221
- lvar_env = lvar_env.assign(param.name, type: param.var_type, node: param.node) {
222
- raise "Unexpected assignment error: #{param.name}"
223
- }
203
+ local_variable_types = method_params.each_param.with_object({}) do |param, hash|
204
+ if param.name
205
+ hash[param.name] = param.var_type
206
+ end
224
207
  end
208
+ type_env = context.type_env.assign_local_variables(local_variable_types)
209
+
210
+ type_env = TypeInference::TypeEnvBuilder.new(
211
+ TypeInference::TypeEnvBuilder::Command::ImportLocalVariableAnnotations.new(annots).merge!.on_duplicate! do |name, original, annotated|
212
+ param = method_params.each_param.find {|param| param.name == name }
213
+ if result = no_subtyping?(sub_type: original, super_type: annotated)
214
+ typing.add_error Diagnostic::Ruby::IncompatibleAnnotation.new(
215
+ node: param.node,
216
+ var_name: name,
217
+ result: result,
218
+ relation: result.relation
219
+ )
220
+ end
221
+ end,
222
+ TypeInference::TypeEnvBuilder::Command::ImportInstanceVariableDefinition.new(definition, checker.factory),
223
+ TypeInference::TypeEnvBuilder::Command::ImportInstanceVariableAnnotations.new(annots).merge!
224
+ ).build(type_env)
225
225
 
226
226
  method_params.errors.each do |error|
227
227
  typing.add_error error
228
228
  end
229
229
 
230
- lvar_env = lvar_env.annotate(annots)
231
-
232
230
  call_context = case self_type
233
231
  when nil
234
232
  TypeInference::MethodCall::UnknownContext.new()
@@ -255,7 +253,6 @@ module Steep
255
253
  break_context: nil,
256
254
  self_type: annots.self_type || self_type,
257
255
  type_env: type_env,
258
- lvar_env: lvar_env,
259
256
  call_context: call_context,
260
257
  variable_context: variable_context
261
258
  ),
@@ -295,9 +292,9 @@ module Steep
295
292
  end
296
293
  end
297
294
 
298
- def default_module_context(implement_module_name, const_env:)
295
+ def default_module_context(implement_module_name, nesting:)
299
296
  if implement_module_name
300
- module_name = checker.factory.absolute_type_name(implement_module_name.name, context: const_env.context)
297
+ module_name = checker.factory.absolute_type_name(implement_module_name.name, context: nesting)
301
298
  module_args = implement_module_name.args.map {|name| AST::Types::Var.new(name: name) }
302
299
 
303
300
  instance_def = checker.factory.definition_builder.build_instance(module_name)
@@ -310,7 +307,7 @@ module Steep
310
307
  instance_type: instance_type,
311
308
  module_type: module_type,
312
309
  implement_name: implement_module_name,
313
- const_env: const_env,
310
+ nesting: nesting,
314
311
  class_name: module_name,
315
312
  instance_definition: instance_def,
316
313
  module_definition: module_def
@@ -320,7 +317,7 @@ module Steep
320
317
  instance_type: nil,
321
318
  module_type: nil,
322
319
  implement_name: nil,
323
- const_env: self.module_context.const_env,
320
+ nesting: nesting,
324
321
  class_name: self.module_context.class_name,
325
322
  module_definition: nil,
326
323
  instance_definition: nil
@@ -331,16 +328,10 @@ module Steep
331
328
  def for_module(node, new_module_name)
332
329
  new_nesting = [nesting, new_module_name || false]
333
330
 
334
- module_const_env = TypeInference::ConstantEnv.new(
335
- factory: checker.factory,
336
- context: new_nesting,
337
- resolver: self.module_context.const_env.resolver
338
- )
339
-
340
331
  annots = source.annotations(block: node, factory: checker.factory, context: new_nesting)
341
332
 
342
333
  implement_module_name = implement_module(module_name: new_module_name, annotations: annots)
343
- module_context = default_module_context(implement_module_name, const_env: module_const_env)
334
+ module_context = default_module_context(implement_module_name, nesting: new_nesting)
344
335
 
345
336
  unless implement_module_name
346
337
  module_context = module_context.update(
@@ -391,18 +382,6 @@ module Steep
391
382
  module_context = module_context.update(module_type: annots.self_type)
392
383
  end
393
384
 
394
- module_type_env = TypeInference::TypeEnv.build(annotations: annots,
395
- subtyping: checker,
396
- const_env: module_const_env,
397
- signatures: checker.factory.env)
398
-
399
- lvar_env = TypeInference::LocalVariableTypeEnv.empty(
400
- subtyping: checker,
401
- self_type: module_context.module_type,
402
- instance_type: module_context.instance_type,
403
- class_type: module_context.module_type
404
- ).annotate(annots)
405
-
406
385
  if implement_module_name
407
386
  definition = checker.factory.definition_builder.build_instance(implement_module_name.name)
408
387
  type_params = definition.type_params_decl.map do |param|
@@ -418,6 +397,20 @@ module Steep
418
397
  variable_context = TypeInference::Context::TypeVariableContext.empty
419
398
  end
420
399
 
400
+ module_const_env = TypeInference::ConstantEnv.new(
401
+ factory: checker.factory,
402
+ context: new_nesting,
403
+ resolver: context.type_env.constant_env.resolver
404
+ )
405
+
406
+ module_type_env = TypeInference::TypeEnvBuilder.new(
407
+ TypeInference::TypeEnvBuilder::Command::ImportGlobalDeclarations.new(checker.factory),
408
+ TypeInference::TypeEnvBuilder::Command::ImportLocalVariableAnnotations.new(annots),
409
+ TypeInference::TypeEnvBuilder::Command::ImportInstanceVariableDefinition.new(module_context.module_definition, checker.factory),
410
+ TypeInference::TypeEnvBuilder::Command::ImportInstanceVariableAnnotations.new(annots).merge!,
411
+ TypeInference::TypeEnvBuilder::Command::ImportConstantAnnotations.new(annots)
412
+ ).build(TypeInference::TypeEnv.new(module_const_env))
413
+
421
414
  self.class.new(
422
415
  checker: checker,
423
416
  source: source,
@@ -430,7 +423,6 @@ module Steep
430
423
  module_context: module_context,
431
424
  self_type: module_context.module_type,
432
425
  type_env: module_type_env,
433
- lvar_env: lvar_env,
434
426
  call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name),
435
427
  variable_context: variable_context
436
428
  )
@@ -451,11 +443,11 @@ module Steep
451
443
  class_const_env = TypeInference::ConstantEnv.new(
452
444
  factory: checker.factory,
453
445
  context: new_nesting,
454
- resolver: self.module_context.const_env.resolver
446
+ resolver: context.type_env.constant_env.resolver
455
447
  )
456
448
 
457
449
  implement_module_name = implement_module(module_name: new_class_name, super_name: super_class_name, annotations: annots)
458
- module_context = default_module_context(implement_module_name, const_env: class_const_env)
450
+ module_context = default_module_context(implement_module_name, nesting: new_nesting)
459
451
 
460
452
  if implement_module_name
461
453
  if super_class_name && implement_module_name.name == absolute_name(super_class_name)
@@ -492,17 +484,13 @@ module Steep
492
484
  end
493
485
  variable_context = TypeInference::Context::TypeVariableContext.new(type_params)
494
486
 
495
- class_type_env = TypeInference::TypeEnv.build(annotations: annots,
496
- subtyping: checker,
497
- const_env: class_const_env,
498
- signatures: checker.factory.env)
499
-
500
- lvar_env = TypeInference::LocalVariableTypeEnv.empty(
501
- subtyping: checker,
502
- self_type: module_context.module_type,
503
- instance_type: module_context.instance_type,
504
- class_type: module_context.module_type
505
- ).annotate(annots)
487
+ singleton_definition = checker.factory.definition_builder.build_singleton(module_context.class_name)
488
+ class_type_env = TypeInference::TypeEnvBuilder.new(
489
+ TypeInference::TypeEnvBuilder::Command::ImportGlobalDeclarations.new(checker.factory),
490
+ TypeInference::TypeEnvBuilder::Command::ImportConstantAnnotations.new(annots),
491
+ TypeInference::TypeEnvBuilder::Command::ImportLocalVariableAnnotations.new(annots),
492
+ TypeInference::TypeEnvBuilder::Command::ImportInstanceVariableDefinition.new(singleton_definition, checker.factory),
493
+ ).build(TypeInference::TypeEnv.new(class_const_env))
506
494
 
507
495
  class_body_context = TypeInference::Context.new(
508
496
  method_context: nil,
@@ -511,7 +499,6 @@ module Steep
511
499
  break_context: nil,
512
500
  self_type: module_context.module_type,
513
501
  type_env: class_type_env,
514
- lvar_env: lvar_env,
515
502
  call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name),
516
503
  variable_context: variable_context
517
504
  )
@@ -578,6 +565,8 @@ module Steep
578
565
  when AST::Types::Name::Instance
579
566
  type_name = instance_type.name
580
567
  checker.factory.definition_builder.build_instance(type_name)
568
+ else
569
+ return
581
570
  end
582
571
 
583
572
  module_definition = case module_type
@@ -592,23 +581,20 @@ module Steep
592
581
  instance_type: annots.instance_type || instance_type,
593
582
  module_type: annots.self_type || annots.module_type || module_type,
594
583
  implement_name: nil,
595
- const_env: self.module_context.const_env,
584
+ nesting: nesting,
596
585
  class_name: self.module_context.class_name,
597
586
  module_definition: module_definition,
598
587
  instance_definition: instance_definition
599
588
  )
600
589
 
601
- type_env = TypeInference::TypeEnv.build(annotations: annots,
602
- subtyping: checker,
603
- const_env: self.module_context.const_env,
604
- signatures: checker.factory.env)
605
-
606
- lvar_env = TypeInference::LocalVariableTypeEnv.empty(
607
- subtyping: checker,
608
- self_type: module_context.module_type,
609
- instance_type: module_context.instance_type,
610
- class_type: module_context.module_type
611
- ).annotate(annots)
590
+ singleton_definition = checker.factory.definition_builder.build_singleton(module_context.class_name)
591
+ type_env =
592
+ TypeInference::TypeEnvBuilder.new(
593
+ TypeInference::TypeEnvBuilder::Command::ImportGlobalDeclarations.new(checker.factory),
594
+ TypeInference::TypeEnvBuilder::Command::ImportConstantAnnotations.new(annots),
595
+ TypeInference::TypeEnvBuilder::Command::ImportLocalVariableAnnotations.new(annots),
596
+ TypeInference::TypeEnvBuilder::Command::ImportInstanceVariableDefinition.new(instance_definition, checker.factory)
597
+ ).build(TypeInference::TypeEnv.new(context.type_env.constant_env))
612
598
 
613
599
  body_context = TypeInference::Context.new(
614
600
  method_context: nil,
@@ -617,7 +603,6 @@ module Steep
617
603
  break_context: nil,
618
604
  self_type: module_context.module_type,
619
605
  type_env: type_env,
620
- lvar_env: lvar_env,
621
606
  call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name),
622
607
  variable_context: TypeInference::Context::TypeVariableContext.empty # Assuming `::Class` and `::Module` don't have type params
623
608
  )
@@ -631,39 +616,15 @@ module Steep
631
616
  )
632
617
  end
633
618
 
634
- def for_branch(node, truthy_vars: Set.new, type_case_override: nil, break_context: context.break_context)
619
+ def for_branch(node, break_context: context.break_context)
635
620
  annots = source.annotations(block: node, factory: checker.factory, context: nesting)
636
621
 
637
- lvar_env = context.lvar_env
638
-
639
- unless truthy_vars.empty?
640
- lvar_env = lvar_env.yield_self do |env|
641
- decls = env.declared_types.each.with_object({}) do |(name, entry), hash|
642
- if truthy_vars.include?(name)
643
- hash[name] = entry.update(type: unwrap(entry.type))
644
- else
645
- hash[name] = entry
646
- end
647
- end
648
-
649
- assignments = env.assigned_types.each.with_object({}) do |(name, entry), hash|
650
- if truthy_vars.include?(name)
651
- hash[name] = entry.update(type: unwrap(entry.type))
652
- else
653
- hash[name] = entry
654
- end
655
- end
656
-
657
- env.update(declared_types: decls, assigned_types: assignments)
658
- end
659
- end
660
-
661
- if type_case_override
662
- lvar_env = type_case_override.inject(lvar_env) do |lvar_env, (name, type)|
663
- lvar_env.assign!(name, node: node, type: type) do |declared_type, assigned_type, result|
664
- relation = Subtyping::Relation.new(sub_type: assigned_type, super_type: declared_type)
622
+ type_env = TypeInference::TypeEnvBuilder.new(
623
+ TypeInference::TypeEnvBuilder::Command::ImportLocalVariableAnnotations.new(annots).merge!.on_duplicate! do |name, outer_type, annotation_type|
624
+ relation = Subtyping::Relation.new(sub_type: annotation_type, super_type: outer_type)
625
+ if result = no_subtyping?(sub_type: annotation_type, super_type: outer_type)
665
626
  typing.add_error(
666
- Diagnostic::Ruby::IncompatibleTypeCase.new(
627
+ Diagnostic::Ruby::IncompatibleAnnotation.new(
667
628
  node: node,
668
629
  var_name: name,
669
630
  relation: relation,
@@ -672,53 +633,11 @@ module Steep
672
633
  )
673
634
  end
674
635
  end
675
- end
676
-
677
- lvar_env = lvar_env.annotate(annots) do |var, outer_type, inner_type, result|
678
- relation = Subtyping::Relation.new(sub_type: inner_type, super_type: outer_type)
679
- typing.add_error(
680
- Diagnostic::Ruby::IncompatibleAnnotation.new(
681
- node: node,
682
- var_name: var,
683
- relation: relation,
684
- result: result
685
- )
686
- )
687
- end
688
-
689
- type_env = context.type_env
636
+ ).build(context.type_env)
690
637
 
691
- if type_case_override
692
- type_env = type_env.with_annotations(
693
- self_type: self_type,
694
- instance_type: module_context.instance_type,
695
- class_type: module_context.module_type
696
- )
697
- end
698
-
699
- type_env = type_env.with_annotations(
700
- ivar_types: annots.ivar_types,
701
- const_types: annots.const_types,
702
- gvar_types: {},
703
- self_type: self_type,
704
- instance_type: module_context.instance_type,
705
- class_type: module_context.module_type
706
- ) do |var, relation, result|
707
- typing.add_error(
708
- Diagnostic::Ruby::IncompatibleAnnotation.new(
709
- node: node,
710
- var_name: var,
711
- relation: relation,
712
- result: result
713
- )
714
- )
638
+ update_context do |context|
639
+ context.with(type_env: type_env, break_context: break_context)
715
640
  end
716
-
717
- update_context {|context|
718
- context.with(type_env: type_env,
719
- break_context: break_context,
720
- lvar_env: lvar_env)
721
- }
722
641
  end
723
642
 
724
643
  def add_typing(node, type:, constr: self)
@@ -774,8 +693,7 @@ module Steep
774
693
 
775
694
  when :lvasgn
776
695
  yield_self do
777
- var, rhs = node.children
778
- name = var
696
+ name, rhs = node.children
779
697
 
780
698
  case name
781
699
  when :_, :__any__
@@ -785,42 +703,56 @@ module Steep
785
703
  when :__skip__
786
704
  add_typing(node, type: AST::Builtin.any_type)
787
705
  else
788
- if declared_type = context.lvar_env.declared_types[name]&.type
789
- case hint
790
- when nil
791
- hint = declared_type
792
- else
793
- if check_relation(sub_type: declared_type, super_type: hint).success?
794
- # declared_type is compatible with hint and more specific to hint.
795
- # This typically happens when hint is untyped, top, or void.
796
- hint = declared_type
797
- end
706
+ if enforced_type = context.type_env.enforced_type(name)
707
+ case
708
+ when hint == nil
709
+ hint = enforced_type
710
+ when check_relation(sub_type: enforced_type, super_type: hint).success?
711
+ # enforced_type is compatible with hint and more specific to hint.
712
+ # This typically happens when hint is untyped, top, or void.
713
+ hint = enforced_type
798
714
  end
799
715
  end
800
716
 
801
- rhs_result = synthesize(rhs, hint: hint)
717
+ if rhs
718
+ rhs_type, rhs_constr, rhs_context = synthesize(rhs, hint: hint).to_ary
719
+
720
+ constr = rhs_constr.update_type_env do |type_env|
721
+ var_type = rhs_type
722
+
723
+ if enforced_type = type_env.enforced_type(name)
724
+ if result = no_subtyping?(sub_type: rhs_type, super_type: enforced_type)
725
+ typing.add_error(
726
+ Diagnostic::Ruby::IncompatibleAssignment.new(
727
+ node: node,
728
+ lhs_type: enforced_type,
729
+ rhs_type: rhs_type,
730
+ result: result
731
+ )
732
+ )
802
733
 
803
- constr = rhs_result.constr.update_lvar_env do |lvar_env|
804
- lvar_env.assign(name, node: node, type: rhs_result.type) do |declared_type, actual_type, result|
805
- typing.add_error(
806
- Diagnostic::Ruby::IncompatibleAssignment.new(
807
- node: node,
808
- lhs_type: declared_type,
809
- rhs_type: actual_type,
810
- result: result
811
- )
812
- )
734
+ var_type = enforced_type
735
+ end
736
+
737
+ if rhs_type.is_a?(AST::Types::Any)
738
+ var_type = enforced_type
739
+ end
740
+ end
741
+
742
+ type_env.assign_local_variable(name, var_type, enforced_type)
813
743
  end
814
- end
815
744
 
816
- constr.add_typing(node, type: rhs_result.type)
745
+ constr.add_typing(node, type: rhs_type)
746
+ else
747
+ add_typing(node, type: enforced_type || AST::Builtin.any_type)
748
+ end
817
749
  end
818
750
  end
819
751
 
820
752
  when :lvar
821
753
  yield_self do
822
754
  var = node.children[0]
823
- if (type = context.lvar_env[var])
755
+ if (type = context.type_env[var])
824
756
  add_typing node, type: type
825
757
  else
826
758
  fallback_to_any(node)
@@ -829,17 +761,21 @@ module Steep
829
761
 
830
762
  when :ivasgn
831
763
  name = node.children[0]
832
- value = node.children[1]
764
+ rhs = node.children[1]
765
+
766
+ rhs_type, constr = synthesize(rhs, hint: context.type_env[name])
833
767
 
834
- type_ivasgn(name, value, node)
768
+ constr.ivasgn(node, rhs_type)
835
769
 
836
770
  when :ivar
837
771
  yield_self do
838
772
  name = node.children[0]
839
- type = type_env.get(ivar: name) do
773
+
774
+ if type = context.type_env[name]
775
+ add_typing(node, type: type)
776
+ else
840
777
  fallback_to_any node
841
778
  end
842
- add_typing(node, type: type)
843
779
  end
844
780
 
845
781
  when :send
@@ -860,22 +796,22 @@ module Steep
860
796
 
861
797
  when :csend
862
798
  yield_self do
863
- pair = if self_class?(node)
864
- module_type = expand_alias(module_context.module_type)
865
- type = if module_type.is_a?(AST::Types::Name::Singleton)
866
- AST::Types::Name::Singleton.new(name: module_type.name)
867
- else
868
- module_type
869
- end
870
- add_typing(node, type: type)
871
- else
872
- type_send(node, send_node: node, block_params: nil, block_body: nil, unwrap: true)
873
- end
799
+ send_type, constr =
800
+ if self_class?(node)
801
+ module_type = expand_alias(module_context.module_type)
802
+ type = if module_type.is_a?(AST::Types::Name::Singleton)
803
+ AST::Types::Name::Singleton.new(name: module_type.name)
804
+ else
805
+ module_type
806
+ end
807
+ add_typing(node, type: type).to_ary
808
+ else
809
+ type_send(node, send_node: node, block_params: nil, block_body: nil, unwrap: true).to_ary
810
+ end
874
811
 
875
- lvar_env = context.lvar_env.join(pair.context.lvar_env, context.lvar_env)
876
- add_typing(node,
877
- type: union_type(pair.type, AST::Builtin.nil_type),
878
- constr: pair.constr.with_updated_context(lvar_env: lvar_env))
812
+ constr
813
+ .update_type_env { context.type_env.join(constr.context.type_env, context.type_env) }
814
+ .add_typing(node, type: union_type(send_type, AST::Builtin.nil_type))
879
815
  end
880
816
 
881
817
  when :match_with_lvasgn
@@ -1219,35 +1155,30 @@ module Steep
1219
1155
  value = node.children[0]
1220
1156
 
1221
1157
  if break_context
1222
- if break_type = break_context.break_type
1223
- if value
1224
- check(value, break_type) do |break_type, actual_type, result|
1158
+ break_type = (break_context || raise).break_type
1159
+
1160
+ if value
1161
+ check(value, break_type) do |break_type, actual_type, result|
1162
+ typing.add_error(
1163
+ Diagnostic::Ruby::BreakTypeMismatch.new(
1164
+ node: node,
1165
+ expected: break_type,
1166
+ actual: actual_type,
1167
+ result: result
1168
+ )
1169
+ )
1170
+ end
1171
+ else
1172
+ unless break_type.is_a?(AST::Types::Bot)
1173
+ check_relation(sub_type: AST::Builtin.nil_type, super_type: break_type).else do |result|
1225
1174
  typing.add_error(
1226
- Diagnostic::Ruby::BreakTypeMismatch.new(
1175
+ Diagnostic::Ruby::ImplicitBreakValueMismatch.new(
1227
1176
  node: node,
1228
- expected: break_type,
1229
- actual: actual_type,
1177
+ jump_type: break_type,
1230
1178
  result: result
1231
1179
  )
1232
1180
  )
1233
1181
  end
1234
- else
1235
- unless break_type.is_a?(AST::Types::Bot)
1236
- check_relation(sub_type: AST::Builtin.nil_type, super_type: break_type).else do |result|
1237
- typing.add_error(
1238
- Diagnostic::Ruby::ImplicitBreakValueMismatch.new(
1239
- node: node,
1240
- jump_type: break_type,
1241
- result: result
1242
- )
1243
- )
1244
- end
1245
- end
1246
- end
1247
- else
1248
- if value
1249
- synthesize(value)
1250
- typing.add_error Diagnostic::Ruby::UnexpectedJumpValue.new(node: node)
1251
1182
  end
1252
1183
  end
1253
1184
  else
@@ -1309,7 +1240,7 @@ module Steep
1309
1240
 
1310
1241
  node.children.each do |arg|
1311
1242
  if arg.is_a?(Symbol)
1312
- type = context.lvar_env[arg]
1243
+ type = context.type_env[arg]
1313
1244
 
1314
1245
  if type
1315
1246
  _, constr = add_typing(node, type: type)
@@ -1339,7 +1270,7 @@ module Steep
1339
1270
  when :arg, :kwarg
1340
1271
  yield_self do
1341
1272
  var = node.children[0]
1342
- type = context.lvar_env[var]
1273
+ type = context.type_env[var]
1343
1274
 
1344
1275
  if type
1345
1276
  add_typing(node, type: type)
@@ -1354,33 +1285,33 @@ module Steep
1354
1285
  var = node.children[0]
1355
1286
  rhs = node.children[1]
1356
1287
 
1357
- var_type = context.lvar_env[var]
1358
- node_type, constr = synthesize(rhs, hint: var_type)
1288
+ var_type = context.type_env[var]
1359
1289
 
1360
- type = AST::Types::Union.build(types: [var_type, node_type])
1361
-
1362
- constr_ = constr.update_lvar_env do |env|
1363
- env.assign(var, node: node, type: type) do |declared_type, type, result|
1290
+ if var_type
1291
+ type, constr = check(rhs, var_type) do |expected_type, actual_type, result|
1364
1292
  typing.add_error(
1365
1293
  Diagnostic::Ruby::IncompatibleAssignment.new(
1366
1294
  node: node,
1367
- lhs_type: declared_type,
1368
- rhs_type: type,
1295
+ lhs_type: expected_type,
1296
+ rhs_type: actual_type,
1369
1297
  result: result
1370
1298
  )
1371
1299
  )
1372
1300
  end
1301
+ else
1302
+ type, constr = synthesize(rhs)
1373
1303
  end
1374
1304
 
1375
- add_typing(node, type: type, constr: constr_)
1305
+ constr.add_typing(node, type: type)
1376
1306
  end
1377
1307
 
1378
1308
  when :restarg
1379
1309
  yield_self do
1380
1310
  var = node.children[0]
1381
- type = context.lvar_env[var]
1311
+ type = context.type_env[var]
1312
+
1382
1313
  unless type
1383
- if context&.method_context&.method_type
1314
+ if context.method_context&.method_type
1384
1315
  Steep.logger.error { "Unknown variable: #{node}" }
1385
1316
  end
1386
1317
  typing.add_error Diagnostic::Ruby::FallbackAny.new(node: node)
@@ -1393,9 +1324,9 @@ module Steep
1393
1324
  when :kwrestarg
1394
1325
  yield_self do
1395
1326
  var = node.children[0]
1396
- type = context.lvar_env[var]
1327
+ type = context.type_env[var]
1397
1328
  unless type
1398
- if context&.method_context&.method_type
1329
+ if context.method_context&.method_type
1399
1330
  Steep.logger.error { "Unknown variable: #{node}" }
1400
1331
  end
1401
1332
  typing.add_error Diagnostic::Ruby::FallbackAny.new(node: node)
@@ -1447,7 +1378,8 @@ module Steep
1447
1378
  when :true, :false
1448
1379
  ty = node.type == :true ? AST::Types::Literal.new(value: true) : AST::Types::Literal.new(value: false)
1449
1380
 
1450
- if hint && check_relation(sub_type: ty, super_type: hint).success?
1381
+ if hint && check_relation(sub_type: ty, super_type: hint).success? && !hint.is_a?(AST::Types::Any) && !hint.is_a?(AST::Types::Top)
1382
+
1451
1383
  add_typing(node, type: hint)
1452
1384
  else
1453
1385
  add_typing(node, type: AST::Types::Boolean.new)
@@ -1568,7 +1500,7 @@ module Steep
1568
1500
 
1569
1501
  when :sclass
1570
1502
  yield_self do
1571
- type, constr = synthesize(node.children[0])
1503
+ type, constr = synthesize(node.children[0]).to_ary
1572
1504
 
1573
1505
  with_sclass_constr(node, type) do |constructor|
1574
1506
  unless constructor
@@ -1578,8 +1510,7 @@ module Steep
1578
1510
  message: "sclass receiver must be instance type or singleton type, but type given `#{type}`"
1579
1511
  )
1580
1512
  )
1581
- constr.add_typing(node, type: AST::Builtin.nil_type)
1582
- return
1513
+ return constr.add_typing(node, type: AST::Builtin.nil_type)
1583
1514
  end
1584
1515
 
1585
1516
  constructor.typing.add_context_for_node(node, context: constructor.context)
@@ -1739,137 +1670,152 @@ module Steep
1739
1670
 
1740
1671
  when :and
1741
1672
  yield_self do
1742
- left, right = node.children
1673
+ left_node, right_node = node.children
1743
1674
 
1744
- left_type, constr = synthesize(left, hint: hint, condition: true)
1675
+ left_type, constr, left_context = synthesize(left_node, hint: hint, condition: true).to_ary
1745
1676
 
1746
1677
  interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing)
1747
- truthy_env, falsey_env = interpreter.eval(env: constr.context.lvar_env, type: left_type, node: left)
1678
+ left_truthy_env, left_falsy_env = interpreter.eval(env: left_context.type_env, node: left_node)
1748
1679
 
1749
1680
  if left_type.is_a?(AST::Types::Logic::Env)
1750
1681
  left_type = left_type.type
1751
1682
  end
1752
1683
 
1753
- right_type, constr = constr
1754
- .update_lvar_env { truthy_env }
1755
- .tap {|constr| typing.add_context_for_node(right, context: constr.context) }
1756
- .for_branch(right)
1757
- .synthesize(right, hint: hint, condition: true)
1684
+ right_type, constr, right_context =
1685
+ constr
1686
+ .update_type_env { left_truthy_env }
1687
+ .tap {|constr| typing.add_context_for_node(right_node, context: constr.context) }
1688
+ .for_branch(right_node)
1689
+ .synthesize(right_node, hint: hint, condition: true).to_ary
1758
1690
 
1759
- truthy_env, _ = interpreter.eval(env: constr.context.lvar_env, type: right_type, node: right)
1691
+ right_truthy_env, right_falsy_env = interpreter.eval(env: right_context.type_env, node: right_node)
1760
1692
 
1761
- env = if right_type.is_a?(AST::Types::Bot)
1762
- falsey_env
1763
- else
1764
- context.lvar_env.join(falsey_env, constr.context.lvar_env)
1765
- end
1693
+ env =
1694
+ if right_type.is_a?(AST::Types::Bot)
1695
+ left_falsy_env
1696
+ else
1697
+ context.type_env.join(left_falsy_env, right_context.type_env)
1698
+ end
1766
1699
 
1767
- type = case
1768
- when check_relation(sub_type: left_type, super_type: AST::Types::Boolean.new).success?
1769
- union_type(left_type, right_type)
1770
- else
1771
- union_type(right_type, AST::Builtin.nil_type)
1772
- end
1700
+ type =
1701
+ case
1702
+ when check_relation(sub_type: left_type, super_type: AST::Types::Boolean.new).success?
1703
+ union_type(left_type, right_type)
1704
+ else
1705
+ union_type(right_type, AST::Builtin.nil_type)
1706
+ end
1773
1707
 
1774
- type = AST::Types::Logic::Env.new(truthy: truthy_env, falsy: env, type: type) if condition
1708
+ if condition
1709
+ type = AST::Types::Logic::Env.new(
1710
+ truthy: right_truthy_env,
1711
+ falsy: context.type_env.join(left_falsy_env, right_falsy_env),
1712
+ type: type
1713
+ )
1714
+ end
1775
1715
 
1776
- add_typing(node,
1777
- type: type,
1778
- constr: constr.update_lvar_env { env })
1716
+ constr.update_type_env { env }.add_typing(node, type: type)
1779
1717
  end
1780
1718
 
1781
1719
  when :or
1782
1720
  yield_self do
1783
- left, right = node.children
1721
+ left_node, right_node = node.children
1784
1722
 
1785
- left_type, constr = synthesize(left, hint: hint, condition: true)
1723
+ left_type, constr, left_context = synthesize(left_node, hint: hint, condition: true).to_ary
1786
1724
 
1787
1725
  interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing)
1788
- truthy_env, falsey_env = interpreter.eval(env: constr.context.lvar_env, type: left_type, node: left)
1726
+ left_truthy_env, left_falsy_env = interpreter.eval(env: left_context.type_env, node: left_node)
1789
1727
 
1790
1728
  if left_type.is_a?(AST::Types::Logic::Env)
1791
1729
  left_type = left_type.type
1792
1730
  end
1793
1731
  left_type, _ = checker.factory.unwrap_optional(left_type)
1794
1732
 
1795
- right_type, constr = constr
1796
- .update_lvar_env { falsey_env }
1797
- .tap {|constr| typing.add_context_for_node(right, context: constr.context) }
1798
- .for_branch(right)
1799
- .synthesize(right, hint: left_type, condition: true)
1733
+ right_type, constr, right_context =
1734
+ constr
1735
+ .update_type_env { left_falsy_env }
1736
+ .tap {|constr| typing.add_context_for_node(right_node, context: constr.context) }
1737
+ .for_branch(right_node)
1738
+ .synthesize(right_node, hint: left_type, condition: true).to_ary
1800
1739
 
1801
- _, falsey_env = interpreter.eval(env: falsey_env, type: right_type, node: right)
1740
+ right_truthy_env, right_falsy_env = interpreter.eval(env: left_falsy_env, node: right_node)
1802
1741
 
1803
1742
  env = if right_type.is_a?(AST::Types::Bot)
1804
- truthy_env
1743
+ left_truthy_env
1805
1744
  else
1806
- context.lvar_env.join(truthy_env, constr.context.lvar_env)
1745
+ context.type_env.join(left_truthy_env, right_context.type_env)
1807
1746
  end
1808
1747
 
1809
- type = case
1810
- when check_relation(sub_type: left_type, super_type: AST::Builtin.bool_type).success? && !left_type.is_a?(AST::Types::Any)
1811
- AST::Builtin.bool_type
1812
- else
1813
- union_type(left_type, right_type)
1814
- end
1748
+ type =
1749
+ case
1750
+ when check_relation(sub_type: left_type, super_type: AST::Builtin.bool_type).success? && !left_type.is_a?(AST::Types::Any)
1751
+ AST::Builtin.bool_type
1752
+ else
1753
+ union_type(left_type, right_type)
1754
+ end
1815
1755
 
1816
- type = AST::Types::Logic::Env.new(truthy: env, falsy: falsey_env, type: type) if condition
1756
+ if condition
1757
+ type = AST::Types::Logic::Env.new(
1758
+ truthy: context.type_env.join(left_truthy_env, right_truthy_env),
1759
+ falsy: right_falsy_env,
1760
+ type: type
1761
+ )
1762
+ end
1817
1763
 
1818
- add_typing(node,
1819
- type: type,
1820
- constr: constr.update_lvar_env { env })
1764
+ constr.update_type_env { env }.add_typing(node, type: type)
1821
1765
  end
1822
1766
 
1823
1767
  when :if
1824
- cond, true_clause, false_clause = node.children
1825
-
1826
- cond_type, constr = synthesize(cond, condition: true)
1827
- interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: constr.typing)
1828
- truthy_env, falsey_env = interpreter.eval(env: constr.context.lvar_env, type: cond_type, node: cond)
1829
-
1830
- if true_clause
1831
- true_pair = constr
1832
- .update_lvar_env { truthy_env }
1833
- .for_branch(true_clause)
1834
- .tap {|constr| typing.add_context_for_node(true_clause, context: constr.context) }
1835
- .synthesize(true_clause, hint: hint)
1836
- end
1768
+ yield_self do
1769
+ cond, true_clause, false_clause = node.children
1770
+
1771
+ cond_type, constr = synthesize(cond, condition: true).to_ary
1772
+ interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: constr.typing)
1773
+ truthy_env, falsy_env = interpreter.eval(env: constr.context.type_env, node: cond)
1774
+
1775
+ if true_clause
1776
+ true_pair =
1777
+ constr
1778
+ .update_type_env { truthy_env }
1779
+ .for_branch(true_clause)
1780
+ .tap {|constr| typing.add_context_for_node(true_clause, context: constr.context) }
1781
+ .synthesize(true_clause, hint: hint)
1782
+ end
1837
1783
 
1838
- if false_clause
1839
- false_pair = constr
1840
- .update_lvar_env { falsey_env }
1841
- .for_branch(false_clause)
1842
- .tap {|constr| typing.add_context_for_node(false_clause, context: constr.context) }
1843
- .synthesize(false_clause, hint: hint)
1844
- end
1784
+ if false_clause
1785
+ false_pair =
1786
+ constr
1787
+ .update_type_env { falsy_env }
1788
+ .for_branch(false_clause)
1789
+ .tap {|constr| typing.add_context_for_node(false_clause, context: constr.context) }
1790
+ .synthesize(false_clause, hint: hint)
1791
+ end
1845
1792
 
1846
- constr = constr.update_lvar_env do |env|
1847
- envs = []
1793
+ constr = constr.update_type_env do |env|
1794
+ envs = []
1848
1795
 
1849
- if true_pair
1850
- unless true_pair.type.is_a?(AST::Types::Bot)
1851
- envs << true_pair.context.lvar_env
1796
+ if true_pair
1797
+ unless true_pair.type.is_a?(AST::Types::Bot)
1798
+ envs << true_pair.context.type_env
1799
+ end
1800
+ else
1801
+ envs << truthy_env
1852
1802
  end
1853
- else
1854
- envs << truthy_env
1855
- end
1856
1803
 
1857
- if false_pair
1858
- unless false_pair.type.is_a?(AST::Types::Bot)
1859
- envs << false_pair.context.lvar_env
1804
+ if false_pair
1805
+ unless false_pair.type.is_a?(AST::Types::Bot)
1806
+ envs << false_pair.context.type_env
1807
+ end
1808
+ else
1809
+ envs << falsy_env
1860
1810
  end
1861
- else
1862
- envs << falsey_env
1811
+
1812
+ env.join(*envs)
1863
1813
  end
1864
1814
 
1865
- env.join(*envs)
1815
+ node_type = union_type(true_pair&.type || AST::Builtin.nil_type, false_pair&.type || AST::Builtin.nil_type)
1816
+ add_typing(node, type: node_type, constr: constr)
1866
1817
  end
1867
1818
 
1868
- add_typing(node,
1869
- type: union_type(true_pair&.type || AST::Builtin.nil_type,
1870
- false_pair&.type || AST::Builtin.nil_type),
1871
- constr: constr)
1872
-
1873
1819
  when :case
1874
1820
  yield_self do
1875
1821
  cond, *whens, els = node.children
@@ -1878,49 +1824,41 @@ module Steep
1878
1824
  interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing)
1879
1825
 
1880
1826
  if cond
1881
- branch_pairs = []
1827
+ branch_results = []
1882
1828
 
1883
- cond_type, constr = constr.synthesize(cond)
1884
- _, cond_vars = interpreter.decompose_value(cond)
1885
- unless cond_vars.empty?
1886
- first_var = cond_vars.to_a[0]
1887
- var_node = cond.updated(:lvar, [first_var])
1888
- else
1889
- first_var = nil
1890
- var_node = cond
1891
- end
1829
+ cond_type, constr = constr.synthesize(cond).to_ary
1830
+ cond_value_node, cond_vars = interpreter.decompose_value(cond)
1892
1831
 
1893
1832
  when_constr = constr
1894
1833
  whens.each do |clause|
1834
+ # @type var tests: Array[Parser::AST::Node]
1835
+ # @type var body: Parser::AST::Node?
1895
1836
  *tests, body = clause.children
1896
1837
 
1897
1838
  test_constr = when_constr
1839
+ # @type var test_envs: Array[TypeInference::TypeEnv]
1898
1840
  test_envs = []
1899
1841
 
1900
1842
  tests.each do |test|
1901
- test_node = test.updated(:send, [test, :===, var_node])
1902
- test_type, test_constr = test_constr.synthesize(test_node, condition: true)
1903
- truthy_env, falsy_env = interpreter.eval(type: test_type, node: test_node, env: test_constr.context.lvar_env)
1904
- truthy_env = cond_vars.inject(truthy_env) do |env, var|
1905
- env.assign!(var, node: test_node, type: env[first_var])
1906
- end
1907
- falsy_env = cond_vars.inject(falsy_env) do |env, var|
1908
- env.assign!(var, node: test_node, type: env[first_var])
1909
- end
1843
+ test_node = test.updated(:send, [test, :===, cond])
1844
+ test_type, test_constr = test_constr.synthesize(test_node, condition: true).to_ary
1845
+ truthy_env, falsy_env = interpreter.eval(node: test_node, env: test_constr.context.type_env)
1910
1846
 
1911
1847
  test_envs << truthy_env
1912
- test_constr = test_constr.update_lvar_env { falsy_env }
1848
+
1849
+ test_constr = test_constr.update_type_env { falsy_env }
1913
1850
  end
1914
1851
 
1915
- body_constr = when_constr.update_lvar_env {|env| env.except(cond_vars).join(*test_envs) }
1852
+ body_constr = when_constr.update_type_env {|env| env.join(*test_envs) }
1916
1853
 
1917
1854
  if body
1918
- branch_pairs << body_constr
1919
- .for_branch(body)
1920
- .tap {|constr| typing.add_context_for_node(body, context: constr.context) }
1921
- .synthesize(body, hint: hint)
1855
+ branch_results <<
1856
+ body_constr
1857
+ .for_branch(body)
1858
+ .tap {|constr| typing.add_context_for_node(body, context: constr.context) }
1859
+ .synthesize(body, hint: hint)
1922
1860
  else
1923
- branch_pairs << Pair.new(type: AST::Builtin.nil_type, constr: body_constr)
1861
+ branch_results << Pair.new(type: AST::Builtin.nil_type, constr: body_constr)
1924
1862
  end
1925
1863
 
1926
1864
  when_constr = test_constr
@@ -1931,13 +1869,14 @@ module Steep
1931
1869
  end_pos = node.loc.end.begin_pos
1932
1870
  typing.add_context(begin_pos..end_pos, context: when_constr.context)
1933
1871
 
1934
- branch_pairs << when_constr.synthesize(els, hint: hint)
1872
+ branch_results << when_constr.synthesize(els, hint: hint)
1935
1873
  end
1936
1874
 
1937
- types = branch_pairs.map(&:type)
1938
- constrs = branch_pairs.map(&:constr)
1875
+ types = branch_results.map(&:type)
1876
+ constrs = branch_results.map(&:constr)
1939
1877
 
1940
- if when_constr.context.lvar_env[cond_vars.first].is_a?(AST::Types::Bot)
1878
+ cond_type = when_constr.context.type_env[cond_value_node]
1879
+ if cond_type.is_a?(AST::Types::Bot)
1941
1880
  # Exhaustive
1942
1881
  if els
1943
1882
  typing.add_error Diagnostic::Ruby::ElseOnExhaustiveCase.new(node: els, type: cond_type)
@@ -1949,49 +1888,52 @@ module Steep
1949
1888
  end
1950
1889
  end
1951
1890
  else
1952
- branch_pairs = []
1891
+ branch_results = []
1953
1892
 
1954
- when_constr = constr
1893
+ condition_constr = constr
1955
1894
  clause_constr = constr
1956
1895
 
1957
- whens.each do |clause|
1958
- *tests, body = clause.children
1896
+ whens.each do |when_clause|
1897
+ when_clause_constr = condition_constr
1898
+ body_envs = []
1959
1899
 
1960
- test_constr = when_constr
1900
+ *tests, body = when_clause.children
1961
1901
 
1962
1902
  tests.each do |test|
1963
- test_type, test_constr = test_constr.synthesize(test, condition: true)
1964
- truthy_env, falsy_env = interpreter.eval(env: test_constr.context.lvar_env, type: test_type, node: test)
1965
- clause_constr = clause_constr.update_lvar_env { truthy_env }
1966
- test_constr = test_constr.update_lvar_env { falsy_env }
1967
- end
1903
+ test_type, condition_constr = condition_constr.synthesize(test, condition: true).to_ary
1904
+ truthy_env, falsy_env = interpreter.eval(env: condition_constr.context.type_env, node: test)
1968
1905
 
1969
- when_constr = test_constr
1906
+ condition_constr = condition_constr.update_type_env { falsy_env }
1907
+ body_envs << truthy_env
1908
+ end
1970
1909
 
1971
1910
  if body
1972
- branch_pairs << clause_constr
1973
- .for_branch(body)
1974
- .tap {|constr| typing.add_context_for_node(body, context: constr.context) }
1975
- .synthesize(body, hint: hint)
1911
+ branch_results <<
1912
+ when_clause_constr
1913
+ .for_branch(body)
1914
+ .update_type_env {|env| env.join(*body_envs) }
1915
+ .tap {|constr| typing.add_context_for_node(body, context: constr.context) }
1916
+ .synthesize(body, hint: hint)
1976
1917
  else
1977
- branch_pairs << Pair.new(type: AST::Builtin.nil_type, constr: clause_constr)
1918
+ branch_results << Pair.new(type: AST::Builtin.nil_type, constr: when_clause_constr)
1978
1919
  end
1979
1920
  end
1980
1921
 
1981
1922
  if els
1982
- branch_pairs << when_constr.synthesize(els, hint: hint)
1923
+ branch_results << condition_constr.synthesize(els, hint: hint)
1983
1924
  end
1984
1925
 
1985
- types = branch_pairs.map(&:type)
1986
- constrs = branch_pairs.map(&:constr)
1926
+ types = branch_results.map(&:type)
1927
+ constrs = branch_results.map(&:constr)
1987
1928
 
1988
1929
  unless els
1989
1930
  types << AST::Builtin.nil_type
1990
1931
  end
1991
1932
  end
1992
1933
 
1993
- constr = constr.update_lvar_env do |env|
1994
- env.join(*constrs.map {|c| c.context.lvar_env })
1934
+ constr = constr.update_type_env do |env|
1935
+ envs = constrs.map {|c| c.context.type_env }
1936
+ env.join(*envs)
1995
1937
  end
1996
1938
 
1997
1939
  add_typing(node, type: union_type(*types), constr: constr)
@@ -2002,15 +1944,19 @@ module Steep
2002
1944
  body, *resbodies, else_node = node.children
2003
1945
  body_pair = synthesize(body, hint: hint) if body
2004
1946
 
1947
+ # @type var body_constr: TypeConstruction
2005
1948
  body_constr = if body_pair
2006
- self.update_lvar_env do |env|
2007
- env.join(env, body_pair.context.lvar_env)
1949
+ update_type_env do |env|
1950
+ env.join(env, body_pair.context.type_env)
2008
1951
  end
2009
1952
  else
2010
1953
  self
2011
1954
  end
2012
1955
 
2013
1956
  resbody_pairs = resbodies.map do |resbody|
1957
+ # @type var exn_classes: Parser::AST::Node
1958
+ # @type var assignment: Parser::AST::Node?
1959
+ # @type var body: Parser::AST::Node?
2014
1960
  exn_classes, assignment, body = resbody.children
2015
1961
 
2016
1962
  if exn_classes
@@ -2031,25 +1977,28 @@ module Steep
2031
1977
  end
2032
1978
  end
2033
1979
 
2034
- type_override = {}
1980
+ resbody_construction = body_constr.for_branch(resbody).update_type_env do |env|
1981
+ assignments = {}
2035
1982
 
2036
- case
2037
- when exn_classes && var_name
2038
- instance_types = exn_types.map do |type|
2039
- type = expand_alias(type)
2040
- case
2041
- when type.is_a?(AST::Types::Name::Singleton)
2042
- to_instance_type(type)
2043
- else
2044
- AST::Builtin.any_type
1983
+ case
1984
+ when exn_classes && var_name && exn_types
1985
+ instance_types = exn_types.map do |type|
1986
+ type = expand_alias(type)
1987
+ case
1988
+ when type.is_a?(AST::Types::Name::Singleton)
1989
+ to_instance_type(type)
1990
+ else
1991
+ AST::Builtin.any_type
1992
+ end
2045
1993
  end
1994
+
1995
+ assignments[var_name] = AST::Types::Union.build(types: instance_types)
1996
+ when var_name
1997
+ assignments[var_name] = AST::Builtin.any_type
2046
1998
  end
2047
- type_override[var_name] = AST::Types::Union.build(types: instance_types)
2048
- when var_name
2049
- type_override[var_name] = AST::Builtin.any_type
2050
- end
2051
1999
 
2052
- resbody_construction = body_constr.for_branch(resbody, type_case_override: type_override)
2000
+ env.assign_local_variables(assignments)
2001
+ end
2053
2002
 
2054
2003
  if body
2055
2004
  resbody_construction.synthesize(body, hint: hint)
@@ -2059,17 +2008,18 @@ module Steep
2059
2008
  end
2060
2009
 
2061
2010
  resbody_types = resbody_pairs.map(&:type)
2062
- resbody_envs = resbody_pairs.map {|pair| pair.context.lvar_env }
2011
+ resbody_envs = resbody_pairs.map {|pair| pair.context.type_env }
2012
+
2013
+ else_constr = body_pair&.constr || self
2063
2014
 
2064
2015
  if else_node
2065
- else_pair = (body_pair&.constr || self).for_branch(else_node).synthesize(else_node, hint: hint)
2066
- add_typing(node,
2067
- type: union_type(*[else_pair.type, *resbody_types].compact),
2068
- constr: update_lvar_env {|env| env.join(*resbody_envs, env) })
2016
+ else_type, else_constr = else_constr.for_branch(else_node).synthesize(else_node, hint: hint)
2017
+ else_constr
2018
+ .update_type_env {|env| env.join(*resbody_envs, env) }
2019
+ .add_typing(node, type: union_type(else_type, *resbody_types))
2069
2020
  else
2070
- add_typing(node,
2071
- type: union_type(*[body_pair&.type, *resbody_types].compact),
2072
- constr: update_lvar_env {|env| env.join(*resbody_envs, (body_pair&.constr || self).context.lvar_env) })
2021
+ update_type_env {|env| env.join(*resbody_envs, else_constr.context.type_env) }
2022
+ .add_typing(node, type: union_type(*[body_pair&.type, *resbody_types].compact))
2073
2023
  end
2074
2024
  end
2075
2025
 
@@ -2097,7 +2047,7 @@ module Steep
2097
2047
  yield_self do
2098
2048
  asgn, collection, body = node.children
2099
2049
 
2100
- collection_type, constr = synthesize(collection)
2050
+ collection_type, constr, collection_context = synthesize(collection).to_ary
2101
2051
  collection_type = expand_self(collection_type)
2102
2052
 
2103
2053
  var_type = case collection_type
@@ -2110,24 +2060,31 @@ module Steep
2110
2060
  method_type.block.type.params.first_param&.type
2111
2061
  end
2112
2062
  end
2063
+ var_name = asgn.children[0]
2113
2064
 
2114
2065
  if var_type
2115
2066
  if body
2116
- body_constr = constr.with_updated_context(
2117
- lvar_env: constr.context.lvar_env.assign(asgn.children[0], node: asgn, type: var_type)
2118
- )
2067
+ body_constr = constr.update_type_env do |type_env|
2068
+ type_env = type_env.assign_local_variables({ var_name => var_type })
2069
+ pins = type_env.pin_local_variables(nil)
2070
+ type_env.merge(local_variable_types: pins)
2071
+ end
2119
2072
 
2120
2073
  typing.add_context_for_body(node, context: body_constr.context)
2121
- _, _, body_context = body_constr.synthesize(body)
2074
+ _, _, body_context = body_constr.synthesize(body).to_ary
2122
2075
 
2123
- constr = constr.update_lvar_env {|env| env.join(constr.context.lvar_env, body_context.lvar_env) }
2076
+ constr = constr.update_type_env do |env|
2077
+ env.join(collection_context.type_env, body_context.type_env)
2078
+ end
2124
2079
  else
2125
2080
  constr = self
2126
2081
  end
2127
2082
 
2128
2083
  add_typing(node, type: collection_type, constr: constr)
2129
2084
  else
2130
- fallback_to_any(node) do
2085
+ constr = synthesize_children(node, skips: [collection])
2086
+
2087
+ constr.fallback_to_any(node) do
2131
2088
  Diagnostic::Ruby::NoMethod.new(
2132
2089
  node: node,
2133
2090
  method: :each,
@@ -2139,10 +2096,10 @@ module Steep
2139
2096
  when :while, :until
2140
2097
  yield_self do
2141
2098
  cond, body = node.children
2142
- cond_type, constr = synthesize(cond, condition: true)
2099
+ cond_type, constr = synthesize(cond, condition: true).to_ary
2143
2100
 
2144
2101
  interpreter = TypeInference::LogicTypeInterpreter.new(subtyping: checker, typing: typing)
2145
- truthy_env, falsy_env = interpreter.eval(env: constr.context.lvar_env, node: cond, type: cond_type)
2102
+ truthy_env, falsy_env = interpreter.eval(env: constr.context.type_env, node: cond)
2146
2103
 
2147
2104
  case node.type
2148
2105
  when :while
@@ -2152,19 +2109,19 @@ module Steep
2152
2109
  end
2153
2110
 
2154
2111
  if body
2155
- _, body_constr = constr
2156
- .update_lvar_env { body_env.pin_assignments }
2157
- .for_branch(body,
2158
- break_context: TypeInference::Context::BreakContext.new(
2159
- break_type: nil,
2160
- next_type: nil
2161
- ))
2162
- .tap {|constr| typing.add_context_for_node(body, context: constr.context) }
2163
- .synthesize(body)
2164
-
2165
- constr = constr.update_lvar_env {|env| env.join(exit_env, body_constr.context.lvar_env) }
2112
+ pins = body_env.pin_local_variables(nil)
2113
+ body_env = body_env.merge(local_variable_types: pins)
2114
+
2115
+ _, body_constr =
2116
+ constr
2117
+ .update_type_env { body_env }
2118
+ .for_branch(body, break_context: TypeInference::Context::BreakContext.new(break_type: hint || AST::Builtin.nil_type, next_type: nil))
2119
+ .tap {|constr| typing.add_context_for_node(body, context: constr.context) }
2120
+ .synthesize(body).to_ary
2121
+
2122
+ constr = constr.update_type_env {|env| env.join(exit_env, body_constr.context.type_env) }
2166
2123
  else
2167
- constr = constr.update_lvar_env { exit_env }
2124
+ constr = constr.update_type_env { exit_env }
2168
2125
  end
2169
2126
 
2170
2127
  add_typing(node, type: AST::Builtin.nil_type, constr: constr)
@@ -2174,21 +2131,18 @@ module Steep
2174
2131
  yield_self do
2175
2132
  cond, body = node.children
2176
2133
 
2177
- cond_pair = synthesize(cond)
2134
+ _, cond_constr, = synthesize(cond).to_ary
2178
2135
 
2179
2136
  if body
2180
- for_loop = cond_pair.constr
2181
- .update_lvar_env {|env| env.pin_assignments }
2182
- .for_branch(body,
2183
- break_context: TypeInference::Context::BreakContext.new(
2184
- break_type: nil,
2185
- next_type: nil
2186
- ))
2137
+ for_loop =
2138
+ cond_constr
2139
+ .update_type_env {|env| env.merge(local_variable_types: env.pin_local_variables(nil)) }
2140
+ .for_branch(body, break_context: TypeInference::Context::BreakContext.new(break_type: hint || AST::Builtin.nil_type, next_type: nil))
2187
2141
 
2188
2142
  typing.add_context_for_node(body, context: for_loop.context)
2189
- body_pair = for_loop.synthesize(body)
2143
+ _, body_constr, body_context = for_loop.synthesize(body)
2190
2144
 
2191
- constr = cond_pair.constr.update_lvar_env {|env| env.join(env, body_pair.context.lvar_env) }
2145
+ constr = cond_constr.update_type_env {|env| env.join(env, body_context.type_env) }
2192
2146
 
2193
2147
  add_typing(node, type: AST::Builtin.nil_type, constr: constr)
2194
2148
  else
@@ -2269,37 +2223,48 @@ module Steep
2269
2223
  when :gvasgn
2270
2224
  yield_self do
2271
2225
  name, rhs = node.children
2272
- type = type_env.get(gvar: name) do
2273
- fallback_to_any node
2274
- end
2226
+ lhs_type = context.type_env[name]
2275
2227
 
2276
- check(rhs, type) do |_, rhs_type, result|
2277
- typing.add_error(
2278
- Diagnostic::Ruby::IncompatibleAssignment.new(
2279
- node: node,
2280
- lhs_type: type,
2281
- rhs_type: rhs_type,
2282
- result: result
2228
+ rhs_type, constr = synthesize(rhs, hint: lhs_type).to_ary
2229
+
2230
+ if lhs_type
2231
+ result = constr.check_relation(sub_type: rhs_type, super_type: lhs_type)
2232
+
2233
+ if result.failure?
2234
+ constr.typing.add_error(
2235
+ Diagnostic::Ruby::IncompatibleAssignment.new(
2236
+ node: node,
2237
+ lhs_type: lhs_type,
2238
+ rhs_type: rhs_type,
2239
+ result: result
2240
+ )
2283
2241
  )
2284
- )
2242
+ end
2243
+ else
2244
+ constr.typing.add_error(Diagnostic::Ruby::UnknownGlobalVariable.new(node: node, name: name))
2285
2245
  end
2246
+
2247
+ constr.add_typing(node, type: rhs_type)
2286
2248
  end
2287
2249
 
2288
2250
  when :gvar
2289
2251
  yield_self do
2290
2252
  name = node.children.first
2291
- type = type_env.get(gvar: name) do
2292
- typing.add_error Diagnostic::Ruby::FallbackAny.new(node: node)
2253
+ if type = context.type_env[name]
2254
+ add_typing(node, type: type)
2255
+ else
2256
+ fallback_to_any(node) do
2257
+ Diagnostic::Ruby::UnknownGlobalVariable.new(node: node, name: name)
2258
+ end
2293
2259
  end
2294
-
2295
- add_typing(node, type: type)
2296
2260
  end
2297
2261
 
2298
2262
  when :block_pass
2299
2263
  yield_self do
2300
2264
  value = node.children[0]
2301
2265
 
2302
- if hint.is_a?(AST::Types::Proc) && value.type == :sym
2266
+ case
2267
+ when hint.is_a?(AST::Types::Proc) && value && value.type == :sym
2303
2268
  if hint.one_arg?
2304
2269
  # Assumes Symbol#to_proc implementation
2305
2270
  param_type = hint.type.params.required[0]
@@ -2333,9 +2298,18 @@ module Steep
2333
2298
  else
2334
2299
  Steep.logger.error "Passing multiple args through Symbol#to_proc is not supported yet"
2335
2300
  end
2301
+ when value == nil
2302
+ type = AST::Types::Proc.new(
2303
+ type: method_context.method_type.block.type,
2304
+ location: nil,
2305
+ block: nil
2306
+ )
2307
+ if method_context.method_type.block.optional?
2308
+ type = AST::Types::Union.build(types: [type, AST::Builtin.nil_type])
2309
+ end
2336
2310
  end
2337
2311
 
2338
- type ||= synthesize(node.children[0], hint: hint).type
2312
+ type ||= synthesize(value, hint: hint).type
2339
2313
 
2340
2314
  add_typing node, type: type
2341
2315
  end
@@ -2452,33 +2426,6 @@ module Steep
2452
2426
  end
2453
2427
  end
2454
2428
 
2455
- def type_ivasgn(name, rhs, node)
2456
- rhs_type = synthesize(rhs, hint: type_env.get(ivar: name) { fallback_to_any(node) }).type
2457
-
2458
- ivar_type = type_env.assign(
2459
- ivar: name,
2460
- type: rhs_type,
2461
- self_type: self_type,
2462
- instance_type: module_context.instance_type,
2463
- class_type: module_context.module_type
2464
- ) do |error|
2465
- if error
2466
- type = type_env.get(ivar: name)
2467
- typing.add_error(
2468
- Diagnostic::Ruby::IncompatibleAssignment.new(
2469
- node: node,
2470
- lhs_type: type,
2471
- rhs_type: rhs_type,
2472
- result: error
2473
- )
2474
- )
2475
- else
2476
- fallback_to_any node
2477
- end
2478
- end
2479
- add_typing(node, type: ivar_type)
2480
- end
2481
-
2482
2429
  def masgn_lhs?(lhs)
2483
2430
  lhs.children.all? do |a|
2484
2431
  asgn_type = if a.type == :splat
@@ -2492,233 +2439,140 @@ module Steep
2492
2439
 
2493
2440
  def lvasgn(node, type)
2494
2441
  name = node.children[0]
2495
- env = context.lvar_env.assign(name, node: node, type: type) do |declared_type, type, result|
2496
- typing.add_error(
2497
- Diagnostic::Ruby::IncompatibleAssignment.new(
2498
- node: node,
2499
- lhs_type: declared_type,
2500
- rhs_type: type,
2501
- result: result
2502
- )
2503
- )
2504
- end
2505
2442
 
2506
- add_typing(node, type: type, constr: with_updated_context(lvar_env: env))
2507
- end
2508
-
2509
- def ivasgn(node, type)
2510
- ivar = node.children[0]
2511
-
2512
- type_env.assign(
2513
- ivar: ivar,
2514
- type: type,
2515
- self_type: self_type,
2516
- instance_type: module_context.instance_type,
2517
- class_type: module_context.module_type
2518
- ) do |error|
2519
- if error
2520
- var_type = type_env.get(ivar: ivar)
2443
+ if enforced_type = context.type_env.enforced_type(name)
2444
+ if result = no_subtyping?(sub_type: type, super_type: enforced_type)
2521
2445
  typing.add_error(
2522
2446
  Diagnostic::Ruby::IncompatibleAssignment.new(
2523
2447
  node: node,
2524
- lhs_type: var_type,
2448
+ lhs_type: enforced_type,
2525
2449
  rhs_type: type,
2526
- result: error
2450
+ result: result
2527
2451
  )
2528
2452
  )
2529
- else
2530
- fallback_to_any node
2453
+
2454
+ type = enforced_type
2531
2455
  end
2532
2456
  end
2533
2457
 
2534
- add_typing(node, type: type)
2458
+ update_type_env {|env| env.assign_local_variable(name, type, enforced_type) }
2459
+ .add_typing(node, type: type)
2535
2460
  end
2536
2461
 
2537
- def type_masgn(node)
2538
- lhs, rhs = node.children
2539
- rhs_pair = synthesize(rhs)
2540
- rhs_type = deep_expand_alias(rhs_pair.type)
2541
-
2542
- constr = rhs_pair.constr
2543
-
2544
- unless masgn_lhs?(lhs)
2545
- Steep.logger.error("Unsupported masgn lhs node: only lvasgn, ivasgn, and splat are supported")
2546
- _, constr = constr.fallback_to_any(lhs)
2547
- return add_typing(node, type: rhs_type, constr: constr)
2548
- end
2549
-
2550
- falseys, truthys = partition_flatten_types(rhs_type) do |type|
2551
- type.is_a?(AST::Types::Nil) || (type.is_a?(AST::Types::Literal) && type.value == false)
2552
- end
2553
-
2554
- unwrap_rhs_type = AST::Types::Union.build(types: truthys)
2555
-
2556
- case
2557
- when unwrap_rhs_type.is_a?(AST::Types::Tuple) || (rhs.type == :array && rhs.children.none? {|n| n.type == :splat })
2558
- tuple_types = if unwrap_rhs_type.is_a?(AST::Types::Tuple)
2559
- unwrap_rhs_type.types.dup
2560
- else
2561
- rhs.children.map do |node|
2562
- typing.type_of(node: node)
2563
- end
2564
- end
2565
-
2566
- assignment_nodes = lhs.children.dup
2567
- leading_assignments = []
2568
- trailing_assignments = []
2462
+ def ivasgn(node, rhs_type)
2463
+ name = node.children[0]
2569
2464
 
2570
- until assignment_nodes.empty?
2571
- cursor = assignment_nodes.first
2465
+ lhs_type = context.type_env[name]
2572
2466
 
2573
- if cursor.type == :splat
2574
- break
2575
- else
2576
- leading_assignments << assignment_nodes.shift
2577
- end
2467
+ if lhs_type
2468
+ if (result = check_relation(sub_type: rhs_type, super_type: lhs_type)).failure?
2469
+ typing.add_error(
2470
+ Diagnostic::Ruby::IncompatibleAssignment.new(node: node, lhs_type: lhs_type, rhs_type: rhs_type, result: result)
2471
+ )
2578
2472
  end
2473
+ else
2474
+ typing.add_error(Diagnostic::Ruby::UnknownInstanceVariable.new(node: node, name: name))
2475
+ end
2579
2476
 
2580
- until assignment_nodes.empty?
2581
- cursor = assignment_nodes.last
2582
-
2583
- if cursor.type == :splat
2584
- break
2585
- else
2586
- trailing_assignments.unshift assignment_nodes.pop
2587
- end
2588
- end
2477
+ add_typing(node, type: rhs_type)
2478
+ end
2589
2479
 
2590
- leading_assignments.each do |asgn|
2591
- type = tuple_types.first
2480
+ def type_masgn_type(mlhs_node, rhs_type, masgn:, optional:)
2481
+ # @type var constr: TypeConstruction
2482
+ constr = self
2592
2483
 
2593
- if type
2594
- tuple_types.shift
2595
- else
2596
- type = AST::Builtin.nil_type
2597
- end
2484
+ if assignments = masgn.expand(mlhs_node, rhs_type || AST::Builtin.any_type, optional)
2485
+ assignments.each do |pair|
2486
+ node, type = pair
2598
2487
 
2599
- case asgn.type
2600
- when :lvasgn
2601
- _, constr = constr.lvasgn(asgn, type)
2602
- when :ivasgn
2603
- _, constr = constr.ivasgn(asgn, type)
2488
+ if assignments.optional
2489
+ type = AST::Builtin.optional(type)
2604
2490
  end
2605
- end
2606
2491
 
2607
- trailing_assignments.reverse_each do |asgn|
2608
- type = tuple_types.last
2609
-
2610
- if type
2611
- tuple_types.pop
2492
+ if node.type == :splat
2493
+ asgn_node = node.children[0]
2494
+ next unless asgn_node
2495
+ var_type = asgn_node.type
2612
2496
  else
2613
- type = AST::Builtin.nil_type
2497
+ asgn_node = node
2498
+ var_type = type
2614
2499
  end
2615
2500
 
2616
- case asgn.type
2501
+ case asgn_node.type
2617
2502
  when :lvasgn
2618
- _, constr = constr.lvasgn(asgn, type)
2503
+ _, constr = constr.lvasgn(asgn_node, type)
2619
2504
  when :ivasgn
2620
- _, constr = constr.ivasgn(asgn, type)
2505
+ _, constr = constr.ivasgn(asgn_node, type)
2506
+ when :gvasgn
2507
+ raise
2508
+ when :mlhs
2509
+ constr = (constr.type_masgn_type(asgn_node, type, masgn: masgn, optional: optional) or return)
2621
2510
  end
2622
- end
2623
2511
 
2624
- element_type = if tuple_types.empty?
2625
- AST::Builtin.nil_type
2626
- else
2627
- AST::Types::Union.build(types: tuple_types)
2628
- end
2629
- array_type = AST::Builtin::Array.instance_type(element_type)
2630
-
2631
- assignment_nodes.each do |asgn|
2632
- case asgn.type
2633
- when :splat
2634
- case asgn.children[0]&.type
2635
- when :lvasgn
2636
- _, constr = constr.lvasgn(asgn.children[0], array_type)
2637
- when :ivasgn
2638
- _, constr = constr.ivasgn(asgn.children[0], array_type)
2639
- end
2640
- when :lvasgn
2641
- _, constr = constr.lvasgn(asgn, element_type)
2642
- when :ivasgn
2643
- _,constr = constr.ivasgn(asgn, element_type)
2512
+ if node.type == :splat
2513
+ _, constr = constr.add_typing(node, type: type)
2644
2514
  end
2645
2515
  end
2646
2516
 
2647
- unless falseys.empty?
2648
- constr = constr.update_lvar_env {|lvar_env| self.context.lvar_env.join(lvar_env, self.context.lvar_env)}
2649
- end
2650
-
2651
- add_typing(node, type: rhs_type, constr: constr)
2517
+ constr
2518
+ end
2519
+ end
2652
2520
 
2653
- when flatten_union(unwrap_rhs_type).all? {|type| AST::Builtin::Array.instance_type?(type) }
2654
- array_elements = flatten_union(unwrap_rhs_type).map {|type| type.args[0] }
2655
- element_type = AST::Types::Union.build(types: array_elements + [AST::Builtin.nil_type])
2521
+ def type_masgn(node)
2522
+ lhs, rhs = node.children
2656
2523
 
2657
- constr = lhs.children.inject(constr) do |constr, assignment|
2658
- case assignment.type
2659
- when :lvasgn
2660
- _, constr = constr.lvasgn(assignment, element_type)
2524
+ masgn = TypeInference::MultipleAssignment.new()
2525
+ hint = masgn.hint_for_mlhs(lhs, context.type_env)
2661
2526
 
2662
- when :ivasgn
2663
- _, constr = constr.ivasgn(assignment, element_type)
2664
- when :splat
2665
- case assignment.children[0]&.type
2666
- when :lvasgn
2667
- _, constr = constr.lvasgn(assignment.children[0], unwrap_rhs_type)
2668
- when :ivasgn
2669
- _, constr = constr.ivasgn(assignment.children[0], unwrap_rhs_type)
2670
- when nil
2671
- # foo, * = bar
2672
- else
2673
- raise
2674
- end
2675
- end
2527
+ rhs_type, lhs_constr = try_tuple_type!(rhs, hint: hint).to_ary
2528
+ rhs_type = deep_expand_alias(rhs_type)
2676
2529
 
2677
- constr
2678
- end
2530
+ falsys, truthys = partition_flatten_types(rhs_type) do |type|
2531
+ type.is_a?(AST::Types::Nil) || (type.is_a?(AST::Types::Literal) && type.value == false)
2532
+ end
2679
2533
 
2680
- unless falseys.empty?
2681
- constr = constr.update_lvar_env {|lvar_env| self.context.lvar_env.join(lvar_env, self.context.lvar_env)}
2682
- end
2534
+ truthy_rhs_type = AST::Types::Union.build(types: truthys)
2535
+ optional = !falsys.empty?
2683
2536
 
2684
- add_typing(node, type: rhs_type, constr: constr)
2537
+ if truthy_rhs_type.is_a?(AST::Types::Tuple) || AST::Builtin::Array.instance_type?(truthy_rhs_type) || truthy_rhs_type.is_a?(AST::Types::Any)
2538
+ constr = lhs_constr.type_masgn_type(lhs, truthy_rhs_type, masgn: masgn, optional: optional)
2685
2539
  else
2686
- unless rhs_type.is_a?(AST::Types::Any)
2687
- Steep.logger.error("Unsupported masgn rhs type: array or tuple is supported (#{rhs_type})")
2688
- end
2540
+ ary_type = try_convert(truthy_rhs_type, :to_ary) || try_convert(truthy_rhs_type, :to_a) || AST::Types::Tuple.new(types: [truthy_rhs_type])
2541
+ constr = lhs_constr.type_masgn_type(lhs, ary_type, masgn: masgn, optional: optional)
2542
+ end
2689
2543
 
2690
- untyped = AST::Builtin.any_type
2544
+ unless constr
2545
+ typing.add_error(
2546
+ Diagnostic::Ruby::MultipleAssignmentConversionError.new(
2547
+ node: rhs,
2548
+ original_type: rhs_type,
2549
+ returned_type: ary_type || AST::Builtin.bottom_type
2550
+ )
2551
+ )
2691
2552
 
2692
- constr = lhs.children.inject(constr) do |constr, assignment|
2693
- case assignment.type
2553
+ constr = lhs_constr
2554
+
2555
+ each_descendant_node(lhs) do |node|
2556
+ case node.type
2694
2557
  when :lvasgn
2695
- _, constr = constr.lvasgn(assignment, untyped)
2558
+ _, constr = constr.lvasgn(node, AST::Builtin.any_type).to_ary
2696
2559
  when :ivasgn
2697
- _, constr = constr.ivasgn(assignment, untyped)
2698
- when :splat
2699
- case assignment.children[0]&.type
2700
- when :lvasgn
2701
- _, constr = constr.lvasgn(assignment.children[0], untyped)
2702
- when :ivasgn
2703
- _, constr = constr.ivasgn(assignment.children[0], untyped)
2704
- when nil
2705
- # foo, * = bar
2706
- else
2707
- raise
2708
- end
2560
+ _, constr = constr.ivasgn(node, AST::Builtin.any_type).to_ary
2561
+ when :gvasgn
2562
+ raise
2563
+ else
2564
+ _, constr = constr.add_typing(node, type: AST::Builtin.any_type).to_ary
2709
2565
  end
2710
-
2711
- constr
2712
2566
  end
2713
-
2714
- add_typing(node, type: rhs_type, constr: constr)
2715
2567
  end
2568
+
2569
+ constr.add_typing(node, type: truthy_rhs_type)
2716
2570
  end
2717
2571
 
2718
2572
  def synthesize_constant(node, parent_node, constant_name)
2719
2573
  const_name = module_name_from_node(parent_node, constant_name)
2720
2574
 
2721
- if const_name && type = type_env.get(const: const_name) { break }
2575
+ if const_name && type = context.type_env.annotated_constant(const_name)
2722
2576
  # const-type annotation wins
2723
2577
  if node
2724
2578
  constr = synthesize_children(node)
@@ -2732,7 +2586,7 @@ module Steep
2732
2586
  when !parent_node
2733
2587
  constr = self
2734
2588
 
2735
- if (type, name = module_context.const_env.resolve(constant_name))
2589
+ if (type, name = context.type_env.constant(constant_name, false))
2736
2590
  if node
2737
2591
  _, constr = add_typing(node, type: type)
2738
2592
  end
@@ -2742,7 +2596,7 @@ module Steep
2742
2596
  when parent_node.type == :cbase
2743
2597
  _, constr = add_typing(parent_node, type: AST::Builtin.nil_type)
2744
2598
 
2745
- if (type, name = constr.module_context.const_env.toplevel(constant_name))
2599
+ if (type, name = constr.context.type_env.constant(constant_name, true))
2746
2600
  if node
2747
2601
  _, constr = constr.add_typing(node, type: type)
2748
2602
  end
@@ -2750,12 +2604,12 @@ module Steep
2750
2604
  return [type, constr, name]
2751
2605
  end
2752
2606
  else
2753
- parent_type, constr = synthesize(parent_node)
2607
+ parent_type, constr = synthesize(parent_node).to_ary
2754
2608
  parent_type = deep_expand_alias(parent_type)
2755
2609
 
2756
2610
  case parent_type
2757
2611
  when AST::Types::Name::Singleton
2758
- if (type, name = module_context.const_env.resolve_child(parent_type.name, constant_name))
2612
+ if (type, name = constr.context.type_env.constant(parent_type.name, constant_name))
2759
2613
  if node
2760
2614
  _, constr = add_typing(node, type: type)
2761
2615
  end
@@ -2817,6 +2671,7 @@ module Steep
2817
2671
  end
2818
2672
 
2819
2673
  block_constr = for_block(
2674
+ body_node,
2820
2675
  block_params: params,
2821
2676
  block_param_hint: params_hint,
2822
2677
  block_type_hint: return_hint,
@@ -2827,13 +2682,6 @@ module Steep
2827
2682
 
2828
2683
  block_constr.typing.add_context_for_body(node, context: block_constr.context)
2829
2684
 
2830
- default_proc_function =
2831
- Interface::Function.new(
2832
- params: Interface::Function::Params.empty,
2833
- return_type: AST::Builtin.any_type,
2834
- location: nil
2835
- )
2836
-
2837
2685
  params.params.each do |param|
2838
2686
  _, block_constr = block_constr.synthesize(param.node, hint: param.type)
2839
2687
  end
@@ -2878,6 +2726,10 @@ module Steep
2878
2726
  )
2879
2727
 
2880
2728
  if expected_block_type = block_constr.block_context.body_type
2729
+ type_vars = expected_block_type.free_variables
2730
+ subst = Interface::Substitution.build(type_vars, type_vars.map { AST::Builtin.any_type })
2731
+ expected_block_type = expected_block_type.subst(subst)
2732
+
2881
2733
  check_relation(sub_type: return_type, super_type: expected_block_type).else do |result|
2882
2734
  block_constr.typing.add_error(
2883
2735
  Diagnostic::Ruby::BlockBodyTypeMismatch.new(
@@ -2921,6 +2773,20 @@ module Steep
2921
2773
  constr
2922
2774
  end
2923
2775
 
2776
+ KNOWN_PURE_METHODS = Set[
2777
+ MethodName("::Array#[]"),
2778
+ MethodName("::Hash#[]")
2779
+ ]
2780
+
2781
+ def pure_send?(call, receiver, arguments)
2782
+ return false unless call.node.type == :send || call.node.type == :csend
2783
+ return false unless call.pure? || KNOWN_PURE_METHODS.superset?(Set.new(call.method_decls.map(&:method_name)))
2784
+
2785
+ [receiver, *arguments].all? do |node|
2786
+ !node || value_node?(node) || context.type_env[node]
2787
+ end
2788
+ end
2789
+
2924
2790
  def type_send_interface(node, interface:, receiver:, receiver_type:, method_name:, arguments:, block_params:, block_body:)
2925
2791
  method = interface.methods[method_name]
2926
2792
 
@@ -2937,8 +2803,28 @@ module Steep
2937
2803
  if call && constr
2938
2804
  case method_name.to_s
2939
2805
  when "[]=", /\w=\Z/
2940
- if typing.has_type?(arguments.last)
2941
- call = call.with_return_type(typing.type_of(node: arguments.last))
2806
+ last_arg = arguments.last or raise
2807
+ if typing.has_type?(last_arg)
2808
+ call = call.with_return_type(typing.type_of(node: last_arg))
2809
+ end
2810
+ end
2811
+
2812
+ if call.is_a?(TypeInference::MethodCall::Typed)
2813
+ if (pure_call, type = constr.context.type_env.pure_method_calls[node])
2814
+ if type
2815
+ call = pure_call.update(node: node, return_type: type)
2816
+ constr.add_typing(node, type: call.return_type)
2817
+ end
2818
+ else
2819
+ if pure_send?(call, receiver, arguments)
2820
+ constr = constr.update_type_env do |env|
2821
+ env.add_pure_call(node, call, call.return_type)
2822
+ end
2823
+ else
2824
+ constr = constr.update_type_env do |env|
2825
+ env.invalidate_pure_node(receiver)
2826
+ end
2827
+ end
2942
2828
  end
2943
2829
  end
2944
2830
 
@@ -2997,6 +2883,17 @@ module Steep
2997
2883
  )
2998
2884
  end
2999
2885
 
2886
+ if node.type == :block
2887
+ send_node = node.children[0]
2888
+ case send_node.type
2889
+ when :super, :zsuper
2890
+ method_name = method_context.name
2891
+ return fallback_to_any(send_node) do
2892
+ Diagnostic::Ruby::UnexpectedSuper.new(node: send_node, method: method_name)
2893
+ end
2894
+ end
2895
+ end
2896
+
3000
2897
  constr.add_call(
3001
2898
  TypeInference::MethodCall::NoMethodError.new(
3002
2899
  node: node,
@@ -3093,6 +2990,15 @@ module Steep
3093
2990
  private: private,
3094
2991
  self_type: AST::Types::Self.new)
3095
2992
 
2993
+ if send_node.type == :super || send_node.type == :zsuper
2994
+ method_name = method_context.name
2995
+ unless method_context.super_method
2996
+ return fallback_to_any(send_node) do
2997
+ Diagnostic::Ruby::UnexpectedSuper.new(node: send_node, method: method_name)
2998
+ end
2999
+ end
3000
+ end
3001
+
3096
3002
  constr.type_send_interface(node,
3097
3003
  interface: interface,
3098
3004
  receiver: receiver,
@@ -3144,6 +3050,9 @@ module Steep
3144
3050
  array_compact: Set[
3145
3051
  MethodName("::Array#compact"),
3146
3052
  MethodName("::Enumerable#compact")
3053
+ ],
3054
+ hash_compact: Set[
3055
+ MethodName("::Hash#compact")
3147
3056
  ]
3148
3057
  }
3149
3058
 
@@ -3170,6 +3079,29 @@ module Steep
3170
3079
  method_decls: decls
3171
3080
  )
3172
3081
 
3082
+ return [call, constr]
3083
+ end
3084
+ end
3085
+ when decl = decls.find {|decl| SPECIAL_METHOD_NAMES[:hash_compact].include?(decl.method_name) }
3086
+ if arguments.empty? && !block_params
3087
+ # compact
3088
+ return_type = method_type.type.return_type
3089
+ if AST::Builtin::Hash.instance_type?(return_type)
3090
+ key = return_type.args[0]
3091
+ value = return_type.args[1]
3092
+ type = AST::Builtin::Hash.instance_type(key, unwrap(value))
3093
+
3094
+ _, constr = add_typing(node, type: type)
3095
+ call = TypeInference::MethodCall::Special.new(
3096
+ node: node,
3097
+ context: constr.context.method_context,
3098
+ method_name: decl.method_name,
3099
+ receiver_type: receiver_type,
3100
+ actual_method_type: method_type.with(type: method_type.type.with(return_type: type)),
3101
+ return_type: type,
3102
+ method_decls: decls
3103
+ )
3104
+
3173
3105
  return [call, constr]
3174
3106
  end
3175
3107
  end
@@ -3239,7 +3171,7 @@ module Steep
3239
3171
 
3240
3172
  [
3241
3173
  call,
3242
- update_lvar_env { constr.context.lvar_env }
3174
+ update_type_env { constr.context.type_env }
3243
3175
  ]
3244
3176
  end
3245
3177
 
@@ -3306,10 +3238,18 @@ module Steep
3306
3238
 
3307
3239
  constr = self
3308
3240
 
3241
+ constr = constr.with(
3242
+ context: context.with(
3243
+ variable_context: TypeInference::Context::TypeVariableContext.new(
3244
+ type_params,
3245
+ parent_context: context.variable_context
3246
+ )
3247
+ )
3248
+ )
3249
+
3309
3250
  method_type = method_type.instantiate(instantiation)
3310
3251
 
3311
3252
  variance = Subtyping::VariableVariance.from_method_type(method_type)
3312
- occurence = Subtyping::VariableOccurence.from_method_type(method_type)
3313
3253
  constraints = Subtyping::Constraints.new(unknowns: type_params.map(&:name))
3314
3254
  ccontext = Subtyping::Constraints::Context.new(
3315
3255
  self_type: self_type,
@@ -3426,6 +3366,7 @@ module Steep
3426
3366
  if pairs
3427
3367
  # Block parameters are compatible with the block type
3428
3368
  block_constr = constr.for_block(
3369
+ block_body,
3429
3370
  block_params: block_params_,
3430
3371
  block_param_hint: method_type.block.type.params,
3431
3372
  block_type_hint: method_type.block.type.return_type,
@@ -3434,15 +3375,13 @@ module Steep
3434
3375
  node_type_hint: method_type.type.return_type
3435
3376
  )
3436
3377
  block_constr = block_constr.with_new_typing(
3437
- block_constr.typing.new_child(
3438
- range: block_constr.typing.block_range(node)
3439
- )
3378
+ block_constr.typing.new_child(block_constr.typing.block_range(node))
3440
3379
  )
3441
3380
 
3442
3381
  block_constr.typing.add_context_for_body(node, context: block_constr.context)
3443
3382
 
3444
3383
  pairs.each do |param, type|
3445
- _, block_constr = block_constr.synthesize(param.node, hint: param.type || type)
3384
+ _, block_constr = block_constr.synthesize(param.node, hint: param.type || type).to_ary
3446
3385
 
3447
3386
  if param.type
3448
3387
  check_relation(sub_type: type, super_type: param.type, constraints: constraints).else do |result|
@@ -3467,16 +3406,20 @@ module Steep
3467
3406
 
3468
3407
  if solved
3469
3408
  # Ready for type check the body of the block
3470
- block_constr = block_constr.update_lvar_env {|env| env.subst(s) }
3471
- if block_body
3472
- block_body_type = block_constr.synthesize_block(
3473
- node: node,
3474
- block_body: block_body,
3475
- block_type_hint: method_type.block.type.return_type
3409
+ block_constr = block_constr.update_type_env {|env| env.subst(s) }
3410
+ block_constr = block_constr.update_context {|context|
3411
+ context.with(
3412
+ type_env: context.type_env.subst(s),
3413
+ block_context: context.block_context&.subst(s),
3414
+ break_context: context.break_context&.subst(s)
3476
3415
  )
3477
- else
3478
- block_body_type = AST::Builtin.nil_type
3479
- end
3416
+ }
3417
+
3418
+ block_body_type = block_constr.synthesize_block(
3419
+ node: node,
3420
+ block_body: block_body,
3421
+ block_type_hint: method_type.block.type.return_type
3422
+ )
3480
3423
 
3481
3424
  result = check_relation(sub_type: block_body_type,
3482
3425
  super_type: method_type.block.type.return_type,
@@ -3537,10 +3480,20 @@ module Steep
3537
3480
  errors << error
3538
3481
  end
3539
3482
 
3540
- errors << Diagnostic::Ruby::UnexpectedBlockGiven.new(
3541
- node: node,
3542
- method_type: method_type
3543
- )
3483
+ case node.children[0].type
3484
+ when :super, :zsuper
3485
+ unless method_context.super_method
3486
+ errors << Diagnostic::Ruby::UnexpectedSuper.new(
3487
+ node: node.children[0],
3488
+ method: method_name
3489
+ )
3490
+ end
3491
+ else
3492
+ errors << Diagnostic::Ruby::UnexpectedBlockGiven.new(
3493
+ node: node,
3494
+ method_type: method_type
3495
+ )
3496
+ end
3544
3497
 
3545
3498
  method_type = eliminate_vars(method_type, type_param_names)
3546
3499
  return_type = method_type.type.return_type
@@ -3652,6 +3605,12 @@ module Steep
3652
3605
  )
3653
3606
  end
3654
3607
 
3608
+ constr = constr.with(
3609
+ context: constr.context.with(
3610
+ variable_context: context.variable_context
3611
+ )
3612
+ )
3613
+
3655
3614
  [
3656
3615
  call,
3657
3616
  constr
@@ -3683,12 +3642,13 @@ module Steep
3683
3642
  end
3684
3643
 
3685
3644
  block_constr = for_block(
3645
+ block_body,
3686
3646
  block_params: block_params,
3687
3647
  block_param_hint: nil,
3688
- block_type_hint: AST::Builtin.any_type,
3648
+ block_type_hint: nil,
3689
3649
  block_block_hint: nil,
3690
3650
  block_annotations: block_annotations,
3691
- node_type_hint: AST::Builtin.any_type
3651
+ node_type_hint: nil
3692
3652
  )
3693
3653
 
3694
3654
  block_constr.typing.add_context_for_body(node, context: block_constr.context)
@@ -3713,7 +3673,7 @@ module Steep
3713
3673
  end
3714
3674
  end
3715
3675
 
3716
- def for_block(block_params:, block_param_hint:, block_type_hint:, block_block_hint:, block_annotations:, node_type_hint:)
3676
+ def for_block(body_node, block_params:, block_param_hint:, block_type_hint:, block_block_hint:, block_annotations:, node_type_hint:)
3717
3677
  block_param_pairs = block_param_hint && block_params.zip(block_param_hint, block_block_hint)
3718
3678
 
3719
3679
  param_types_hash = {}
@@ -3729,14 +3689,32 @@ module Steep
3729
3689
  end
3730
3690
  end
3731
3691
 
3732
- decls = param_types_hash.each.with_object({}) do |(name, type), hash|
3733
- hash[name] = TypeInference::LocalVariableTypeEnv::Entry.new(type: type)
3692
+ param_types = param_types_hash.each.with_object({}) do |pair, hash|
3693
+ # @type var hash: Hash[Symbol, [AST::Types::t, AST::Types::t?]]
3694
+ name, type = pair
3695
+ hash[name] = [type, nil]
3734
3696
  end
3735
- lvar_env = context.lvar_env
3736
- .pin_assignments
3737
- .except(decls.keys)
3738
- .update(assigned_types: decls)
3739
- .annotate(block_annotations)
3697
+
3698
+ pins = context.type_env.pin_local_variables(nil)
3699
+
3700
+ type_env = context.type_env
3701
+ type_env = type_env.merge(local_variable_types: pins)
3702
+ type_env = type_env.merge(local_variable_types: param_types)
3703
+ type_env = TypeInference::TypeEnvBuilder.new(
3704
+ TypeInference::TypeEnvBuilder::Command::ImportLocalVariableAnnotations.new(block_annotations).merge!.on_duplicate! do |name, outer_type, inner_type|
3705
+ next if outer_type.is_a?(AST::Types::Var) || inner_type.is_a?(AST::Types::Var)
3706
+ next unless body_node
3707
+
3708
+ if result = no_subtyping?(sub_type: outer_type, super_type: inner_type)
3709
+ typing.add_error Diagnostic::Ruby::IncompatibleAnnotation.new(
3710
+ node: body_node,
3711
+ var_name: name,
3712
+ result: result,
3713
+ relation: result.relation
3714
+ )
3715
+ end
3716
+ end
3717
+ ).build(type_env)
3740
3718
 
3741
3719
  break_type = if block_annotations.break_type
3742
3720
  union_type(node_type_hint, block_annotations.break_type)
@@ -3745,21 +3723,18 @@ module Steep
3745
3723
  end
3746
3724
 
3747
3725
  block_context = TypeInference::Context::BlockContext.new(
3748
- body_type: block_annotations.block_type || block_type_hint || AST::Builtin.any_type
3726
+ body_type: block_annotations.block_type || block_type_hint
3749
3727
  )
3750
3728
  break_context = TypeInference::Context::BreakContext.new(
3751
- break_type: break_type,
3752
- next_type: block_context.body_type
3729
+ break_type: break_type || AST::Builtin.any_type,
3730
+ next_type: block_context.body_type || AST::Builtin.any_type
3753
3731
  )
3754
3732
 
3755
3733
  self_type = self.self_type
3756
3734
  module_context = self.module_context
3757
3735
 
3758
3736
  if implements = block_annotations.implement_module_annotation
3759
- module_context = default_module_context(
3760
- implements.name,
3761
- const_env: self.module_context.const_env
3762
- )
3737
+ module_context = default_module_context(implements.name, nesting: nesting)
3763
3738
 
3764
3739
  self_type = module_context.module_type
3765
3740
  end
@@ -3779,8 +3754,7 @@ module Steep
3779
3754
  module_context: module_context,
3780
3755
  break_context: break_context,
3781
3756
  self_type: self_type,
3782
- type_env: type_env.dup,
3783
- lvar_env: lvar_env,
3757
+ type_env: type_env,
3784
3758
  call_context: self.context.call_context,
3785
3759
  variable_context: variable_context
3786
3760
  )
@@ -3800,35 +3774,10 @@ module Steep
3800
3774
  end
3801
3775
  end
3802
3776
 
3803
- def each_child_node(node)
3804
- if block_given?
3805
- node.children.each do |child|
3806
- if child.is_a?(::AST::Node)
3807
- yield child
3808
- end
3809
- end
3810
- else
3811
- enum_for :each_child_node, node
3812
- end
3813
- end
3814
-
3815
3777
  def nesting
3816
3778
  module_context&.nesting
3817
3779
  end
3818
3780
 
3819
- def absolute_nested_module_name(module_name)
3820
- n = nesting
3821
- while n && !n[1]
3822
- n = n[0]
3823
- end
3824
-
3825
- if n
3826
- module_name.absolute!
3827
- else
3828
- n + module_name
3829
- end
3830
- end
3831
-
3832
3781
  def absolute_name(name)
3833
3782
  checker.factory.absolute_type_name(name, context: nesting)
3834
3783
  end
@@ -4025,12 +3974,14 @@ module Steep
4025
3974
  end
4026
3975
 
4027
3976
  def try_tuple_type!(node, hint: nil)
4028
- if node.type == :array && (hint.nil? || hint.is_a?(AST::Types::Tuple))
4029
- node_range = node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }
3977
+ if node.type == :array
3978
+ if hint.nil? || hint.is_a?(AST::Types::Tuple)
3979
+ node_range = node.loc.expression.yield_self {|l| l.begin_pos..l.end_pos }
4030
3980
 
4031
- typing.new_child(node_range) do |child_typing|
4032
- if pair = with_new_typing(child_typing).try_tuple_type(node, hint)
4033
- return pair.with(constr: pair.constr.save_typing)
3981
+ typing.new_child(node_range) do |child_typing|
3982
+ if pair = with_new_typing(child_typing).try_tuple_type(node, hint)
3983
+ return pair.with(constr: pair.constr.save_typing)
3984
+ end
4034
3985
  end
4035
3986
  end
4036
3987
  end
@@ -4065,13 +4016,13 @@ module Steep
4065
4016
  return
4066
4017
  end
4067
4018
 
4068
- interface = checker.factory.interface(type, private: false)
4019
+ interface = checker.factory.interface(type, private: false, self_type: self_type)
4069
4020
  if entry = interface.methods[method]
4070
4021
  method_type = entry.method_types.find do |method_type|
4071
4022
  method_type.type.params.optional?
4072
4023
  end
4073
4024
 
4074
- method_type.type.return_type
4025
+ method_type.type.return_type if method_type
4075
4026
  end
4076
4027
  rescue => exn
4077
4028
  Steep.log_error(exn, message: "Unexpected error when converting #{type.to_s} with #{method}")
@@ -4109,20 +4060,15 @@ module Steep
4109
4060
  constr.add_typing(node, type: AST::Builtin::Array.instance_type(element_type))
4110
4061
  end
4111
4062
 
4112
- # Try to give record type to hash_node.
4113
- #
4114
- # Returns nil when it cannot have a record type.
4115
- # `record_type` can be nil when the keys are not specified.
4116
- #
4117
4063
  def type_hash_record(hash_node, record_type)
4118
4064
  raise unless hash_node.type == :hash || hash_node.type == :kwargs
4119
4065
 
4120
4066
  constr = self
4121
4067
 
4122
4068
  if record_type
4123
- elements = record_type.elements.dup
4069
+ hints = record_type.elements.dup
4124
4070
  else
4125
- elements = {}
4071
+ hints = {}
4126
4072
  end
4127
4073
 
4128
4074
  elems = {}
@@ -4137,7 +4083,18 @@ module Steep
4137
4083
  key = key_node.children[0]
4138
4084
 
4139
4085
  _, constr = constr.synthesize(key_node, hint: AST::Types::Literal.new(value: key))
4140
- value_type, constr = constr.synthesize(value_node, hint: elements[key])
4086
+
4087
+ value_type, constr = constr.synthesize(value_node, hint: hints[key])
4088
+
4089
+ if hints.key?(key)
4090
+ hint_type = hints[key]
4091
+ case
4092
+ when value_type.is_a?(AST::Types::Any)
4093
+ value_type = hints[key]
4094
+ when hint_type.is_a?(AST::Types::Var)
4095
+ value_type = value_type
4096
+ end
4097
+ end
4141
4098
 
4142
4099
  elems[key] = value_type
4143
4100
  else
@@ -4240,11 +4197,11 @@ module Steep
4240
4197
  def pick_one_of(types, range:)
4241
4198
  types.each do |type|
4242
4199
  with_child_typing(range: range) do |constr|
4243
- type_, constr = yield type, constr
4244
-
4245
- constr.check_relation(sub_type: type_, super_type: type).then do
4246
- constr = constr.save_typing
4247
- return Pair.new(type: type, constr: constr)
4200
+ if (type_, constr = yield(type, constr))
4201
+ constr.check_relation(sub_type: type_, super_type: type).then do
4202
+ constr = constr.save_typing
4203
+ return Pair.new(type: type, constr: constr)
4204
+ end
4248
4205
  end
4249
4206
  end
4250
4207
  end