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
@@ -5,8 +5,6 @@ module Steep
5
5
  attr_reader :factory
6
6
  attr_reader :resolver
7
7
 
8
- # ConstantEnv receives an TypeName as a context, not a Namespace, because this is a simulation of Ruby.
9
- # Any namespace is a module or class.
10
8
  def initialize(factory:, context:, resolver:)
11
9
  @cache = {}
12
10
  @factory = factory
@@ -29,6 +29,10 @@ module Steep
29
29
  def initialize(body_type:)
30
30
  @body_type = body_type
31
31
  end
32
+
33
+ def subst(s)
34
+ BlockContext.new(body_type: body_type&.subst(s))
35
+ end
32
36
  end
33
37
 
34
38
  class BreakContext
@@ -39,6 +43,10 @@ module Steep
39
43
  @break_type = break_type
40
44
  @next_type = next_type
41
45
  end
46
+
47
+ def subst(s)
48
+ BreakContext.new(break_type: break_type.subst(s), next_type: next_type&.subst(s))
49
+ end
42
50
  end
43
51
 
44
52
  class ModuleContext
@@ -46,28 +54,24 @@ module Steep
46
54
  attr_reader :module_type
47
55
  attr_reader :defined_instance_methods
48
56
  attr_reader :defined_module_methods
49
- attr_reader :const_env
57
+ attr_reader :nesting
50
58
  attr_reader :implement_name
51
59
  attr_reader :class_name
52
60
  attr_reader :instance_definition
53
61
  attr_reader :module_definition
54
62
 
55
- def initialize(instance_type:, module_type:, implement_name:, const_env:, class_name:, instance_definition: nil, module_definition: nil)
63
+ def initialize(instance_type:, module_type:, implement_name:, class_name:, instance_definition: nil, module_definition: nil, nesting:)
56
64
  @instance_type = instance_type
57
65
  @module_type = module_type
58
66
  @defined_instance_methods = Set.new
59
67
  @defined_module_methods = Set.new
60
68
  @implement_name = implement_name
61
- @const_env = const_env
69
+ @nesting = nesting
62
70
  @class_name = class_name
63
71
  @instance_definition = instance_definition
64
72
  @module_definition = module_definition
65
73
  end
66
74
 
67
- def nesting
68
- const_env.context
69
- end
70
-
71
75
  def class_variables
72
76
  if module_definition
73
77
  @class_variables ||= module_definition.class_variables.transform_values do |var_def|
@@ -80,16 +84,16 @@ module Steep
80
84
  instance_type: self.instance_type,
81
85
  module_type: self.module_type,
82
86
  implement_name: self.implement_name,
83
- const_env: self.const_env,
84
87
  class_name: self.class_name,
85
88
  instance_definition: self.instance_definition,
86
- module_definition: self.module_definition
89
+ module_definition: self.module_definition,
90
+ nesting: self.nesting
87
91
  )
88
92
  ModuleContext.new(
89
93
  instance_type: instance_type,
90
94
  module_type: module_type,
91
95
  implement_name: implement_name,
92
- const_env: const_env,
96
+ nesting: nesting,
93
97
  class_name: class_name,
94
98
  instance_definition: instance_definition,
95
99
  module_definition: module_definition
@@ -134,17 +138,15 @@ module Steep
134
138
  attr_reader :module_context
135
139
  attr_reader :self_type
136
140
  attr_reader :type_env
137
- attr_reader :lvar_env
138
141
  attr_reader :variable_context
139
142
 
140
- def initialize(method_context:, block_context:, break_context:, module_context:, self_type:, type_env:, lvar_env:, call_context:, variable_context:)
143
+ def initialize(method_context:, block_context:, break_context:, module_context:, self_type:, type_env:, call_context:, variable_context:)
141
144
  @method_context = method_context
142
145
  @block_context = block_context
143
146
  @break_context = break_context
144
147
  @module_context = module_context
145
148
  @self_type = self_type
146
149
  @type_env = type_env
147
- @lvar_env = lvar_env
148
150
  @call_context = call_context
149
151
  @variable_context = variable_context
150
152
  end
@@ -155,7 +157,6 @@ module Steep
155
157
  module_context: self.module_context,
156
158
  self_type: self.self_type,
157
159
  type_env: self.type_env,
158
- lvar_env: self.lvar_env,
159
160
  call_context: self.call_context,
160
161
  variable_context: self.variable_context)
