steep 1.0.2 → 1.1.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (121) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +5 -0
  3. data/.gitignore +1 -0
  4. data/CHANGELOG.md +22 -3
  5. data/Gemfile +6 -3
  6. data/Gemfile.lock +12 -16
  7. data/Gemfile.steep +3 -0
  8. data/Gemfile.steep.lock +49 -0
  9. data/Rakefile +5 -0
  10. data/Steepfile +6 -1
  11. data/bin/setup +2 -0
  12. data/bin/steep +19 -0
  13. data/lib/steep/ast/types/factory.rb +1 -1
  14. data/lib/steep/diagnostic/ruby.rb +49 -3
  15. data/lib/steep/diagnostic/signature.rb +18 -0
  16. data/lib/steep/drivers/watch.rb +3 -1
  17. data/lib/steep/method_name.rb +9 -3
  18. data/lib/steep/node_helper.rb +49 -0
  19. data/lib/steep/services/completion_provider.rb +22 -15
  20. data/lib/steep/services/hover_provider/ruby.rb +30 -12
  21. data/lib/steep/services/type_check_service.rb +12 -12
  22. data/lib/steep/shims/symbol_start_with.rb +18 -0
  23. data/lib/steep/signature/validator.rb +19 -0
  24. data/lib/steep/subtyping/constraints.rb +43 -14
  25. data/lib/steep/type_construction.rb +666 -746
  26. data/lib/steep/type_inference/constant_env.rb +0 -2
  27. data/lib/steep/type_inference/context.rb +23 -17
  28. data/lib/steep/type_inference/logic_type_interpreter.rb +210 -119
  29. data/lib/steep/type_inference/method_call.rb +80 -6
  30. data/lib/steep/type_inference/multiple_assignment.rb +189 -0
  31. data/lib/steep/type_inference/type_env.rb +271 -120
  32. data/lib/steep/type_inference/type_env_builder.rb +138 -0
  33. data/lib/steep/typing.rb +2 -0
  34. data/lib/steep/version.rb +1 -1
  35. data/lib/steep.rb +4 -3
  36. data/rbs_collection.steep.lock.yaml +112 -0
  37. data/rbs_collection.steep.yaml +19 -0
  38. data/sample/sig/conference.rbs +8 -0
  39. data/sig/shims/parser/source/map.rbs +146 -0
  40. data/sig/shims/parser/source/range.rbs +237 -0
  41. data/sig/shims/parser.rbs +17 -0
  42. data/sig/steep/ast/annotation/collection.rbs +75 -0
  43. data/sig/steep/ast/annotation.rbs +126 -0
  44. data/sig/steep/ast/builtin.rbs +69 -0
  45. data/sig/steep/ast/type_params.rbs +11 -0
  46. data/sig/steep/ast/types/any.rbs +29 -0
  47. data/sig/steep/ast/types/boolean.rbs +31 -0
  48. data/sig/steep/ast/types/bot.rbs +29 -0
  49. data/sig/steep/ast/types/class.rbs +29 -0
  50. data/sig/steep/ast/types/factory.rbs +76 -0
  51. data/sig/steep/ast/types/helper.rbs +19 -0
  52. data/sig/steep/ast/types/instance.rbs +29 -0
  53. data/sig/steep/ast/types/intersection.rbs +35 -0
  54. data/sig/steep/ast/types/literal.rbs +33 -0
  55. data/sig/steep/ast/types/logic.rbs +78 -0
  56. data/sig/steep/ast/types/name.rbs +71 -0
  57. data/sig/steep/ast/types/nil.rbs +31 -0
  58. data/sig/steep/ast/types/proc.rbs +46 -0
  59. data/sig/steep/ast/types/record.rbs +38 -0
  60. data/sig/steep/ast/types/self.rbs +29 -0
  61. data/sig/steep/ast/types/top.rbs +29 -0
  62. data/sig/steep/ast/types/tuple.rbs +34 -0
  63. data/sig/steep/ast/types/union.rbs +38 -0
  64. data/sig/steep/ast/types/var.rbs +37 -0
  65. data/sig/steep/ast/types/void.rbs +29 -0
  66. data/sig/steep/ast/types.rbs +37 -0
  67. data/sig/steep/diagnostic/deprecated/unknown_constant_assigned.rbs +15 -0
  68. data/sig/steep/diagnostic/helper.rbs +9 -0
  69. data/sig/steep/diagnostic/lsp_formatter.rbs +29 -0
  70. data/sig/steep/diagnostic/ruby.rbs +494 -0
  71. data/sig/steep/diagnostic/signature.rbs +215 -0
  72. data/sig/steep/interface/block.rbs +35 -0
  73. data/sig/steep/interface/function.rbs +253 -0
  74. data/sig/steep/interface/interface.rbs +23 -0
  75. data/sig/steep/interface/method_type.rbs +55 -0
  76. data/sig/steep/interface/substitution.rbs +53 -0
  77. data/sig/steep/interface/type_param.rbs +35 -0
  78. data/sig/steep/method_name.rbs +26 -0
  79. data/sig/steep/module_helper.rbs +7 -0
  80. data/sig/steep/node_helper.rbs +11 -0
  81. data/sig/steep/project/dsl.rbs +94 -0
  82. data/sig/steep/project/options.rbs +15 -0
  83. data/sig/steep/project/pattern.rbs +25 -0
  84. data/sig/steep/project/target.rbs +25 -0
  85. data/sig/steep/project.rbs +19 -0
  86. data/sig/steep/services/completion_provider.rbs +123 -0
  87. data/sig/steep/services/content_change.rbs +35 -0
  88. data/sig/steep/services/file_loader.rbs +13 -0
  89. data/sig/steep/services/goto_service.rbs +45 -0
  90. data/sig/steep/services/hover_provider/rbs.rbs +21 -0
  91. data/sig/steep/services/hover_provider/ruby.rbs +109 -0
  92. data/sig/steep/services/hover_provider/singleton_methods.rbs +11 -0
  93. data/sig/steep/services/path_assignment.rbs +21 -0
  94. data/sig/steep/services/signature_service.rbs +91 -0
  95. data/sig/steep/services/stats_calculator.rbs +17 -0
  96. data/sig/steep/services/type_check_service.rbs +93 -0
  97. data/sig/steep/source.rbs +55 -0
  98. data/sig/steep/subtyping/cache.rbs +17 -0
  99. data/sig/steep/subtyping/check.rbs +93 -0
  100. data/sig/steep/subtyping/constraints.rbs +111 -0
  101. data/sig/steep/subtyping/relation.rbs +51 -0
  102. data/sig/steep/subtyping/result.rbs +157 -0
  103. data/sig/steep/subtyping/variable_variance.rbs +23 -0
  104. data/sig/steep/type_construction.rbs +285 -0
  105. data/sig/steep/type_inference/block_params.rbs +52 -0
  106. data/sig/steep/type_inference/constant_env.rbs +27 -0
  107. data/sig/steep/type_inference/context.rbs +137 -0
  108. data/sig/steep/type_inference/logic_type_interpreter.rbs +72 -0
  109. data/sig/steep/type_inference/method_call.rbs +124 -0
  110. data/sig/steep/type_inference/method_params.rbs +104 -0
  111. data/sig/steep/type_inference/multiple_assignment.rbs +76 -0
  112. data/sig/steep/type_inference/type_env.rbs +158 -0
  113. data/sig/steep/type_inference/type_env_builder.rbs +77 -0
  114. data/sig/steep/typing.rbs +68 -0
  115. data/sig/steep.rbs +31 -0
  116. data/smoke/class/f.rb +1 -0
  117. data/smoke/class/test_expectations.yml +2 -2
  118. data/smoke/diagnostics/test_expectations.yml +4 -2
  119. metadata +90 -6
  120. data/lib/steep/type_inference/local_variable_type_env.rb +0 -249
  121. 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,16 +132,15 @@ module Steep
