steep 1.4.0 → 1.5.0.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.vscode/steep-shared.code-snippets +41 -0
  4. data/CHANGELOG.md +37 -0
  5. data/Gemfile +2 -5
  6. data/Gemfile.lock +20 -17
  7. data/Gemfile.steep +1 -1
  8. data/Gemfile.steep.lock +6 -6
  9. data/Rakefile +198 -0
  10. data/Steepfile +3 -1
  11. data/lib/steep/ast/builtin.rb +9 -7
  12. data/lib/steep/ast/node/type_application.rb +13 -5
  13. data/lib/steep/ast/node/type_assertion.rb +28 -9
  14. data/lib/steep/ast/types/factory.rb +39 -7
  15. data/lib/steep/cli.rb +2 -1
  16. data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
  17. data/lib/steep/diagnostic/lsp_formatter.rb +3 -3
  18. data/lib/steep/diagnostic/ruby.rb +73 -12
  19. data/lib/steep/drivers/annotations.rb +1 -0
  20. data/lib/steep/drivers/check.rb +18 -13
  21. data/lib/steep/drivers/checkfile.rb +1 -1
  22. data/lib/steep/drivers/diagnostic_printer.rb +6 -4
  23. data/lib/steep/drivers/init.rb +2 -1
  24. data/lib/steep/drivers/print_project.rb +3 -1
  25. data/lib/steep/drivers/stats.rb +1 -1
  26. data/lib/steep/drivers/utils/driver_helper.rb +10 -8
  27. data/lib/steep/drivers/utils/jobs_option.rb +6 -1
  28. data/lib/steep/drivers/validate.rb +9 -5
  29. data/lib/steep/drivers/watch.rb +8 -3
  30. data/lib/steep/expectations.rb +144 -75
  31. data/lib/steep/index/signature_symbol_provider.rb +22 -13
  32. data/lib/steep/node_helper.rb +172 -0
  33. data/lib/steep/server/base_worker.rb +2 -1
  34. data/lib/steep/server/change_buffer.rb +17 -15
  35. data/lib/steep/server/interaction_worker.rb +20 -0
  36. data/lib/steep/server/lsp_formatter.rb +20 -1
  37. data/lib/steep/server/master.rb +51 -36
  38. data/lib/steep/server/type_check_worker.rb +18 -2
  39. data/lib/steep/server/worker_process.rb +19 -2
  40. data/lib/steep/services/completion_provider.rb +189 -3
  41. data/lib/steep/services/file_loader.rb +1 -1
  42. data/lib/steep/services/goto_service.rb +123 -27
  43. data/lib/steep/services/signature_help_provider.rb +1 -6
  44. data/lib/steep/signature/validator.rb +6 -1
  45. data/lib/steep/source.rb +165 -108
  46. data/lib/steep/subtyping/check.rb +5 -3
  47. data/lib/steep/subtyping/variable_variance.rb +11 -0
  48. data/lib/steep/thread_waiter.rb +35 -0
  49. data/lib/steep/type_construction.rb +416 -171
  50. data/lib/steep/type_inference/block_params.rb +50 -9
  51. data/lib/steep/type_inference/context.rb +4 -0
  52. data/lib/steep/type_inference/context_array.rb +6 -6
  53. data/lib/steep/type_inference/logic_type_interpreter.rb +202 -68
  54. data/lib/steep/typing.rb +5 -4
  55. data/lib/steep/version.rb +1 -1
  56. data/lib/steep.rb +21 -14
  57. data/sample/Steepfile +1 -0
  58. data/sig/shims/bundler.rbs +3 -0
  59. data/sig/shims/language-server_protocol.rbs +151 -10
  60. data/sig/shims/parser/nodes.rbs +210 -0
  61. data/sig/shims/parser.rbs +10 -0
  62. data/sig/steep/ast/builtin.rbs +2 -2
  63. data/sig/steep/ast/node/type_application.rbs +2 -2
  64. data/sig/steep/ast/node/type_assertion.rbs +8 -2
  65. data/sig/steep/ast/types/factory.rbs +28 -1
  66. data/sig/steep/diagnostic/deprecated/else_on_exhaustive_case.rbs +13 -0
  67. data/sig/steep/diagnostic/lsp_formatter.rbs +5 -2
  68. data/sig/steep/diagnostic/ruby.rbs +76 -6
  69. data/sig/steep/drivers/annotations.rbs +5 -5
  70. data/sig/steep/drivers/check.rbs +11 -11
  71. data/sig/steep/drivers/diagnostic_printer.rbs +9 -9
  72. data/sig/steep/drivers/init.rbs +6 -6
  73. data/sig/steep/drivers/print_project.rbs +4 -4
  74. data/sig/steep/drivers/utils/driver_helper.rbs +8 -6
  75. data/sig/steep/drivers/validate.rbs +4 -4
  76. data/sig/steep/drivers/watch.rbs +1 -1
  77. data/sig/steep/expectations.rbs +72 -0
  78. data/sig/steep/index/signature_symbol_provider.rbs +22 -10
  79. data/sig/steep/interface/block.rbs +2 -0
  80. data/sig/steep/interface/function.rbs +2 -2
  81. data/sig/steep/node_helper.rbs +56 -0
  82. data/sig/steep/path_helper.rbs +1 -1
  83. data/sig/steep/project/options.rbs +1 -1
  84. data/sig/steep/range_extension.rbs +2 -2
  85. data/sig/steep/server/master.rbs +16 -2
  86. data/sig/steep/server/type_check_worker.rbs +5 -1
  87. data/sig/steep/server/worker_process.rbs +5 -1
  88. data/sig/steep/services/completion_provider.rbs +31 -1
  89. data/sig/steep/services/goto_service.rbs +80 -19
  90. data/sig/steep/source.rbs +27 -4
  91. data/sig/steep/subtyping/variable_variance.rbs +9 -9
  92. data/sig/steep/thread_waiter.rbs +13 -0
  93. data/sig/steep/type_construction.rbs +26 -9
  94. data/sig/steep/type_inference/block_params.rbs +13 -1
  95. data/sig/steep/type_inference/context.rbs +5 -1
  96. data/sig/steep/type_inference/context_array.rbs +16 -15
  97. data/sig/steep/type_inference/logic_type_interpreter.rbs +36 -6
  98. data/sig/steep/type_inference/type_env_builder.rbs +4 -0
  99. data/sig/steep/typing.rbs +22 -20
  100. data/sig/steep.rbs +14 -13
  101. data/smoke/and/a.rb +1 -1
  102. data/smoke/and/test_expectations.yml +5 -7
  103. data/smoke/diagnostics/incompatible_annotation.rb +1 -1
  104. data/smoke/diagnostics/test_expectations.yml +2 -2
  105. data/smoke/enumerator/a.rb +0 -7
  106. data/smoke/enumerator/b.rb +0 -2
  107. data/smoke/enumerator/test_expectations.yml +17 -105
  108. data/smoke/lambda/a.rb +0 -5
  109. data/smoke/lambda/test_expectations.yml +0 -22
  110. data/smoke/type_case/test_expectations.yml +10 -0
  111. data/steep.gemspec +2 -2
  112. metadata +16 -9