161
162
  self.class.new(
@@ -165,18 +166,23 @@ module Steep
165
166
  module_context: module_context,
166
167
  self_type: self_type,
167
168
  type_env: type_env,
168
- lvar_env: lvar_env,
169
169
  call_context: call_context,
170
170
  variable_context: variable_context
171
171
  )
172
172
  end
173
173
 
174
+ def inspect
175
+ s = "#<%s:%#018x " % [self.class, object_id]
176
+ s << instance_variables.map(&:to_s).sort.map {|name| "#{name}=..." }.join(", ")
177
+ s + ">"
178
+ end
179
+
174
180
  def factory
175
- type_env.subtyping.factory
181
+ type_env.constant_env.factory
176
182
  end
177
183
 
178
184
  def env
179
- type_env.subtyping.factory.env
185
+ factory.env
180
186
  end
181
187
  end
182
188
  end
@@ -29,134 +29,202 @@ module Steep
29
29
  end
30
30
  end
31
31
 
32
- def eval(env:, type:, node:)
33
- value_node, vars = decompose_value(node)
32
+ def eval(env:, node:)
33
+ objects = Set[]
34
+ truthy_type, falsy_type, truthy_env, falsy_env = evaluate_node(env: env, node: node, refined_objects: objects)
34
35
 
35
- truthy_env = env
36
- falsy_env = env
36
+ [truthy_env, falsy_env, objects, truthy_type, falsy_type]
37
+ end
38
+
39
+ def evaluate_node(env:, node:, refined_objects:)
40
+ type = typing.type_of(node: node)
41
+
42
+ if type.is_a?(AST::Types::Logic::Env)
43
+ truthy_env = type.truthy
44
+ falsy_env = type.falsy
37
45
 
38
- if type.is_a?(AST::Types::Any)
39
- type = guess_type_from_method(node) || type
46
+ return [AST::Types::Boolean.new, AST::Types::Boolean.new, truthy_env, falsy_env]
40
47
  end
41
48
 
42
- if type.is_a?(AST::Types::Logic::Base)
43
- vars.each do |var_name|
44
- var_type = truthy_env[var_name]
45
- truthy_type, falsy_type = factory.unwrap_optional(var_type)
46
- falsy_type ||= AST::Builtin.nil_type
47
- truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type) {|_, type, _| type }
48
- falsy_env = truthy_env.assign!(var_name, node: node, type: falsy_type) {|_, type, _| type }
49
+ case node.type
50
+ when :lvar
51
+ name = node.children[0]
52
+ refined_objects << name
53
+ truthy_type, falsy_type = factory.unwrap_optional(type)
54
+ return [
55
+ truthy_type,
56
+ falsy_type,
57
+ env.refine_types(local_variable_types: { name => truthy_type }),
58
+ env.refine_types(local_variable_types: { name => falsy_type })
59
+ ]
60
+ when :lvasgn
61
+ name, rhs = node.children
62
+ truthy_type, falsy_type, truthy_env, falsy_env = evaluate_node(env: env, node: rhs, refined_objects: refined_objects)
63
+ return [
64
+ truthy_type,
65
+ falsy_type,
66
+ evaluate_assignment(node, truthy_env, truthy_type, refined_objects: refined_objects),
67
+ evaluate_assignment(node, falsy_env, falsy_type, refined_objects: refined_objects)
68
+ ]
69
+ when :masgn
70
+ lhs, rhs = node.children
71
+ truthy_type, falsy_type, truthy_env, falsy_env = evaluate_node(env: env, node: rhs, refined_objects: refined_objects)
72
+ return [
73
+ truthy_type,
74
+ falsy_type,
75
+ evaluate_assignment(node, truthy_env, truthy_type, refined_objects: refined_objects),
76
+ evaluate_assignment(node, falsy_env, falsy_type, refined_objects: refined_objects)
77
+ ]
78
+ when :begin
79
+ last_node = node.children.last or raise
80
+ return evaluate_node(env: env, node: last_node, refined_objects: refined_objects)
81
+ when :send
82
+ if type.is_a?(AST::Types::Any)
83
+ type = guess_type_from_method(node) || type
49
84
  end
50
85
 
51
86
  case type