129
132
  end
130
133
  end
131
134
 
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
139
+ end
140
+ end
141
+
132
142
  def for_new_method(method_name, node, args:, self_type:, definition:)
133
143
  annots = source.annotations(block: node, factory: checker.factory, context: nesting)
134
- type_env = TypeInference::TypeEnv.build(
135
- annotations: annots,
136
- subtyping: checker,
137
- const_env: module_context&.const_env || self.type_env.const_env,
138
- signatures: checker.factory.env
139
- )
140
- type_env.merge_const_types(self.type_env)
141
-
142
144
  definition_method_type = if definition
143
145
  definition.methods[method_name]&.yield_self do |method|
144
146
  method.method_types
@@ -191,27 +193,6 @@ module Steep
191
193
  super_method: super_method
192
194
  )
193
195
 
194
- if definition
195
- definition.instance_variables.each do |name, decl|
196
- type_env.set(ivar: name, type: checker.factory.type(decl.type))
197
- end
198
- end
199
-
200
- type_env = type_env.with_annotations(
201
- ivar_types: annots.ivar_types,
202
- const_types: annots.const_types,
203
- self_type: annots.self_type || self_type,
204
- instance_type: module_context.instance_type,
205
- class_type: module_context.module_type
206
- )
207
-
208
- lvar_env = TypeInference::LocalVariableTypeEnv.empty(
209
- subtyping: checker,
210
- self_type: annots.self_type || self_type,
211
- instance_type: module_context.instance_type,
212
- class_type: module_context.module_type
213
- )
214
-
215
196
  method_params =
216
197
  if method_type
217
198
  TypeInference::MethodParams.build(node: node, method_type: method_type)
@@ -219,18 +200,33 @@ module Steep
219
200
  TypeInference::MethodParams.empty(node: node)
220
201
  end
221
202
 
222
- method_params.each_param do |param|
223
- lvar_env = lvar_env.assign(param.name, type: param.var_type, node: param.node) {
224
- raise "Unexpected assignment error: #{param.name}"
225
- }
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
226
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)
227
225
 
228
226
  method_params.errors.each do |error|
229
227
  typing.add_error error
230
228
  end
231
229
 
232
- lvar_env = lvar_env.annotate(annots)
233
-
234
230
  call_context = case self_type
235
231
  when nil
236
232
  TypeInference::MethodCall::UnknownContext.new()
@@ -257,7 +253,6 @@ module Steep
257
253
  break_context: nil,
258
254
  self_type: annots.self_type || self_type,
259
255
  type_env: type_env,
260
- lvar_env: lvar_env,
261
256
  call_context: call_context,
262
257
  variable_context: variable_context
263
258
  ),
@@ -297,9 +292,9 @@ module Steep
297
292
  end
298
293
  end
299
294
 
300
- def default_module_context(implement_module_name, const_env:)
295
+ def default_module_context(implement_module_name, nesting:)
301
296
  if implement_module_name
302
- 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)
303
298
  module_args = implement_module_name.args.map {|name| AST::Types::Var.new(name: name) }
304
299
 
305
300
  instance_def = checker.factory.definition_builder.build_instance(module_name)
@@ -312,7 +307,7 @@ module Steep
312
307
  instance_type: instance_type,
313
308
  module_type: module_type,
314
309
  implement_name: implement_module_name,
315
- const_env: const_env,
310
+ nesting: nesting,
316
311
  class_name: module_name,
317
312
  instance_definition: instance_def,
318
313
  module_definition: module_def
@@ -322,7 +317,7 @@ module Steep
322
317
  instance_type: nil,
323
318
  module_type: nil,
324
319
  implement_name: nil,
325
- const_env: const_env,
320
+ nesting: nesting,
326
321
  class_name: self.module_context.class_name,
327
322
  module_definition: nil,
328
323
  instance_definition: nil
@@ -333,16 +328,10 @@ module Steep
333
328
  def for_module(node, new_module_name)
334
329
  new_nesting = [nesting, new_module_name || false]
335
330
 
336
- module_const_env = TypeInference::ConstantEnv.new(
337
- factory: checker.factory,
338
- context: new_nesting,
339
- resolver: self.module_context.const_env.resolver
340
- )
341
-
342
331
  annots = source.annotations(block: node, factory: checker.factory, context: new_nesting)
343
332
 
344
333
  implement_module_name = implement_module(module_name: new_module_name, annotations: annots)
345
- 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)
346
335
 
347
336
  unless implement_module_name
348
337
  module_context = module_context.update(
@@ -393,18 +382,6 @@ module Steep
393
382
  module_context = module_context.update(module_type: annots.self_type)
394
383
  end
395
384
 
396
- module_type_env = TypeInference::TypeEnv.build(annotations: annots,
397
- subtyping: checker,
398
- const_env: module_const_env,
399
- signatures: checker.factory.env)
400
-
401
- lvar_env = TypeInference::LocalVariableTypeEnv.empty(
402
- subtyping: checker,
403
- self_type: module_context.module_type,
404
- instance_type: module_context.instance_type,
405
- class_type: module_context.module_type
406
- ).annotate(annots)
407
-
408
385
  if implement_module_name
409
386
  definition = checker.factory.definition_builder.build_instance(implement_module_name.name)
410
387
  type_params = definition.type_params_decl.map do |param|
@@ -420,6 +397,20 @@ module Steep
420
397
  variable_context = TypeInference::Context::TypeVariableContext.empty
421
398
  end
422
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
+
423
414
  self.class.new(
424
415
  checker: checker,
425
416
  source: source,
@@ -432,7 +423,6 @@ module Steep
432
423
  module_context: module_context,
433
424
  self_type: module_context.module_type,
434
425
  type_env: module_type_env,
435
- lvar_env: lvar_env,
436
426
  call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name),
437
427
  variable_context: variable_context
438
428
  )