@@ -76,6 +76,14 @@ module Steep
76
76
  enum_for :each_param
77
77
  end
78
78
  end
79
+
80
+ def type
81
+ types = params.map do |param|
82
+ param.type or return
83
+ end
84
+
85
+ AST::Types::Tuple.new(types: types)
86
+ end
79
87
  end
80
88
 
81
89
  attr_reader :leading_params
@@ -191,15 +199,30 @@ module Steep
191
199
  return nil
192
200
  end
193
201
 
194
- if rest_param && hint.rest
195
- rest = rest_param.type&.yield_self {|ty| ty.args&.first } || hint.rest
196
- else
197
- rest = hint.rest
202
+ if rest_param
203
+ if hint.rest
204
+ if rest_type = rest_param.type
205
+ if AST::Builtin::Array.instance_type?(rest_type)
206
+ rest_type.is_a?(AST::Types::Name::Instance) or raise
207
+ rest = rest_type.args.first or raise
208
+ end
209
+ end
210
+
211
+ rest ||= hint.rest
212
+ end
198
213
  end
199
214
  else
200
215
  leadings = leading_params.map {|param| param.type || AST::Types::Any.new }
201
216
  optionals = optional_params.map {|param| param.type || AST::Types::Any.new }
202
- rest = rest_param&.yield_self {|param| param.type&.args&.[](0) || AST::Types::Any.new }
217
+
218
+ if rest_param
219
+ if rest_type = rest_param.type
220
+ if array = AST::Builtin::Array.instance_type?(rest_type)
221
+ rest = array.args.first or raise
222
+ end
223
+ end
224
+ rest ||= AST::Types::Any.new
225
+ end
203
226
  end