52
- when AST::Types::Logic::Env
53
- truthy_env = type.truthy
54
- falsy_env = type.falsy
55
- when AST::Types::Logic::ReceiverIsNil
56
- case value_node.type
57
- when :send
58
- receiver = value_node.children[0]
59
-
60
- if receiver
61
- _, receiver_vars = decompose_value(receiver)
62
-
63
- receiver_vars.each do |receiver_var|
64
- var_type = env[receiver_var]
65
- truthy_type, falsy_type = factory.unwrap_optional(var_type)
66
-
67
- truthy_env = truthy_env.assign!(receiver_var, node: node, type: falsy_type || AST::Builtin.nil_type)
68
- falsy_env = falsy_env.assign!(receiver_var, node: node, type: truthy_type)
69
- end
70
- end
71
- end
72
- when AST::Types::Logic::ReceiverIsArg
73
- case value_node.type
74
- when :send
75
- receiver, _, arg = value_node.children
76
-
77
- if receiver
78
- _, receiver_vars = decompose_value(receiver)
79
- arg_type = typing.type_of(node: arg)
80
-
81
- if arg_type.is_a?(AST::Types::Name::Singleton)
82
- receiver_vars.each do |var_name|
83
- case var_name
84
- when :_, :__any__, :__skip__
85
- # skip
86
- else
87
- var_type = env[var_name]
88
- truthy_type, falsy_type = type_case_select(var_type, arg_type.name)
89
-
90
- truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type)
91
- falsy_env = falsy_env.assign!(var_name, node: node, type: falsy_type)
92
- end
93
- end
94
- end
95
- end
87
+ when AST::Types::Logic::Base
88
+ receiver, _, *arguments = node.children
89
+ truthy_env, falsy_env = evaluate_method_call(env: env, type: type, receiver: receiver, arguments: arguments, refined_objects: refined_objects)
90
+
91
+ if truthy_env && falsy_env
92
+ return [AST::Builtin.true_type, AST::Builtin.false_type, truthy_env, falsy_env]
96
93
  end
97
- when AST::Types::Logic::ArgIsReceiver
98
- case value_node.type
99
- when :send
100
- receiver, _, arg = value_node.children
101
-
102
- if receiver
103
- _, arg_vars = decompose_value(arg)
104
- receiver_type = factory.deep_expand_alias(typing.type_of(node: receiver))
105
-
106
- if receiver_type.is_a?(AST::Types::Name::Singleton)
107
- arg_vars.each do |var_name|
108
- var_type = env[var_name]
109
- truthy_type, falsy_type = type_case_select(var_type, receiver_type.name)
110
-
111
- truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type)
112
- falsy_env = falsy_env.assign!(var_name, node: node, type: falsy_type)
113
- end
114
- end
115
- end
94
+ else
95
+ if env[node]
96
+ truthy_type, falsy_type = factory.unwrap_optional(type)
97
+
98
+ refined_objects << node
99
+ return [
100
+ truthy_type,
101
+ falsy_type,
102
+ env.refine_types(pure_call_types: { node => truthy_type }),
103
+ env.refine_types(pure_call_types: { node => falsy_type })
104
+ ]
116
105
  end
117
- when AST::Types::Logic::ArgEqualsReceiver
118
- case value_node.type
119
- when :send
120
- receiver, _, arg = value_node.children
106
+ end
107
+ end
121
108
 
122
- if receiver
123
- _, arg_vars = decompose_value(arg)
109
+ truthy_type, falsy_type = factory.unwrap_optional(type)
110
+ return [truthy_type, falsy_type, env, env]
111
+ end
124
112
 
125
- arg_vars.each do |var_name|
126
- var_type = factory.deep_expand_alias(env[var_name])
127
- truthy_types, falsy_types = literal_var_type_case_select(receiver, var_type)
113
+ def evaluate_assignment(assignment_node, env, rhs_type, refined_objects:)
114
+ case assignment_node.type
115
+ when :lvasgn
116
+ name, _ = assignment_node.children
117
+ refined_objects << name
118
+ env.refine_types(local_variable_types: { name => rhs_type })
119
+ when :masgn
120
+ lhs, _ = assignment_node.children
121
+
122
+ masgn = MultipleAssignment.new()
123
+ assignments = masgn.expand(lhs, rhs_type, false)
124
+ unless assignments
125
+ rhs_type_converted = try_convert(rhs_type, :to_ary)
126
+ rhs_type_converted ||= try_convert(rhs_type, :to_a)
127
+ rhs_type_converted ||= AST::Types::Tuple.new(types: [rhs_type])
128
+ assignments = masgn.expand(lhs, rhs_type_converted, false)
129
+ end
128
130
 