@@ -453,11 +443,11 @@ module Steep
453
443
  class_const_env = TypeInference::ConstantEnv.new(
454
444
  factory: checker.factory,
455
445
  context: new_nesting,
456
- resolver: self.module_context.const_env.resolver
446
+ resolver: context.type_env.constant_env.resolver
457
447
  )
458
448
 
459
449
  implement_module_name = implement_module(module_name: new_class_name, super_name: super_class_name, annotations: annots)
460
- 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)
461
451
 
462
452
  if implement_module_name
463
453
  if super_class_name && implement_module_name.name == absolute_name(super_class_name)
@@ -494,17 +484,13 @@ module Steep
494
484
  end
495
485
  variable_context = TypeInference::Context::TypeVariableContext.new(type_params)
496
486
 
497
- class_type_env = TypeInference::TypeEnv.build(annotations: annots,
498
- subtyping: checker,
499
- const_env: class_const_env,
500
- signatures: checker.factory.env)
501
-
502
- lvar_env = TypeInference::LocalVariableTypeEnv.empty(
503
- subtyping: checker,
504
- self_type: module_context.module_type,
505
- instance_type: module_context.instance_type,
506
- class_type: module_context.module_type
507
- ).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))
508
494
 
509
495
  class_body_context = TypeInference::Context.new(
510
496
  method_context: nil,
@@ -513,7 +499,6 @@ module Steep
513
499
  break_context: nil,
514
500
  self_type: module_context.module_type,
515
501
  type_env: class_type_env,
516
- lvar_env: lvar_env,
517
502
  call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name),
518
503
  variable_context: variable_context
519
504
  )
@@ -580,6 +565,8 @@ module Steep
580
565
  when AST::Types::Name::Instance
581
566
  type_name = instance_type.name
582
567
  checker.factory.definition_builder.build_instance(type_name)
568
+ else
569
+ return
583
570
  end
584
571
 
585
572
  module_definition = case module_type
@@ -594,23 +581,20 @@ module Steep
594
581
  instance_type: annots.instance_type || instance_type,
595
582
  module_type: annots.self_type || annots.module_type || module_type,
596
583
  implement_name: nil,
597
- const_env: self.module_context.const_env,
584
+ nesting: nesting,
598
585
  class_name: self.module_context.class_name,
599
586
  module_definition: module_definition,
600
587
  instance_definition: instance_definition
601
588
  )
602
589
 
603
- type_env = TypeInference::TypeEnv.build(annotations: annots,
604
- subtyping: checker,
605
- const_env: self.module_context.const_env,
606
- signatures: checker.factory.env)
607
-
608
- lvar_env = TypeInference::LocalVariableTypeEnv.empty(
609
- subtyping: checker,
610
- self_type: module_context.module_type,
611
- instance_type: module_context.instance_type,
612
- class_type: module_context.module_type
613
- ).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))
614
598
 
615
599
  body_context = TypeInference::Context.new(
616
600
  method_context: nil,
@@ -619,7 +603,6 @@ module Steep
619
603
  break_context: nil,
620
604
  self_type: module_context.module_type,
621
605
  type_env: type_env,
622
- lvar_env: lvar_env,
623
606
  call_context: TypeInference::MethodCall::ModuleContext.new(type_name: module_context.class_name),
624
607
  variable_context: TypeInference::Context::TypeVariableContext.empty # Assuming `::Class` and `::Module` don't have type params
625
608
  )
@@ -633,39 +616,15 @@ module Steep
633
616
  )
634
617
  end
635
618
 
636
- 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)
637
620
  annots = source.annotations(block: node, factory: checker.factory, context: nesting)
638
621
 
639
- lvar_env = context.lvar_env
640
-
641
- unless truthy_vars.empty?
642
- lvar_env = lvar_env.yield_self do |env|
643
- decls = env.declared_types.each.with_object({}) do |(name, entry), hash|
644
- if truthy_vars.include?(name)
645
- hash[name] = entry.update(type: unwrap(entry.type))
646
- else
647
- hash[name] = entry
648
- end
649
- end
650
-
651
- assignments = env.assigned_types.each.with_object({}) do |(name, entry), hash|
652
- if truthy_vars.include?(name)
653
- hash[name] = entry.update(type: unwrap(entry.type))
654
- else
655
- hash[name] = entry
656
- end
657
- end
658
-
659
- env.update(declared_types: decls, assigned_types: assignments)
660
- end
661
- end
662
-
663
- if type_case_override
664
- lvar_env = type_case_override.inject(lvar_env) do |lvar_env, (name, type)|
665
- lvar_env.assign!(name, node: node, type: type) do |declared_type, assigned_type, result|
666
- 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)
667
626
  typing.add_error(
668
- Diagnostic::Ruby::IncompatibleTypeCase.new(
627
+ Diagnostic::Ruby::IncompatibleAnnotation.new(
669
628
  node: node,
670
629
  var_name: name,
671
630
  relation: relation,
@@ -674,53 +633,11 @@ module Steep
674
633
  )
675
634
  end
676
635
  end
677
- end
678
-
679
- lvar_env = lvar_env.annotate(annots) do |var, outer_type, inner_type, result|
680
- relation = Subtyping::Relation.new(sub_type: inner_type, super_type: outer_type)
681
- typing.add_error(
682
- Diagnostic::Ruby::IncompatibleAnnotation.new(
683
- node: node,
684
- var_name: var,
685
- relation: relation,
686
- result: result
687
- )
688
- )
689
- end
636
+ ).build(context.type_env)
690
637
 
691
- type_env = context.type_env
692
-
693
- if type_case_override
694
- type_env = type_env.with_annotations(
695
- self_type: self_type,
696
- instance_type: module_context.instance_type,
697
- class_type: module_context.module_type
698
- )
638
+ update_context do |context|
639
+ context.with(type_env: type_env, break_context: break_context)
699
640
  end
700
-
701
- type_env = type_env.with_annotations(
702
- ivar_types: annots.ivar_types,
703
- const_types: annots.const_types,
704
- gvar_types: {},
705
- self_type: self_type,
706
- instance_type: module_context.instance_type,
707
- class_type: module_context.module_type
708
- ) do |var, relation, result|
709
- typing.add_error(
710
- Diagnostic::Ruby::IncompatibleAnnotation.new(
711
- node: node,
712
- var_name: var,
713
- relation: relation,
714
- result: result
715
- )
716
- )
717
- end
718
-
719
- update_context {|context|
720
- context.with(type_env: type_env,
721
- break_context: break_context,
722
- lvar_env: lvar_env)
723
- }
724
641
  end
725
642
 
726
643
  def add_typing(node, type:, constr: self)
@@ -776,8 +693,7 @@ module Steep
776
693
 
777
694
  when :lvasgn
778
695
  yield_self do
779
- var, rhs = node.children
780
- name = var
696
+ name, rhs = node.children
781
697
 
782
698
  case name
783
699
  when :_, :__any__
@@ -787,42 +703,56 @@ module Steep
787
703
  when :__skip__
788
704
  add_typing(node, type: AST::Builtin.any_type)
789
705
  else
790
- if declared_type = context.lvar_env.declared_types[name]&.type
791
- case hint
792
- when nil
793
- hint = declared_type
794
- else
795
- if check_relation(sub_type: declared_type, super_type: hint).success?
796
- # declared_type is compatible with hint and more specific to hint.
797
- # This typically happens when hint is untyped, top, or void.
798
- hint = declared_type
799
- 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
800
714
  end
801
715
  end
802
716
 
803
- 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
+ )
804
733
 