204
227
 
205
228
  Interface::Function::Params.build(
@@ -217,6 +240,17 @@ module Steep
217
240
  # @type var zip: Array[[Param | MultipleParam, AST::Types::t]]
218
241
  zip = []
219
242
 
243
+ if untyped_args?(params_type)
244
+ params.each do |param|
245
+ if param == rest_param
246
+ zip << [param, AST::Builtin::Array.instance_type(fill_untyped: true)]
247
+ else
248
+ zip << [param, AST::Builtin.any_type]
249
+ end
250
+ end
251
+ return zip
252
+ end
253
+
220
254
  if expandable? && (type = expandable_params?(params_type, factory))
221
255
  case
222
256
  when AST::Builtin::Array.instance_type?(type)
@@ -254,10 +288,10 @@ module Steep
254
288
  types = params_type.flat_unnamed_params
255
289
 
256
290
  (leading_params + optional_params).each do |param|
257
- type = types.shift&.last || params_type.rest
291
+ typ = types.shift&.last || params_type.rest
258
292
 
259
- if type
260
- zip << [param, type]
293
+ if typ
294
+ zip << [param, typ]
261
295
  else
262
296
  zip << [param, AST::Builtin.nil_type]
263
297
  end
@@ -268,7 +302,9 @@ module Steep
268
302
  array = AST::Builtin::Array.instance_type(params_type.rest || AST::Builtin.any_type)
269
303
  zip << [rest_param, array]
270
304
  else
271
- union = AST::Types::Union.build(types: types.map(&:last) + [params_type.rest])
305
+ union_members = types.map(&:last)
306
+ union_members << params_type.rest if params_type.rest
307
+ union = AST::Types::Union.build(types: union_members)
272
308
  array = AST::Builtin::Array.instance_type(union)
273
309
  zip << [rest_param, array]
274
310
  end
@@ -360,6 +396,11 @@ module Steep
360
396
 
361
397
  MultipleParam.new(node: node, params: params)
362
398
  end
399
+
400
+ def untyped_args?(params)
401
+ flat = params.flat_unnamed_params
402
+ flat.size == 1 && flat[0][1].is_a?(AST::Types::Any)
403
+ end
363
404
  end
364
405
  end
365
406
  end
@@ -21,6 +21,10 @@ module Steep
21
21
  def block_type
22
22
  method_type&.block
23
23
  end
24
+
25
+ def attribute_setter?
26
+ name.to_s.end_with?('=')
27
+ end
24
28
  end
25
29
 
26
30
  class BlockContext
@@ -23,14 +23,15 @@ module Steep
23
23
  root.range
24
24
  end
25
25
 
26
- def self.from_source(source:, range: nil, context: nil)
26
+ def self.from_source(source:, range: nil, context:)
27
27
  content = if source.node
28
28
  source.node.location.expression.source_buffer.source
29
29
  else
30
30
  ""
31
31
  end
32
32
  buffer = RBS::Buffer.new(name: source.path, content: content)
33
- new(buffer: buffer, context: context, range: range || 0..buffer.content.size)
33
+ range ||= 0..buffer.content.size
34
+ new(buffer: buffer, context: context, range: range)
34
35
  end
35
36
 
36
37
  def insert_context(range, context:, entry: self.root)
@@ -62,12 +63,11 @@ module Steep
62
63
  end
63
64
  end
64
65
 
65
- def each_entry
66
- if block_given?
66
+ def each_entry(&block)
67
+ if block
67
68
  es = [root]
68
69
 
69
- until es.empty?
70
- e = es.pop
70
+ while e = es.pop
71
71
  es.push(*e.sub_entries.to_a)
72
72
 
73
73
  yield e
@@ -1,6 +1,22 @@
1
1
  module Steep
2
2
  module TypeInference
3
3
  class LogicTypeInterpreter
4
+ class Result < Struct.new(:env, :type, :unreachable, keyword_init: true)
5
+ def update_env
6
+ env = yield()
7
+ Result.new(type: type, env: env, unreachable: unreachable)
8
+ end
9
+
10
+ def update_type
11
+ Result.new(type: yield, env: env, unreachable: unreachable)
12
+ end
13
+
14
+ def unreachable!
15
+ self.unreachable = true
16
+ self
17
+ end
18
+ end
19
+
4
20
  attr_reader :subtyping
5
21
  attr_reader :typing
6
22
  attr_reader :config
@@ -31,55 +47,112 @@ module Steep
31
47
  end
32
48
  end
33
49
 
34
- def eval(env:, node:)
35
- objects = Set[]
36
- truthy_type, falsy_type, truthy_env, falsy_env = evaluate_node(env: env, node: node, refined_objects: objects)
50
+ TRUE = AST::Types::Literal.new(value: true)
51
+ FALSE = AST::Types::Literal.new(value: false)
52
+ BOOL = AST::Types::Boolean.new
53
+ BOT = AST::Types::Bot.new
54
+ UNTYPED = AST::Types::Any.new
37
55
 
38
- [truthy_env, falsy_env, objects, truthy_type, falsy_type]
56
+ def eval(env:, node:)
57
+ evaluate_node(env: env, node: node)
39
58
  end
40
59
 
41
- def evaluate_node(env:, node:, refined_objects:)
42
- type = typing.type_of(node: node)
43
-
60
+ def evaluate_node(env:, node:, type: typing.type_of(node: node))
44
61
  if type.is_a?(AST::Types::Logic::Env)
45
62
  truthy_env = type.truthy
46
63
  falsy_env = type.falsy
47
64
 
48
- return [AST::Types::Boolean.new, AST::Types::Boolean.new, truthy_env, falsy_env]
65
+ truthy_type, falsy_type = factory.partition_union(type.type)
66
+
67
+ return [
68
+ Result.new(env: truthy_env, type: truthy_type || TRUE, unreachable: !truthy_type),
69
+ Result.new(env: falsy_env, type: falsy_type || FALSE, unreachable: !falsy_type)
70
+ ]
71
+ end
72
+
73
+ if type.is_a?(AST::Types::Bot)
74
+ return [
75
+ Result.new(env: env, type: type, unreachable: true),
76
+ Result.new(env: env, type: type, unreachable: true),
77
+ ]
49
78
  end
50
79
 
51
80
  case node.type
52
81
  when :lvar
53
82
  name = node.children[0]
54
- refined_objects << name
55
- truthy_type, falsy_type = factory.unwrap_optional(type)
56
- return [
57
- truthy_type,
58
- falsy_type,
59
- env.refine_types(local_variable_types: { name => truthy_type }),
60
- env.refine_types(local_variable_types: { name => falsy_type })
61
- ]
83
+ truthy_type, falsy_type = factory.partition_union(type)
84
+
85
+ truthy_result =
86
+ if truthy_type
87
+ Result.new(type: truthy_type, env: env.refine_types(local_variable_types: { name => truthy_type }), unreachable: false)
88
+ else
89
+ Result.new(type: type, env: env, unreachable: true)
90
+ end
91
+
92
+ falsy_result =
93
+ if falsy_type
94
+ Result.new(type: falsy_type, env: env.refine_types(local_variable_types: { name => falsy_type }), unreachable: false)
95
+ else
96
+ Result.new(type: type, env: env, unreachable: true)
97
+ end
98
+
99
+ return [truthy_result, falsy_result]
100
+
62
101
  when :lvasgn
63
102
  name, rhs = node.children
64
- truthy_type, falsy_type, truthy_env, falsy_env = evaluate_node(env: env, node: rhs, refined_objects: refined_objects)
103
+ if TypeConstruction::SPECIAL_LVAR_NAMES.include?(name)
104
+ return [
105
+ Result.new(type: type, env: env, unreachable: false),
106
+ Result.new(type: type, env: env, unreachable: false)
107
+ ]
108
+ end
109
+
110
+ truthy_result, falsy_result = evaluate_node(env: env, node: rhs)
111
+
65
112
  return [
66
- truthy_type,
67
- falsy_type,
68
- evaluate_assignment(node, truthy_env, truthy_type, refined_objects: refined_objects),
69
- evaluate_assignment(node, falsy_env, falsy_type, refined_objects: refined_objects)
113
+ truthy_result.update_env { evaluate_assignment(node, truthy_result.env, truthy_result.type) },
114
+ falsy_result.update_env { evaluate_assignment(node, falsy_result.env, falsy_result.type) }
70
115
  ]
116
+
71
117
  when :masgn
72
- lhs, rhs = node.children
73
- truthy_type, falsy_type, truthy_env, falsy_env = evaluate_node(env: env, node: rhs, refined_objects: refined_objects)
118
+ _, rhs = node.children
119
+ truthy_result, falsy_result = evaluate_node(env: env, node: rhs)
120
+
74
121
  return [
75
- truthy_type,
76
- falsy_type,
77
- evaluate_assignment(node, truthy_env, truthy_type, refined_objects: refined_objects),
78
- evaluate_assignment(node, falsy_env, falsy_type, refined_objects: refined_objects)
122
+ truthy_result.update_env { evaluate_assignment(node, truthy_result.env, truthy_result.type) },
123
+ falsy_result.update_env { evaluate_assignment(node, falsy_result.env, falsy_result.type) }
79
124
  ]
125
+
80
126
  when :begin
81
127
  last_node = node.children.last or raise
82
- return evaluate_node(env: env, node: last_node, refined_objects: refined_objects)
128
+ return evaluate_node(env: env, node: last_node)
129
+
130
+ when :csend
131
+ if type.is_a?(AST::Types::Any)
132
+ type = guess_type_from_method(node) || type
133
+ end
134
+
135
+ receiver, _, *arguments = node.children
136
+ receiver_type = typing.type_of(node: receiver)
137
+
138
+ truthy_receiver, falsy_receiver = evaluate_node(env: env, node: receiver)
139
+ truthy_type, _ = factory.partition_union(type)
140
+
141
+ truthy_result, falsy_result = evaluate_node(
142
+ env: truthy_receiver.env,
143
+ node: node.updated(:send),
144
+ type: truthy_type || type
145
+ )
146
+ truthy_result.unreachable! if truthy_receiver.unreachable
147
+
148
+ falsy_result = Result.new(
149
+ env: env.join(falsy_receiver.env, falsy_result.env),
150
+ unreachable: falsy_result.unreachable && falsy_receiver.unreachable,
151
+ type: falsy_result.type
152
+ )
153
+
154
+ return [truthy_result, falsy_result]
155
+
83
156
  when :send
84
157
  if type.is_a?(AST::Types::Any)
85
158
  type = guess_type_from_method(node) || type
@@ -88,38 +161,46 @@ module Steep
88
161
  case type
89
162
  when AST::Types::Logic::Base
90
163
  receiver, _, *arguments = node.children
91
- truthy_env, falsy_env = evaluate_method_call(env: env, type: type, receiver: receiver, arguments: arguments, refined_objects: refined_objects)
92
-
93
- if truthy_env && falsy_env
94
- return [AST::Builtin.true_type, AST::Builtin.false_type, truthy_env, falsy_env]
164
+ if (truthy_result, falsy_result = evaluate_method_call(env: env, type: type, receiver: receiver, arguments: arguments))
165
+ return [truthy_result, falsy_result]
95
166
  end
96
167
  else
97
168
  if env[node]
98
- truthy_type, falsy_type = factory.unwrap_optional(type)
99
-
100
- refined_objects << node
101
- return [
102
- truthy_type,
103
- falsy_type,
104
- env.refine_types(pure_call_types: { node => truthy_type }),
105
- env.refine_types(pure_call_types: { node => falsy_type })
106
- ]
169
+ truthy_type, falsy_type = factory.partition_union(type)
170
+
171
+ truthy_result =
172
+ if truthy_type
173
+ Result.new(type: truthy_type, env: env.refine_types(pure_call_types: { node => truthy_type }), unreachable: false)
174
+ else
175
+ Result.new(type: type, env: env, unreachable: true)
176
+ end
177
+
178
+ falsy_result =
179
+ if falsy_type
180
+ Result.new(type: falsy_type, env: env.refine_types(pure_call_types: { node => falsy_type }), unreachable: false)
181
+ else
182
+ Result.new(type: type, env: env, unreachable: true)
183
+ end
184
+
185
+ return [truthy_result, falsy_result]
107
186
  end
108
187
  end
109
188
  end
110
189
 
111
- truthy_type, falsy_type = factory.unwrap_optional(type)
112
- return [truthy_type, falsy_type, env, env]
190
+ truthy_type, falsy_type = factory.partition_union(type)
191
+ return [
192
+ Result.new(type: truthy_type || BOT, env: env, unreachable: truthy_type.nil?),
193
+ Result.new(type: falsy_type || BOT, env: env, unreachable: falsy_type.nil?)
194
+ ]
113
195
  end
114
196
 
115
- def evaluate_assignment(assignment_node, env, rhs_type, refined_objects:)
197
+ def evaluate_assignment(assignment_node, env, rhs_type)
116
198
  case assignment_node.type
117
199
  when :lvasgn
118
200
  name, _ = assignment_node.children
119
201
  if TypeConstruction::SPECIAL_LVAR_NAMES.include?(name)
120
202
  env
121
203
  else
122
- refined_objects << name
123
204
  env.refine_types(local_variable_types: { name => rhs_type })
124
205
  end
125
206
  when :masgn
@@ -140,7 +221,7 @@ module Steep
140
221
 
141
222
  assignments.each do |pair|
142
223
  node, type = pair
143
- env = evaluate_assignment(node, env, type, refined_objects: refined_objects)
224
+ env = evaluate_assignment(node, env, type)
144
225
  end
145
226
 
146
227
  env
@@ -149,7 +230,7 @@ module Steep
149
230
  end
150
231
  end
151
232
 
152
- def refine_node_type(env:, node:, truthy_type:, falsy_type:, refined_objects:)
233
+ def refine_node_type(env:, node:, truthy_type:, falsy_type:)
153
234
  case node.type
154
235
  when :lvar
155
236
  name = node.children[0]
@@ -157,7 +238,6 @@ module Steep
157
238
  if TypeConstruction::SPECIAL_LVAR_NAMES.include?(name)
158
239
  [env, env]
159
240
  else
160
- refined_objects << name
161
241
  [
162
242
  env.refine_types(local_variable_types: { name => truthy_type }),
163
243
  env.refine_types(local_variable_types: { name => falsy_type })
@@ -167,12 +247,11 @@ module Steep
167
247
  when :lvasgn
168
248
  name, rhs = node.children
169
249
 
170
- truthy_env, falsy_env = refine_node_type(env: env, node: rhs, truthy_type: truthy_type, falsy_type: falsy_type, refined_objects: refined_objects)
250
+ truthy_env, falsy_env = refine_node_type(env: env, node: rhs, truthy_type: truthy_type, falsy_type: falsy_type)
171
251
 
172
252
  if TypeConstruction::SPECIAL_LVAR_NAMES.include?(name)
173
253
  [truthy_env, falsy_env]
174
254
  else
175
- refined_objects << name
176
255
  [
177
256
  truthy_env.refine_types(local_variable_types: { name => truthy_type }),
178
257
  falsy_env.refine_types(local_variable_types: { name => falsy_type })
@@ -181,7 +260,6 @@ module Steep
181
260
 
182
261
  when :send
183
262
  if env[node]
184
- refined_objects << node
185
263
  [
186
264
  env.refine_types(pure_call_types: { node => truthy_type }),
187
265
  env.refine_types(pure_call_types: { node => falsy_type })
@@ -191,20 +269,35 @@ module Steep
191
269
  end
192
270
  when :begin
193
271
  last_node = node.children.last or raise
194
- refine_node_type(env: env, node: last_node, truthy_type: truthy_type, falsy_type: falsy_type, refined_objects: refined_objects)
272
+ refine_node_type(env: env, node: last_node, truthy_type: truthy_type, falsy_type: falsy_type)
195
273
  else
196
274
  [env, env]
197
275
  end
198
276
  end
199
277
 
200
- def evaluate_method_call(env:, type:, receiver:, arguments:, refined_objects:)
278
+ def evaluate_method_call(env:, type:, receiver:, arguments:)
201
279
  case type
202
280
  when AST::Types::Logic::ReceiverIsNil
203
281
  if receiver && arguments.size.zero?
204
282
  receiver_type = typing.type_of(node: receiver)
205
- truthy_receiver, falsy_receiver = factory.unwrap_optional(receiver_type)
206
- refine_node_type(env: env, node: receiver, truthy_type: falsy_receiver, falsy_type: truthy_receiver, refined_objects: refined_objects)
283
+ truthy_receiver, falsy_receiver = factory.partition_union(receiver_type)
284
+
285
+ truthy_env, falsy_env = refine_node_type(
286
+ env: env,
287
+ node: receiver,
288
+ truthy_type: falsy_receiver || BOT,
289
+ falsy_type: truthy_receiver || BOT
290
+ )
291
+
292
+ truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
293
+ truthy_result.unreachable! unless truthy_receiver
294
+
295
+ falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
296
+ falsy_result.unreachable! unless falsy_receiver
297
+
298
+ [truthy_result, falsy_result]
207
299
  end
300
+
208
301
  when AST::Types::Logic::ReceiverIsArg
209
302
  if receiver && (arg = arguments[0])
210
303
  receiver_type = typing.type_of(node: receiver)
@@ -212,9 +305,23 @@ module Steep
212
305
 
213
306
  if arg_type.is_a?(AST::Types::Name::Singleton)
214
307
  truthy_type, falsy_type = type_case_select(receiver_type, arg_type.name)
215
- refine_node_type(env: env, node: receiver, truthy_type: truthy_type, falsy_type: falsy_type, refined_objects: refined_objects)
308
+ truthy_env, falsy_env = refine_node_type(
309
+ env: env,
310
+ node: receiver,
311
+ truthy_type: truthy_type || factory.instance_type(arg_type.name),
312
+ falsy_type: falsy_type || UNTYPED
313
+ )
314
+
315
+ truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
316
+ truthy_result.unreachable! unless truthy_type
317
+
318
+ falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
319
+ falsy_result.unreachable! unless falsy_type
320
+
321
+ [truthy_result, falsy_result]
216
322
  end
217
323
  end
324
+
218
325
  when AST::Types::Logic::ArgIsReceiver
219
326
  if receiver && (arg = arguments[0])
220
327
  receiver_type = factory.deep_expand_alias(typing.type_of(node: receiver))
@@ -222,26 +329,49 @@ module Steep
222
329
 
223
330
  if receiver_type.is_a?(AST::Types::Name::Singleton)
224
331
  truthy_type, falsy_type = type_case_select(arg_type, receiver_type.name)
225
- refine_node_type(env: env, node: arg, truthy_type: truthy_type, falsy_type: falsy_type, refined_objects: refined_objects)
332
+ truthy_env, falsy_env = refine_node_type(
333
+ env: env,
334
+ node: arg,
335
+ truthy_type: truthy_type || factory.instance_type(receiver_type.name),
336
+ falsy_type: falsy_type || UNTYPED
337
+ )
338
+
339
+ truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
340
+ truthy_result.unreachable! unless truthy_type
341
+
342
+ falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
343
+ falsy_result.unreachable! unless falsy_type
344
+
345
+ [truthy_result, falsy_result]
226
346
  end
227
347
  end
228
348
  when AST::Types::Logic::ArgEqualsReceiver
229
349
  if receiver && (arg = arguments[0])
230
350
  arg_type = factory.expand_alias(typing.type_of(node: arg))
231
351
  if (truthy_types, falsy_types = literal_var_type_case_select(receiver, arg_type))
232
- refine_node_type(
352
+ truthy_env, falsy_env = refine_node_type(
233
353
  env: env,
234
354
  node: arg,
235
- truthy_type: AST::Types::Union.build(types: truthy_types),
236
- falsy_type: AST::Types::Union.build(types: falsy_types),
237
- refined_objects: refined_objects
355
+ truthy_type: truthy_types.empty? ? BOT : AST::Types::Union.build(types: truthy_types),
356
+ falsy_type: falsy_types.empty? ? BOT : AST::Types::Union.build(types: falsy_types)
238
357
  )
358
+
359
+ truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
360
+ truthy_result.unreachable! if truthy_types.empty?
361
+
362
+ falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
363
+ falsy_result.unreachable! if falsy_types.empty?
364
+
365
+ [truthy_result, falsy_result]
239
366
  end
240
367
  end
241
368
  when AST::Types::Logic::Not
242
369
  if receiver
243
- truthy_type, falsy_type, truthy_env, falsy_env = evaluate_node(env: env, node: receiver, refined_objects: refined_objects)
244
- [falsy_env, truthy_env]
370
+ truthy_result, falsy_result = evaluate_node(env: env, node: receiver)
371
+ [
372
+ falsy_result.update_type { TRUE },
373
+ truthy_result.update_type { FALSE }
374
+ ]
245
375
  end
246
376
  end
247
377
  end
@@ -332,8 +462,8 @@ module Steep
332
462
  truth_types, false_types = type_case_select0(type, klass)
333
463
 
334
464
  [
335
- AST::Types::Union.build(types: truth_types),
336
- AST::Types::Union.build(types: false_types)
465
+ truth_types.empty? ? nil : AST::Types::Union.build(types: truth_types),
466
+ false_types.empty? ? nil : AST::Types::Union.build(types: false_types)
337
467
  ]
338
468
  end
339
469
 
@@ -342,8 +472,8 @@ module Steep
342
472
 
343
473
  case type
344
474
  when AST::Types::Union
345
- truthy_types = []
346
- falsy_types = []
475
+ truthy_types = [] # :Array[AST::Types::t]
476
+ falsy_types = [] #: Array[AST::Types::t]
347
477
 
348
478
  type.types.each do |ty|
349
479
  truths, falses = type_case_select0(ty, klass)
@@ -360,7 +490,11 @@ module Steep
360
490
 
361
491
  when AST::Types::Name::Alias
362
492
  ty = factory.expand_alias(type)
363
- type_case_select0(ty, klass)
493
+ if ty == type
494
+ [[type], [type]]
495
+ else
496
+ type_case_select0(ty, klass)
497
+ end
364
498
 
365
499
  when AST::Types::Any, AST::Types::Top
366
500
  [
data/lib/steep/typing.rb CHANGED
@@ -32,10 +32,10 @@ module Steep
32
32
  @should_update = false
33
33
 
34
34
  @errors = []
35
- @typing = {}.compare_by_identity
35
+ (@typing = {}).compare_by_identity
36
36
  @root_context = root_context
37
- @contexts = contexts || TypeInference::ContextArray.from_source(source: source)
38
- @method_calls = {}.compare_by_identity
37
+ @contexts = contexts || TypeInference::ContextArray.from_source(source: source, context: root_context)
38
+ (@method_calls = {}).compare_by_identity
39
39
 
40
40
  @source_index = source_index || Index::SourceIndex.new(source: source)
41
41
  end
@@ -222,10 +222,11 @@ module Steep
222
222
  end
223
223
 
224
224
  def new_child(range)
225
+ context = contexts[range.begin] || contexts.root.context
225
226
  child = self.class.new(source: source,
226
227
  parent: self,
227
228
  root_context: root_context,
228
- contexts: TypeInference::ContextArray.new(buffer: contexts.buffer, range: range, context: nil),
229
+ contexts: TypeInference::ContextArray.new(buffer: contexts.buffer, range: range, context: context),
229
230
  source_index: source_index.new_child)
230
231
  @should_update = true
231
232
 
data/lib/steep/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Steep
2
- VERSION = "1.4.0"
2
+ VERSION = "1.5.0.pre.1"
3
3
  end