129
- truthy_env = truthy_env.assign!(var_name, node: node, type: AST::Types::Union.build(types: truthy_types, location: nil))
130
- falsy_env = falsy_env.assign!(var_name, node: node, type: AST::Types::Union.build(types: falsy_types, location: nil))
131
- end
132
- end
133
- end
134
- when AST::Types::Logic::Not
135
- case value_node.type
136
- when :send
137
- receiver, * = value_node.children
138
- receiver_type = typing.type_of(node: receiver)
139
- falsy_env, truthy_env = eval(env: env, type: receiver_type, node: receiver)
140
- end
131
+ assignments or raise
132
+
133
+ assignments.each do |pair|
134
+ node, type = pair
135
+ env = evaluate_assignment(node, env, type, refined_objects: refined_objects)
141
136
  end
137
+
138
+ env
142
139
  else
143
- _, vars = decompose_value(node)
140
+ env
141
+ end
142
+ end
144
143
 
145
- vars.each do |var_name|
146
- var_type = env[var_name]
147
- truthy_type, falsy_type = factory.unwrap_optional(var_type)
144
+ def refine_node_type(env:, node:, truthy_type:, falsy_type:, refined_objects:)
145
+ case node.type
146
+ when :lvar
147
+ name = node.children[0]
148
148
 
149
- if falsy_type
150
- truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type)
151
- falsy_env = falsy_env.assign!(var_name, node: node, type: falsy_type)
152
- else
153
- truthy_env = truthy_env.assign!(var_name, node: node, type: truthy_type)
154
- falsy_env = falsy_env.assign!(var_name, node: node, type: truthy_type)
155
- end
149
+ refined_objects << name
150
+ [
151
+ env.refine_types(local_variable_types: { name => truthy_type }),
152
+ env.refine_types(local_variable_types: { name => falsy_type })
153
+ ]
154
+ when :lvasgn
155
+ name, rhs = node.children
156
+
157
+ truthy_env, falsy_env = refine_node_type(env: env, node: rhs, truthy_type: truthy_type, falsy_type: falsy_type, refined_objects: refined_objects)
158
+ refined_objects << name
159
+ [
160
+ truthy_env.refine_types(local_variable_types: { name => truthy_type }),
161
+ falsy_env.refine_types(local_variable_types: { name => falsy_type })
162
+ ]
163
+ when :send
164
+ if env[node]
165
+ refined_objects << node
166
+ [
167
+ env.refine_types(pure_call_types: { node => truthy_type }),
168
+ env.refine_types(pure_call_types: { node => falsy_type })
169
+ ]
170
+ else
171
+ [env, env]
156
172
  end
173
+ when :begin
174
+ last_node = node.children.last or raise
175
+ refine_node_type(env: env, node: last_node, truthy_type: truthy_type, falsy_type: falsy_type, refined_objects: refined_objects)
176
+ else
177
+ [env, env]
157
178
  end
179
+ end
158
180
 