805
- constr = rhs_result.constr.update_lvar_env do |lvar_env|
806
- lvar_env.assign(name, node: node, type: rhs_result.type) do |declared_type, actual_type, result|
807
- typing.add_error(
808
- Diagnostic::Ruby::IncompatibleAssignment.new(
809
- node: node,
810
- lhs_type: declared_type,
811
- rhs_type: actual_type,
812
- result: result
813
- )
814
- )
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)
815
743
  end
816
- end
817
744
 
818
- 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
819
749
  end
820
750
  end
821
751
 
822
752
  when :lvar
823
753
  yield_self do
824
754
  var = node.children[0]
825
- if (type = context.lvar_env[var])
755
+ if (type = context.type_env[var])
826
756
  add_typing node, type: type
827
757
  else
828
758
  fallback_to_any(node)
@@ -831,17 +761,21 @@ module Steep
831
761
 
832
762
  when :ivasgn
833
763
  name = node.children[0]
834
- value = node.children[1]
764
+ rhs = node.children[1]
765
+
766
+ rhs_type, constr = synthesize(rhs, hint: context.type_env[name])
835
767
 
836
- type_ivasgn(name, value, node)
768
+ constr.ivasgn(node, rhs_type)
837
769
 
838
770
  when :ivar
839
771
  yield_self do
840
772
  name = node.children[0]
841
- type = type_env.get(ivar: name) do
773
+
774
+ if type = context.type_env[name]
775
+ add_typing(node, type: type)
776
+ else
842
777
  fallback_to_any node
843
778
  end
844
- add_typing(node, type: type)
845
779
  end
846
780
 
847
781
  when :send
@@ -862,22 +796,22 @@ module Steep
862
796
 
863
797
  when :csend
864
798
  yield_self do
865
- pair = if self_class?(node)
866
- module_type = expand_alias(module_context.module_type)
867
- type = if module_type.is_a?(AST::Types::Name::Singleton)
868
- AST::Types::Name::Singleton.new(name: module_type.name)
869
- else
870
- module_type
871
- end
872
- add_typing(node, type: type)
873
- else
874
- type_send(node, send_node: node, block_params: nil, block_body: nil, unwrap: true)
875
- 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
876
811
 
877
- lvar_env = context.lvar_env.join(pair.context.lvar_env, context.lvar_env)
878
- add_typing(node,
879
- type: union_type(pair.type, AST::Builtin.nil_type),
880
- 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))
881
815
  end
882
816
 
883
817
  when :match_with_lvasgn
@@ -1221,35 +1155,30 @@ module Steep
1221
1155
  value = node.children[0]
1222
1156
 
1223
1157
  if break_context
1224
- if break_type = break_context.break_type
1225
- if value
1226
- 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|
1227
1174
  typing.add_error(
1228
- Diagnostic::Ruby::BreakTypeMismatch.new(
1175
+ Diagnostic::Ruby::ImplicitBreakValueMismatch.new(
1229
1176
  node: node,
1230
- expected: break_type,
1231
- actual: actual_type,
1177
+ jump_type: break_type,
1232
1178
  result: result
1233
1179
  )
1234
1180
  )
1235
1181
  end
1236
- else
1237
- unless break_type.is_a?(AST::Types::Bot)
1238
- check_relation(sub_type: AST::Builtin.nil_type, super_type: break_type).else do |result|
1239
- typing.add_error(
1240
- Diagnostic::Ruby::ImplicitBreakValueMismatch.new(
1241
- node: node,
1242
- jump_type: break_type,
1243
- result: result
1244
- )
1245
- )
1246
- end
1247
- end
1248
- end
1249
- else
1250
- if value
1251
- synthesize(value)
1252
- typing.add_error Diagnostic::Ruby::UnexpectedJumpValue.new(node: node)
1253
1182
  end
1254
1183
  end
1255
1184
  else
@@ -1311,7 +1240,7 @@ module Steep
1311
1240
 
1312
1241
  node.children.each do |arg|
1313
1242
  if arg.is_a?(Symbol)
1314
- type = context.lvar_env[arg]
1243
+ type = context.type_env[arg]
1315
1244
 
1316
1245
  if type
1317
1246
  _, constr = add_typing(node, type: type)
@@ -1341,7 +1270,7 @@ module Steep
1341
1270
  when :arg, :kwarg
1342
1271
  yield_self do
1343
1272
  var = node.children[0]
1344
- type = context.lvar_env[var]
1273
+ type = context.type_env[var]
1345
1274
 
1346
1275
  if type
1347
1276
  add_typing(node, type: type)
@@ -1356,7 +1285,7 @@ module Steep
1356
1285
  var = node.children[0]
1357
1286
  rhs = node.children[1]
1358
1287
 
1359
- var_type = context.lvar_env[var]
1288
+ var_type = context.type_env[var]
1360
1289
 
1361
1290
  if var_type
1362
1291
  type, constr = check(rhs, var_type) do |expected_type, actual_type, result|
@@ -1379,9 +1308,10 @@ module Steep
1379
1308
  when :restarg
1380
1309
  yield_self do
1381
1310
  var = node.children[0]
1382
- type = context.lvar_env[var]
1311
+ type = context.type_env[var]
1312
+
1383
1313
  unless type
1384
- if context&.method_context&.method_type
1314
+ if context.method_context&.method_type
1385
1315
  Steep.logger.error { "Unknown variable: #{node}" }
1386
1316
  end
1387
1317
  typing.add_error Diagnostic::Ruby::FallbackAny.new(node: node)
@@ -1394,9 +1324,9 @@ module Steep
1394
1324
  when :kwrestarg
1395
1325
  yield_self do
1396
1326
  var = node.children[0]
1397
- type = context.lvar_env[var]
1327
+ type = context.type_env[var]
1398
1328
  unless type
1399
- if context&.method_context&.method_type
1329
+ if context.method_context&.method_type
1400
1330
  Steep.logger.error { "Unknown variable: #{node}" }
1401
1331
  end
1402
1332
  typing.add_error Diagnostic::Ruby::FallbackAny.new(node: node)
@@ -1448,7 +1378,8 @@ module Steep
1448
1378
  when :true, :false
1449
1379
  ty = node.type == :true ? AST::Types::Literal.new(value: true) : AST::Types::Literal.new(value: false)
1450
1380
 
1451
- 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
+
1452
1383
  add_typing(node, type: hint)
1453
1384
  else
1454
1385
  add_typing(node, type: AST::Types::Boolean.new)
@@ -1569,7 +1500,7 @@ module Steep
1569
1500
 
1570
1501
  when :sclass
1571
1502
  yield_self do
1572
- type, constr = synthesize(node.children[0])
1503
+ type, constr = synthesize(node.children[0]).to_ary
1573
1504
 
1574
1505
  with_sclass_constr(node, type) do |constructor|
1575
1506
  unless constructor
@@ -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,30 +2223,40 @@ 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
@@ -2462,33 +2426,6 @@ module Steep
2462
2426
  end
2463
2427
  end
2464
2428
 
2465
- def type_ivasgn(name, rhs, node)
2466
- rhs_type = synthesize(rhs, hint: type_env.get(ivar: name) { fallback_to_any(node) }).type
2467
-
2468
- ivar_type = type_env.assign(
2469
- ivar: name,
2470
- type: rhs_type,
2471
- self_type: self_type,
2472
- instance_type: module_context.instance_type,
2473
- class_type: module_context.module_type
2474
- ) do |error|
2475
- if error
2476
- type = type_env.get(ivar: name)
2477
- typing.add_error(
2478
- Diagnostic::Ruby::IncompatibleAssignment.new(
2479
- node: node,
2480
- lhs_type: type,
2481
- rhs_type: rhs_type,
2482
- result: error
2483
- )
2484
- )
2485
- else
2486
- fallback_to_any node
2487
- end
2488
- end
2489
- add_typing(node, type: ivar_type)
2490
- end
2491
-
2492
2429
  def masgn_lhs?(lhs)
2493
2430
  lhs.children.all? do |a|
2494
2431
  asgn_type = if a.type == :splat
@@ -2502,233 +2439,140 @@ module Steep
2502
2439
 
2503
2440
  def lvasgn(node, type)
2504
2441
  name = node.children[0]
2505
- env = context.lvar_env.assign(name, node: node, type: type) do |declared_type, type, result|
2506
- typing.add_error(
2507
- Diagnostic::Ruby::IncompatibleAssignment.new(
2508
- node: node,
2509
- lhs_type: declared_type,
2510
- rhs_type: type,
2511
- result: result
2512
- )
2513
- )
2514
- end
2515
2442
 
2516
- add_typing(node, type: type, constr: with_updated_context(lvar_env: env))
2517
- end
2518
-
2519
- def ivasgn(node, type)
2520
- ivar = node.children[0]
2521
-
2522
- type_env.assign(
2523
- ivar: ivar,
2524
- type: type,
2525
- self_type: self_type,
2526
- instance_type: module_context.instance_type,
2527
- class_type: module_context.module_type
2528
- ) do |error|
2529
- if error
2530
- 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)
2531
2445
  typing.add_error(
2532
2446
  Diagnostic::Ruby::IncompatibleAssignment.new(
2533
2447
  node: node,
2534
- lhs_type: var_type,
2448
+ lhs_type: enforced_type,
2535
2449
  rhs_type: type,
2536
- result: error
2450
+ result: result
2537
2451
  )
2538
2452
  )
2539
- else
2540
- fallback_to_any node
2453
+
2454
+ type = enforced_type
2541
2455
  end
2542
2456
  end
2543
2457
 
2544
- add_typing(node, type: type)
2458
+ update_type_env {|env| env.assign_local_variable(name, type, enforced_type) }
2459
+ .add_typing(node, type: type)
2545
2460
  end
2546
2461
 
2547
- def type_masgn(node)
2548
- lhs, rhs = node.children
2549
- rhs_pair = synthesize(rhs)
2550
- rhs_type = deep_expand_alias(rhs_pair.type)
2551
-
2552
- constr = rhs_pair.constr
2553
-
2554
- unless masgn_lhs?(lhs)
2555
- Steep.logger.error("Unsupported masgn lhs node: only lvasgn, ivasgn, and splat are supported")
2556
- _, constr = constr.fallback_to_any(lhs)
2557
- return add_typing(node, type: rhs_type, constr: constr)
2558
- end
2559
-
2560
- falseys, truthys = partition_flatten_types(rhs_type) do |type|
2561
- type.is_a?(AST::Types::Nil) || (type.is_a?(AST::Types::Literal) && type.value == false)
2562
- end
2563
-
2564
- unwrap_rhs_type = AST::Types::Union.build(types: truthys)
2565
-
2566
- case
2567
- when unwrap_rhs_type.is_a?(AST::Types::Tuple) || (rhs.type == :array && rhs.children.none? {|n| n.type == :splat })
2568
- tuple_types = if unwrap_rhs_type.is_a?(AST::Types::Tuple)
2569
- unwrap_rhs_type.types.dup
2570
- else
2571
- rhs.children.map do |node|
2572
- typing.type_of(node: node)
2573
- end
2574
- end
2575
-
2576
- assignment_nodes = lhs.children.dup
2577
- leading_assignments = []
2578
- trailing_assignments = []
2462
+ def ivasgn(node, rhs_type)
2463
+ name = node.children[0]
2579
2464
 
2580
- until assignment_nodes.empty?
2581
- cursor = assignment_nodes.first
2465
+ lhs_type = context.type_env[name]
2582
2466
 
2583
- if cursor.type == :splat
2584
- break
2585
- else
2586
- leading_assignments << assignment_nodes.shift
2587
- 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
+ )
2588
2472
  end
2473
+ else
2474
+ typing.add_error(Diagnostic::Ruby::UnknownInstanceVariable.new(node: node, name: name))
2475
+ end
2589
2476
 
2590
- until assignment_nodes.empty?
2591
- cursor = assignment_nodes.last
2477
+ add_typing(node, type: rhs_type)
2478
+ end
2592
2479
 