159
- [truthy_env, falsy_env]
181
+ def evaluate_method_call(env:, type:, receiver:, arguments:, refined_objects:)
182
+ case type
183
+ when AST::Types::Logic::ReceiverIsNil
184
+ if receiver && arguments.size.zero?
185
+ receiver_type = typing.type_of(node: receiver)
186
+ truthy_receiver, falsy_receiver = factory.unwrap_optional(receiver_type)
187
+ refine_node_type(env: env, node: receiver, truthy_type: falsy_receiver, falsy_type: truthy_receiver, refined_objects: refined_objects)
188
+ end
189
+ when AST::Types::Logic::ReceiverIsArg
190
+ if receiver && (arg = arguments[0])
191
+ receiver_type = typing.type_of(node: receiver)
192
+ arg_type = factory.deep_expand_alias(typing.type_of(node: arg))
193
+
194
+ if arg_type.is_a?(AST::Types::Name::Singleton)
195
+ truthy_type, falsy_type = type_case_select(receiver_type, arg_type.name)
196
+ refine_node_type(env: env, node: receiver, truthy_type: truthy_type, falsy_type: falsy_type, refined_objects: refined_objects)
197
+ end
198
+ end
199
+ when AST::Types::Logic::ArgIsReceiver
200
+ if receiver && (arg = arguments[0])
201
+ receiver_type = factory.deep_expand_alias(typing.type_of(node: receiver))
202
+ arg_type = typing.type_of(node: arg)
203
+
204
+ if receiver_type.is_a?(AST::Types::Name::Singleton)
205
+ truthy_type, falsy_type = type_case_select(arg_type, receiver_type.name)
206
+ refine_node_type(env: env, node: arg, truthy_type: truthy_type, falsy_type: falsy_type, refined_objects: refined_objects)
207
+ end
208
+ end
209
+ when AST::Types::Logic::ArgEqualsReceiver
210
+ if receiver && (arg = arguments[0])
211
+ arg_type = factory.expand_alias(typing.type_of(node: arg))
212
+ if (truthy_types, falsy_types = literal_var_type_case_select(receiver, arg_type))
213
+ refine_node_type(
214
+ env: env,
215
+ node: arg,
216
+ truthy_type: AST::Types::Union.build(types: truthy_types),
217
+ falsy_type: AST::Types::Union.build(types: falsy_types),
218
+ refined_objects: refined_objects
219
+ )
220
+ end
221
+ end
222
+ when AST::Types::Logic::Not
223
+ if receiver
224
+ truthy_type, falsy_type, truthy_env, falsy_env = evaluate_node(env: env, node: receiver, refined_objects: refined_objects)
225
+ [falsy_env, truthy_env]
226
+ end
227
+ end
160
228
  end
161
229
 
162
230
  def decompose_value(node)
@@ -164,10 +232,8 @@ module Steep
164
232
  when :lvar
165
233
  [node, Set[node.children[0]]]
166
234
  when :masgn
167
- lhs, rhs = node.children
168
- lhs_vars = lhs.children.select {|m| m.type == :lvasgn }.map {|m| m.children[0] }
169
- val, vars = decompose_value(rhs)
170
- [val, vars + lhs_vars]
235
+ _, rhs = node.children
236
+ decompose_value(rhs)
171
237
  when :lvasgn
172
238
  var, rhs = node.children
173
239
  val, vars = decompose_value(rhs)
@@ -187,13 +253,18 @@ module Steep
187
253
  def literal_var_type_case_select(value_node, arg_type)
188
254
  case arg_type
189
255
  when AST::Types::Union
256
+ # @type var truthy_types: Array[AST::Types::t]
190
257
  truthy_types = []
258
+ # @type var falsy_types: Array[AST::Types::t]
191
259
  falsy_types = []
192
260
 
193
261
  arg_type.types.each do |type|
194
- ts, fs = literal_var_type_case_select(value_node, type)
195
- truthy_types.push(*ts)
196
- falsy_types.push(*fs)
262
+ if (ts, fs = literal_var_type_case_select(value_node, type))
263
+ truthy_types.push(*ts)
264
+ falsy_types.push(*fs)
265
+ else
266
+ return
267
+ end
197
268
  end
198
269
 
199
270
  [truthy_types, falsy_types]
@@ -216,7 +287,10 @@ module Steep
216
287
  (type.is_a?(AST::Types::Literal) && type.value == false)
217
288
  end
218
289
  when :int, :str, :sym
219
- types.each.with_object([[], []]) do |type, pair|
290
+ # @type var pairs: [Array[AST::Types::t], Array[AST::Types::t]]
291
+ pairs = [[], []]
292
+
293
+ types.each_with_object(pairs) do |type, pair|
220
294
  true_types, false_types = pair
221
295
 
222
296
  case
@@ -231,8 +305,6 @@ module Steep
231
305
  false_types << type
232
306
  end
233
307
  end
234
- else
235
- [[arg_type], [arg_type]]
236
308
  end
237
309
  end
238
310
  end
@@ -298,6 +370,25 @@ module Steep
298
370
  end
299
371
  end
300
372
  end
373
+
374
+ def try_convert(type, method)
375
+ case type
376
+ when AST::Types::Any, AST::Types::Bot, AST::Types::Top, AST::Types::Var
377
+ return
378
+ end
379
+
380
+ interface = factory.interface(type, private: false, self_type: type)
381
+ if entry = interface.methods[method]
382
+ method_type = entry.method_types.find do |method_type|
383
+ method_type.type.params.optional?
384
+ end
385
+
386
+ method_type.type.return_type if method_type
387
+ end
388
+ rescue => exn
389
+ Steep.log_error(exn, message: "Unexpected error when converting #{type.to_s} with #{method}")
390
+ nil
391
+ end
301
392
  end