2593
- if cursor.type == :splat
2594
- break
2595
- else
2596
- trailing_assignments.unshift assignment_nodes.pop
2597
- end
2598
- end
2480
+ def type_masgn_type(mlhs_node, rhs_type, masgn:, optional:)
2481
+ # @type var constr: TypeConstruction
2482
+ constr = self
2599
2483
 
2600
- leading_assignments.each do |asgn|
2601
- type = tuple_types.first
2484
+ if assignments = masgn.expand(mlhs_node, rhs_type || AST::Builtin.any_type, optional)
2485
+ assignments.each do |pair|
2486
+ node, type = pair
2602
2487
 
2603
- if type
2604
- tuple_types.shift
2605
- else
2606
- type = AST::Builtin.nil_type
2488
+ if assignments.optional
2489
+ type = AST::Builtin.optional(type)
2607
2490
  end
2608
2491
 
2609
- case asgn.type
2610
- when :lvasgn
2611
- _, constr = constr.lvasgn(asgn, type)
2612
- when :ivasgn
2613
- _, constr = constr.ivasgn(asgn, type)
2614
- end
2615
- end
2616
-
2617
- trailing_assignments.reverse_each do |asgn|
2618
- type = tuple_types.last
2619
-
2620
- if type
2621
- 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
2622
2496
  else
2623
- type = AST::Builtin.nil_type
2497
+ asgn_node = node
2498
+ var_type = type
2624
2499
  end
2625
2500
 
2626
- case asgn.type
2501
+ case asgn_node.type
2627
2502
  when :lvasgn
2628
- _, constr = constr.lvasgn(asgn, type)
2503
+ _, constr = constr.lvasgn(asgn_node, type)
2629
2504
  when :ivasgn
2630
- _, 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)
2631
2510
  end
2632
- end
2633
2511
 
2634
- element_type = if tuple_types.empty?
2635
- AST::Builtin.nil_type
2636
- else
2637
- AST::Types::Union.build(types: tuple_types)
2638
- end
2639
- array_type = AST::Builtin::Array.instance_type(element_type)
2640
-
2641
- assignment_nodes.each do |asgn|
2642
- case asgn.type
2643
- when :splat
2644
- case asgn.children[0]&.type
2645
- when :lvasgn
2646
- _, constr = constr.lvasgn(asgn.children[0], array_type)
2647
- when :ivasgn
2648
- _, constr = constr.ivasgn(asgn.children[0], array_type)
2649
- end
2650
- when :lvasgn
2651
- _, constr = constr.lvasgn(asgn, element_type)
2652
- when :ivasgn
2653
- _,constr = constr.ivasgn(asgn, element_type)
2512
+ if node.type == :splat
2513
+ _, constr = constr.add_typing(node, type: type)
2654
2514
  end
2655
2515
  end
2656
2516
 
2657
- unless falseys.empty?
2658
- constr = constr.update_lvar_env {|lvar_env| self.context.lvar_env.join(lvar_env, self.context.lvar_env)}
2659
- end
2660
-
2661
- add_typing(node, type: rhs_type, constr: constr)
2517
+ constr
2518
+ end
2519
+ end
2662
2520
 
2663
- when flatten_union(unwrap_rhs_type).all? {|type| AST::Builtin::Array.instance_type?(type) }
2664
- array_elements = flatten_union(unwrap_rhs_type).map {|type| type.args[0] }
2665
- element_type = AST::Types::Union.build(types: array_elements + [AST::Builtin.nil_type])
2521
+ def type_masgn(node)
2522
+ lhs, rhs = node.children
2666
2523
 
2667
- constr = lhs.children.inject(constr) do |constr, assignment|
2668
- case assignment.type
2669
- when :lvasgn
2670
- _, constr = constr.lvasgn(assignment, element_type)
2524
+ masgn = TypeInference::MultipleAssignment.new()
2525
+ hint = masgn.hint_for_mlhs(lhs, context.type_env)
2671
2526
 
2672
- when :ivasgn
2673
- _, constr = constr.ivasgn(assignment, element_type)
2674
- when :splat
2675
- case assignment.children[0]&.type
2676
- when :lvasgn
2677
- _, constr = constr.lvasgn(assignment.children[0], unwrap_rhs_type)
2678
- when :ivasgn
2679
- _, constr = constr.ivasgn(assignment.children[0], unwrap_rhs_type)
2680
- when nil
2681
- # foo, * = bar
2682
- else
2683
- raise
2684
- end
2685
- end
2527
+ rhs_type, lhs_constr = try_tuple_type!(rhs, hint: hint).to_ary
2528
+ rhs_type = deep_expand_alias(rhs_type)
2686
2529
 
2687
- constr
2688
- 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
2689
2533
 
2690
- unless falseys.empty?
2691
- constr = constr.update_lvar_env {|lvar_env| self.context.lvar_env.join(lvar_env, self.context.lvar_env)}
2692
- end
2534
+ truthy_rhs_type = AST::Types::Union.build(types: truthys)
2535
+ optional = !falsys.empty?
2693
2536
 
2694
- 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)
2695
2539
  else
2696
- unless rhs_type.is_a?(AST::Types::Any)
2697
- Steep.logger.error("Unsupported masgn rhs type: array or tuple is supported (#{rhs_type})")
2698
- 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
2543
+
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
+ )
2699
2552
 
2700
- untyped = AST::Builtin.any_type
2553
+ constr = lhs_constr
2701
2554
 
2702
- constr = lhs.children.inject(constr) do |constr, assignment|
2703
- case assignment.type
2555
+ each_descendant_node(lhs) do |node|
2556
+ case node.type
2704
2557
  when :lvasgn
2705
- _, constr = constr.lvasgn(assignment, untyped)
2558
+ _, constr = constr.lvasgn(node, AST::Builtin.any_type).to_ary
2706
2559
  when :ivasgn
2707
- _, constr = constr.ivasgn(assignment, untyped)
2708
- when :splat
2709
- case assignment.children[0]&.type
2710
- when :lvasgn
2711
- _, constr = constr.lvasgn(assignment.children[0], untyped)
2712
- when :ivasgn
2713
- _, constr = constr.ivasgn(assignment.children[0], untyped)
2714
- when nil
2715
- # foo, * = bar
2716
- else
2717
- raise
2718
- 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
2719
2565
  end
2720
-
2721
- constr
2722
2566
  end
2723
-
2724
- add_typing(node, type: rhs_type, constr: constr)
2725
2567
  end
2568
+
2569
+ constr.add_typing(node, type: truthy_rhs_type)
2726
2570
  end
2727
2571
 
2728
2572
  def synthesize_constant(node, parent_node, constant_name)