302
393
  end
303
394
  end
@@ -12,7 +12,6 @@ module Steep
12
12
 
13
13
  def hash
14
14
  method_name.hash
15
- # RBS::MethodType doesn't have #hash
16
15
  end
17
16
 
18
17
  def ==(other)
@@ -26,30 +25,53 @@ module Steep
26
25
  end
27
26
  end
28
27
 
29
- MethodContext = Struct.new(:method_name, keyword_init: true) do
28
+ MethodContext = _ = Struct.new(:method_name, keyword_init: true) do
29
+ # @implements MethodContext
30
+
30
31
  def to_s
31
32
  "@#{method_name}"
32
33
  end
33
34
  end
34
35
 
35
- ModuleContext = Struct.new(:type_name, keyword_init: true) do
36
+ ModuleContext = _ = Struct.new(:type_name, keyword_init: true) do
37
+ # @implements ModuleContext
38
+
36
39
  def to_s
37
40
  "@#{type_name}@"
38
41
  end
39
42
  end
40
43
 
41
- TopLevelContext = Class.new() do
44
+ TopLevelContext = _ = Class.new() do
42
45
  def to_s
43
46
  "@<main>"
44
47
  end
48
+
49
+ def ==(other)
50
+ other.is_a?(TopLevelContext)
51
+ end
52
+
53
+ alias eql? ==
54
+
55
+ def hash
56
+ self.class.hash
57
+ end
45
58
  end
46
59
 
47
- UnknownContext = Class.new() do
60
+ UnknownContext = _ = Class.new() do
48
61
  def to_s
49
62
  "@<unknown>"
50
63
  end
51
- end
52
64
 
65
+ def ==(other)
66
+ other.is_a?(UnknownContext)
67
+ end
68
+
69
+ alias eql? ==
70
+
71
+ def hash
72
+ self.class.hash
73
+ end
74
+ end
53
75
 
54
76
  class Base
55
77
  attr_reader :node
@@ -73,6 +95,21 @@ module Steep
73
95
  end
74
96
  end
75
97
  end
98
+
99
+ def ==(other)
100
+ other.is_a?(Base) &&
101
+ other.node == node &&
102
+ other.context == context &&
103
+ other.method_name == method_name &&
104
+ other.return_type == return_type &&
105
+ other.receiver_type == receiver_type
106
+ end
107
+
108
+ alias eql? ==
109
+
110
+ def hash
111
+ node.hash ^ context.hash ^ method_name.hash ^ return_type.hash ^ receiver_type.hash
112
+ end
76
113
  end
77
114
 
78
115
  class Typed < Base
@@ -84,6 +121,43 @@ module Steep
84
121
  @actual_method_type = actual_method_type
85
122
  @method_decls = method_decls
86
123
  end
124
+
125
+ def pure?
126
+ method_decls.all? do |method_decl|
127
+ case member = method_decl.method_def.member
128
+ when RBS::AST::Members::MethodDefinition
129
+ member.annotations.any? {|annotation| annotation.string == "pure" }
130
+ when RBS::AST::Members::Attribute
131
+ # The attribute writer is not pure
132
+ !method_decl.method_name.method_name.end_with?("=")
133
+ end
134
+ end
135
+ end
136
+
137
+ def update(node: self.node, return_type: self.return_type)
138
+ _ = self.class.new(
139
+ node: node,
140
+ return_type: return_type,
141
+ context: context,
142
+ method_name: method_name,
143
+ receiver_type: receiver_type,
144
+ actual_method_type: actual_method_type,
145
+ method_decls: method_decls
146
+ )
147
+ end
148
+
149
+ def ==(other)
150
+ super &&
151
+ other.is_a?(Typed) &&
152
+ other.actual_method_type == actual_method_type &&
153
+ other.method_decls == method_decls
154
+ end
155
+
156
+ alias eql? ==
157
+
158
+ def hash
159
+ super ^ actual_method_type.hash ^ method_decls.hash
160
+ end
87
161
  end
88
162
 
89
163
  class Special < Typed