2729
2573
  const_name = module_name_from_node(parent_node, constant_name)
2730
2574
 
2731
- if const_name && type = type_env.get(const: const_name) { break }
2575
+ if const_name && type = context.type_env.annotated_constant(const_name)
2732
2576
  # const-type annotation wins
2733
2577
  if node
2734
2578
  constr = synthesize_children(node)
@@ -2742,7 +2586,7 @@ module Steep
2742
2586
  when !parent_node
2743
2587
  constr = self
2744
2588
 
2745
- if (type, name = module_context.const_env.resolve(constant_name))
2589
+ if (type, name = context.type_env.constant(constant_name, false))
2746
2590
  if node
2747
2591
  _, constr = add_typing(node, type: type)
2748
2592
  end
@@ -2752,7 +2596,7 @@ module Steep
2752
2596
  when parent_node.type == :cbase
2753
2597
  _, constr = add_typing(parent_node, type: AST::Builtin.nil_type)
2754
2598
 
2755
- if (type, name = constr.module_context.const_env.toplevel(constant_name))
2599
+ if (type, name = constr.context.type_env.constant(constant_name, true))
2756
2600
  if node
2757
2601
  _, constr = constr.add_typing(node, type: type)
2758
2602
  end
@@ -2760,12 +2604,12 @@ module Steep
2760
2604
  return [type, constr, name]
2761
2605
  end
2762
2606
  else
2763
- parent_type, constr = synthesize(parent_node)
2607
+ parent_type, constr = synthesize(parent_node).to_ary
2764
2608
  parent_type = deep_expand_alias(parent_type)
2765
2609
 
2766
2610
  case parent_type
2767
2611
  when AST::Types::Name::Singleton
2768
- 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))
2769
2613
  if node
2770
2614
  _, constr = add_typing(node, type: type)
2771
2615
  end
@@ -2827,6 +2671,7 @@ module Steep
2827
2671
  end
2828
2672
 
2829
2673
  block_constr = for_block(
2674
+ body_node,
2830
2675
  block_params: params,
2831
2676
  block_param_hint: params_hint,
2832
2677
  block_type_hint: return_hint,
@@ -2881,6 +2726,10 @@ module Steep
2881
2726
  )
2882
2727
 
2883
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
+
2884
2733
  check_relation(sub_type: return_type, super_type: expected_block_type).else do |result|
2885
2734
  block_constr.typing.add_error(
2886
2735
  Diagnostic::Ruby::BlockBodyTypeMismatch.new(
@@ -2924,6 +2773,20 @@ module Steep
2924
2773
  constr
2925
2774
  end
2926
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
+
2927
2790
  def type_send_interface(node, interface:, receiver:, receiver_type:, method_name:, arguments:, block_params:, block_body:)
2928
2791
  method = interface.methods[method_name]
2929
2792
 
@@ -2940,8 +2803,28 @@ module Steep
2940
2803
  if call && constr
2941
2804
  case method_name.to_s
2942
2805
  when "[]=", /\w=\Z/
2943
- if typing.has_type?(arguments.last)
2944
- 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
2945
2828
  end
2946
2829
  end
2947
2830
 
@@ -3000,6 +2883,17 @@ module Steep
3000
2883
  )
3001
2884
  end
3002
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
+
3003
2897
  constr.add_call(
3004
2898
  TypeInference::MethodCall::NoMethodError.new(
3005
2899
  node: node,
@@ -3277,7 +3171,7 @@ module Steep
3277
3171
 
3278
3172
  [
3279
3173
  call,
3280
- update_lvar_env { constr.context.lvar_env }
3174
+ update_type_env { constr.context.type_env }
3281
3175
  ]
3282
3176
  end
3283
3177
 
@@ -3344,6 +3238,15 @@ module Steep
3344
3238
 
3345
3239
  constr = self
3346
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
+
3347
3250
  method_type = method_type.instantiate(instantiation)
3348
3251
 
3349
3252
  variance = Subtyping::VariableVariance.from_method_type(method_type)
@@ -3463,6 +3366,7 @@ module Steep
3463
3366
  if pairs
3464
3367
  # Block parameters are compatible with the block type
3465
3368
  block_constr = constr.for_block(
3369
+ block_body,
3466
3370
  block_params: block_params_,
3467
3371
  block_param_hint: method_type.block.type.params,
3468
3372
  block_type_hint: method_type.block.type.return_type,
@@ -3471,15 +3375,13 @@ module Steep
3471
3375
  node_type_hint: method_type.type.return_type
3472
3376
  )
3473
3377
  block_constr = block_constr.with_new_typing(
3474
- block_constr.typing.new_child(
3475
- range: block_constr.typing.block_range(node)
3476
- )
3378
+ block_constr.typing.new_child(block_constr.typing.block_range(node))
3477
3379
  )
3478
3380
 
3479
3381
  block_constr.typing.add_context_for_body(node, context: block_constr.context)
3480
3382
 
3481
3383
  pairs.each do |param, type|
3482
- _, 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
3483
3385
 
3484
3386
  if param.type
3485
3387
  check_relation(sub_type: type, super_type: param.type, constraints: constraints).else do |result|
@@ -3504,16 +3406,20 @@ module Steep
3504
3406
 
3505
3407
  if solved
3506
3408
  # Ready for type check the body of the block
3507
- block_constr = block_constr.update_lvar_env {|env| env.subst(s) }
3508
- if block_body
3509
- block_body_type = block_constr.synthesize_block(
3510
- node: node,
3511
- block_body: block_body,
3512
- 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)
3513
3415
  )
3514
- else
3515
- block_body_type = AST::Builtin.nil_type
3516
- 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
+ )
3517
3423
 
3518
3424
  result = check_relation(sub_type: block_body_type,
3519
3425
  super_type: method_type.block.type.return_type,
@@ -3574,10 +3480,20 @@ module Steep
3574
3480
  errors << error
3575
3481
  end
3576
3482
 
3577
- errors << Diagnostic::Ruby::UnexpectedBlockGiven.new(
3578
- node: node,
3579
- method_type: method_type
3580
- )
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
3581
3497
 
3582
3498
  method_type = eliminate_vars(method_type, type_param_names)
3583
3499
  return_type = method_type.type.return_type
@@ -3689,6 +3605,12 @@ module Steep
3689
3605
  )
3690
3606
  end
3691
3607
 
3608
+ constr = constr.with(
3609
+ context: constr.context.with(
3610
+ variable_context: context.variable_context
3611
+ )
3612
+ )
3613
+
3692
3614
  [
3693
3615
  call,
3694
3616
  constr
@@ -3720,12 +3642,13 @@ module Steep
3720
3642
  end
3721
3643
 
3722
3644
  block_constr = for_block(
3645
+ block_body,
3723
3646
  block_params: block_params,
3724
3647
  block_param_hint: nil,
3725
- block_type_hint: AST::Builtin.any_type,
3648
+ block_type_hint: nil,
3726
3649
  block_block_hint: nil,
3727
3650
  block_annotations: block_annotations,
3728
- node_type_hint: AST::Builtin.any_type
3651
+ node_type_hint: nil
3729
3652
  )
3730
3653
 
3731
3654
  block_constr.typing.add_context_for_body(node, context: block_constr.context)
@@ -3750,7 +3673,7 @@ module Steep
3750
3673
  end
3751
3674
  end
3752
3675
 
3753
- 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:)
3754
3677
  block_param_pairs = block_param_hint && block_params.zip(block_param_hint, block_block_hint)
3755
3678
 
3756
3679
  param_types_hash = {}
@@ -3766,14 +3689,32 @@ module Steep
3766
3689
  end
3767
3690
  end
3768
3691
 
3769
- decls = param_types_hash.each.with_object({}) do |(name, type), hash|
3770
- 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]
3771
3696
  end
3772
- lvar_env = context.lvar_env
3773
- .pin_assignments
3774
- .except(decls.keys)
3775
- .update(assigned_types: decls)
3776
- .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)
3777
3718
 
3778
3719
  break_type = if block_annotations.break_type
3779
3720
  union_type(node_type_hint, block_annotations.break_type)
@@ -3782,21 +3723,18 @@ module Steep
3782
3723
  end
3783
3724
 
3784
3725
  block_context = TypeInference::Context::BlockContext.new(
3785
- body_type: block_annotations.block_type || block_type_hint || AST::Builtin.any_type
3726
+ body_type: block_annotations.block_type || block_type_hint
3786
3727
  )
3787
3728
  break_context = TypeInference::Context::BreakContext.new(
3788
- break_type: break_type,
3789
- 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
3790
3731
  )
3791
3732
 
3792
3733
  self_type = self.self_type
3793
3734
  module_context = self.module_context
3794
3735
 
3795
3736
  if implements = block_annotations.implement_module_annotation
3796
- module_context = default_module_context(
3797
- implements.name,
3798
- const_env: self.module_context.const_env
3799
- )
3737
+ module_context = default_module_context(implements.name, nesting: nesting)
3800
3738
 
3801
3739
  self_type = module_context.module_type
3802
3740
  end
@@ -3816,8 +3754,7 @@ module Steep
3816
3754
  module_context: module_context,
3817
3755
  break_context: break_context,
3818
3756
  self_type: self_type,
3819
- type_env: type_env.dup,
3820
- lvar_env: lvar_env,
3757
+ type_env: type_env,
3821
3758
  call_context: self.context.call_context,
3822
3759
  variable_context: variable_context
3823
3760
  )
@@ -3837,35 +3774,10 @@ module Steep
3837
3774
  end
3838
3775
  end
3839
3776
 
3840
- def each_child_node(node)
3841
- if block_given?
3842
- node.children.each do |child|
3843
- if child.is_a?(::AST::Node)
3844
- yield child
3845
- end
3846
- end
3847
- else
3848
- enum_for :each_child_node, node
3849
- end
3850
- end
3851
-
3852
3777
  def nesting
3853
3778
  module_context&.nesting
3854
3779
  end
3855
3780
 
3856
- def absolute_nested_module_name(module_name)
3857
- n = nesting
3858
- while n && !n[1]
3859
- n = n[0]
3860
- end
3861
-
3862
- if n
3863
- module_name.absolute!
3864
- else
3865
- n + module_name
3866
- end
3867
- end
3868
-
3869
3781
  def absolute_name(name)
3870
3782
  checker.factory.absolute_type_name(name, context: nesting)
3871
3783
  end
@@ -4062,12 +3974,14 @@ module Steep
4062
3974
  end
4063
3975
 
4064
3976
  def try_tuple_type!(node, hint: nil)
4065
- if node.type == :array && (hint.nil? || hint.is_a?(AST::Types::Tuple))
4066
- 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 }
4067
3980
 
4068
- typing.new_child(node_range) do |child_typing|
4069
- if pair = with_new_typing(child_typing).try_tuple_type(node, hint)
4070
- 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
4071
3985
  end
4072
3986
  end
4073
3987
  end
@@ -4102,13 +4016,13 @@ module Steep
4102
4016
  return
4103
4017
  end
4104
4018
 
4105
- interface = checker.factory.interface(type, private: false)
4019
+ interface = checker.factory.interface(type, private: false, self_type: self_type)
4106
4020
  if entry = interface.methods[method]
4107
4021
  method_type = entry.method_types.find do |method_type|
4108
4022
  method_type.type.params.optional?
4109
4023
  end
4110
4024
 
4111
- method_type.type.return_type
4025
+ method_type.type.return_type if method_type
4112
4026
  end
4113
4027
  rescue => exn
4114
4028
  Steep.log_error(exn, message: "Unexpected error when converting #{type.to_s} with #{method}")
@@ -4146,20 +4060,15 @@ module Steep
4146
4060
  constr.add_typing(node, type: AST::Builtin::Array.instance_type(element_type))
4147
4061
  end
4148
4062
 
4149
- # Try to give record type to hash_node.
4150
- #
4151
- # Returns nil when it cannot have a record type.
4152
- # `record_type` can be nil when the keys are not specified.
4153
- #
4154
4063
  def type_hash_record(hash_node, record_type)
4155
4064
  raise unless hash_node.type == :hash || hash_node.type == :kwargs
4156
4065
 
4157
4066
  constr = self
4158
4067
 
4159
4068
  if record_type
4160
- elements = record_type.elements.dup
4069
+ hints = record_type.elements.dup
4161
4070
  else
4162
- elements = {}
4071
+ hints = {}
4163
4072
  end
4164
4073
 
4165
4074
  elems = {}
@@ -4174,7 +4083,18 @@ module Steep
4174
4083
  key = key_node.children[0]
4175
4084
 
4176
4085
  _, constr = constr.synthesize(key_node, hint: AST::Types::Literal.new(value: key))
4177
- 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
4178
4098
 
4179
4099
  elems[key] = value_type
4180
4100
  else
@@ -4277,11 +4197,11 @@ module Steep
4277
4197
  def pick_one_of(types, range:)
4278
4198
  types.each do |type|
4279
4199
  with_child_typing(range: range) do |constr|
4280
- type_, constr = yield type, constr
4281
-
4282
- constr.check_relation(sub_type: type_, super_type: type).then do
4283
- constr = constr.save_typing
4284
- 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
4285
4205
  end
4286
4206
  end
4287
4207
  end