steep-relaxed 1.9.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.gitmodules +0 -0
  4. data/CHANGELOG.md +1032 -0
  5. data/LICENSE +21 -0
  6. data/README.md +260 -0
  7. data/Rakefile +227 -0
  8. data/STDGEM_DEPENDENCIES.txt +59 -0
  9. data/Steepfile +68 -0
  10. data/bin/console +14 -0
  11. data/bin/generate-diagnostics-docs.rb +112 -0
  12. data/bin/mem_graph.rb +67 -0
  13. data/bin/mem_prof.rb +102 -0
  14. data/bin/output_rebaseline.rb +34 -0
  15. data/bin/output_test.rb +60 -0
  16. data/bin/rbs +20 -0
  17. data/bin/rbs-inline +19 -0
  18. data/bin/setup +9 -0
  19. data/bin/stackprof_test.rb +19 -0
  20. data/bin/steep +19 -0
  21. data/bin/steep-check.rb +251 -0
  22. data/bin/steep-prof +16 -0
  23. data/doc/narrowing.md +195 -0
  24. data/doc/shape.md +194 -0
  25. data/exe/steep +18 -0
  26. data/guides/README.md +5 -0
  27. data/guides/src/gem-rbs-collection/gem-rbs-collection.md +126 -0
  28. data/guides/src/getting-started/getting-started.md +163 -0
  29. data/guides/src/nil-optional/nil-optional.md +195 -0
  30. data/lib/steep/annotation_parser.rb +199 -0
  31. data/lib/steep/ast/annotation/collection.rb +172 -0
  32. data/lib/steep/ast/annotation.rb +137 -0
  33. data/lib/steep/ast/builtin.rb +104 -0
  34. data/lib/steep/ast/ignore.rb +148 -0
  35. data/lib/steep/ast/node/type_application.rb +88 -0
  36. data/lib/steep/ast/node/type_assertion.rb +81 -0
  37. data/lib/steep/ast/types/any.rb +35 -0
  38. data/lib/steep/ast/types/boolean.rb +45 -0
  39. data/lib/steep/ast/types/bot.rb +35 -0
  40. data/lib/steep/ast/types/class.rb +43 -0
  41. data/lib/steep/ast/types/factory.rb +557 -0
  42. data/lib/steep/ast/types/helper.rb +40 -0
  43. data/lib/steep/ast/types/instance.rb +42 -0
  44. data/lib/steep/ast/types/intersection.rb +93 -0
  45. data/lib/steep/ast/types/literal.rb +59 -0
  46. data/lib/steep/ast/types/logic.rb +84 -0
  47. data/lib/steep/ast/types/name.rb +128 -0
  48. data/lib/steep/ast/types/nil.rb +41 -0
  49. data/lib/steep/ast/types/proc.rb +117 -0
  50. data/lib/steep/ast/types/record.rb +79 -0
  51. data/lib/steep/ast/types/self.rb +43 -0
  52. data/lib/steep/ast/types/shared_instance.rb +11 -0
  53. data/lib/steep/ast/types/top.rb +35 -0
  54. data/lib/steep/ast/types/tuple.rb +60 -0
  55. data/lib/steep/ast/types/union.rb +97 -0
  56. data/lib/steep/ast/types/var.rb +65 -0
  57. data/lib/steep/ast/types/void.rb +35 -0
  58. data/lib/steep/cli.rb +401 -0
  59. data/lib/steep/diagnostic/deprecated/else_on_exhaustive_case.rb +20 -0
  60. data/lib/steep/diagnostic/deprecated/unknown_constant_assigned.rb +28 -0
  61. data/lib/steep/diagnostic/helper.rb +18 -0
  62. data/lib/steep/diagnostic/lsp_formatter.rb +78 -0
  63. data/lib/steep/diagnostic/result_printer2.rb +48 -0
  64. data/lib/steep/diagnostic/ruby.rb +1221 -0
  65. data/lib/steep/diagnostic/signature.rb +570 -0
  66. data/lib/steep/drivers/annotations.rb +52 -0
  67. data/lib/steep/drivers/check.rb +339 -0
  68. data/lib/steep/drivers/checkfile.rb +210 -0
  69. data/lib/steep/drivers/diagnostic_printer.rb +105 -0
  70. data/lib/steep/drivers/init.rb +66 -0
  71. data/lib/steep/drivers/langserver.rb +56 -0
  72. data/lib/steep/drivers/print_project.rb +113 -0
  73. data/lib/steep/drivers/stats.rb +203 -0
  74. data/lib/steep/drivers/utils/driver_helper.rb +143 -0
  75. data/lib/steep/drivers/utils/jobs_option.rb +26 -0
  76. data/lib/steep/drivers/vendor.rb +27 -0
  77. data/lib/steep/drivers/watch.rb +194 -0
  78. data/lib/steep/drivers/worker.rb +58 -0
  79. data/lib/steep/equatable.rb +23 -0
  80. data/lib/steep/expectations.rb +228 -0
  81. data/lib/steep/index/rbs_index.rb +350 -0
  82. data/lib/steep/index/signature_symbol_provider.rb +185 -0
  83. data/lib/steep/index/source_index.rb +167 -0
  84. data/lib/steep/interface/block.rb +103 -0
  85. data/lib/steep/interface/builder.rb +843 -0
  86. data/lib/steep/interface/function.rb +1090 -0
  87. data/lib/steep/interface/method_type.rb +330 -0
  88. data/lib/steep/interface/shape.rb +239 -0
  89. data/lib/steep/interface/substitution.rb +159 -0
  90. data/lib/steep/interface/type_param.rb +115 -0
  91. data/lib/steep/located_value.rb +20 -0
  92. data/lib/steep/method_name.rb +42 -0
  93. data/lib/steep/module_helper.rb +24 -0
  94. data/lib/steep/node_helper.rb +273 -0
  95. data/lib/steep/path_helper.rb +30 -0
  96. data/lib/steep/project/dsl.rb +268 -0
  97. data/lib/steep/project/group.rb +31 -0
  98. data/lib/steep/project/options.rb +63 -0
  99. data/lib/steep/project/pattern.rb +59 -0
  100. data/lib/steep/project/target.rb +92 -0
  101. data/lib/steep/project.rb +78 -0
  102. data/lib/steep/rake_task.rb +132 -0
  103. data/lib/steep/range_extension.rb +29 -0
  104. data/lib/steep/server/base_worker.rb +97 -0
  105. data/lib/steep/server/change_buffer.rb +73 -0
  106. data/lib/steep/server/custom_methods.rb +77 -0
  107. data/lib/steep/server/delay_queue.rb +45 -0
  108. data/lib/steep/server/interaction_worker.rb +492 -0
  109. data/lib/steep/server/lsp_formatter.rb +455 -0
  110. data/lib/steep/server/master.rb +922 -0
  111. data/lib/steep/server/target_group_files.rb +205 -0
  112. data/lib/steep/server/type_check_controller.rb +366 -0
  113. data/lib/steep/server/type_check_worker.rb +303 -0
  114. data/lib/steep/server/work_done_progress.rb +64 -0
  115. data/lib/steep/server/worker_process.rb +176 -0
  116. data/lib/steep/services/completion_provider.rb +802 -0
  117. data/lib/steep/services/content_change.rb +61 -0
  118. data/lib/steep/services/file_loader.rb +74 -0
  119. data/lib/steep/services/goto_service.rb +441 -0
  120. data/lib/steep/services/hover_provider/rbs.rb +88 -0
  121. data/lib/steep/services/hover_provider/ruby.rb +221 -0
  122. data/lib/steep/services/hover_provider/singleton_methods.rb +20 -0
  123. data/lib/steep/services/path_assignment.rb +46 -0
  124. data/lib/steep/services/signature_help_provider.rb +202 -0
  125. data/lib/steep/services/signature_service.rb +428 -0
  126. data/lib/steep/services/stats_calculator.rb +68 -0
  127. data/lib/steep/services/type_check_service.rb +394 -0
  128. data/lib/steep/services/type_name_completion.rb +236 -0
  129. data/lib/steep/signature/validator.rb +651 -0
  130. data/lib/steep/source/ignore_ranges.rb +69 -0
  131. data/lib/steep/source.rb +691 -0
  132. data/lib/steep/subtyping/cache.rb +30 -0
  133. data/lib/steep/subtyping/check.rb +1113 -0
  134. data/lib/steep/subtyping/constraints.rb +341 -0
  135. data/lib/steep/subtyping/relation.rb +101 -0
  136. data/lib/steep/subtyping/result.rb +324 -0
  137. data/lib/steep/subtyping/variable_variance.rb +89 -0
  138. data/lib/steep/test.rb +9 -0
  139. data/lib/steep/thread_waiter.rb +43 -0
  140. data/lib/steep/type_construction.rb +5183 -0
  141. data/lib/steep/type_inference/block_params.rb +416 -0
  142. data/lib/steep/type_inference/case_when.rb +303 -0
  143. data/lib/steep/type_inference/constant_env.rb +56 -0
  144. data/lib/steep/type_inference/context.rb +195 -0
  145. data/lib/steep/type_inference/logic_type_interpreter.rb +613 -0
  146. data/lib/steep/type_inference/method_call.rb +193 -0
  147. data/lib/steep/type_inference/method_params.rb +531 -0
  148. data/lib/steep/type_inference/multiple_assignment.rb +194 -0
  149. data/lib/steep/type_inference/send_args.rb +712 -0
  150. data/lib/steep/type_inference/type_env.rb +341 -0
  151. data/lib/steep/type_inference/type_env_builder.rb +138 -0
  152. data/lib/steep/typing.rb +321 -0
  153. data/lib/steep/version.rb +3 -0
  154. data/lib/steep.rb +369 -0
  155. data/manual/annotations.md +181 -0
  156. data/manual/ignore.md +20 -0
  157. data/manual/ruby-diagnostics.md +1879 -0
  158. data/sample/Steepfile +22 -0
  159. data/sample/lib/conference.rb +49 -0
  160. data/sample/lib/length.rb +35 -0
  161. data/sample/sig/conference.rbs +42 -0
  162. data/sample/sig/generics.rbs +15 -0
  163. data/sample/sig/length.rbs +34 -0
  164. data/steep-relaxed.gemspec +56 -0
  165. metadata +340 -0
@@ -0,0 +1,613 @@
1
+ module Steep
2
+ module TypeInference
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
+
20
+ attr_reader :subtyping
21
+ attr_reader :typing
22
+ attr_reader :config
23
+
24
+ def initialize(subtyping:, typing:, config:)
25
+ @subtyping = subtyping
26
+ @typing = typing
27
+ @config = config
28
+ end
29
+
30
+ def factory
31
+ subtyping.factory
32
+ end
33
+
34
+ def guess_type_from_method(node)
35
+ if node.type == :send
36
+ method = node.children[1]
37
+ case method
38
+ when :is_a?, :kind_of?, :instance_of?
39
+ AST::Types::Logic::ReceiverIsArg.instance
40
+ when :nil?
41
+ AST::Types::Logic::ReceiverIsNil.instance
42
+ when :!
43
+ AST::Types::Logic::Not.instance
44
+ when :===
45
+ AST::Types::Logic::ArgIsReceiver.instance
46
+ end
47
+ end
48
+ end
49
+
50
+ TRUE = AST::Types::Literal.new(value: true)
51
+ FALSE = AST::Types::Literal.new(value: false)
52
+ BOOL = AST::Types::Boolean.instance
53
+ BOT = AST::Types::Bot.instance
54
+ UNTYPED = AST::Types::Any.instance
55
+
56
+ def eval(env:, node:)
57
+ evaluate_node(env: env, node: node)
58
+ end
59
+
60
+ def evaluate_node(env:, node:, type: typing.type_of(node: node))
61
+ if type.is_a?(AST::Types::Logic::Env)
62
+ truthy_env = type.truthy
63
+ falsy_env = type.falsy
64
+
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
+ ]
78
+ end
79
+
80
+ if type.is_a?(AST::Types::Var)
81
+ type = config.upper_bound(type.name) || type
82
+ end
83
+
84
+ case node.type
85
+ when :lvar
86
+ name = node.children[0]
87
+ truthy_type, falsy_type = factory.partition_union(type)
88
+
89
+ truthy_result =
90
+ if truthy_type
91
+ Result.new(type: truthy_type, env: env.refine_types(local_variable_types: { name => truthy_type }), unreachable: false)
92
+ else
93
+ Result.new(type: type, env: env, unreachable: true)
94
+ end
95
+
96
+ falsy_result =
97
+ if falsy_type
98
+ Result.new(type: falsy_type, env: env.refine_types(local_variable_types: { name => falsy_type }), unreachable: false)
99
+ else
100
+ Result.new(type: type, env: env, unreachable: true)
101
+ end
102
+
103
+ return [truthy_result, falsy_result]
104
+
105
+ when :lvasgn
106
+ name, rhs = node.children
107
+ if TypeConstruction::SPECIAL_LVAR_NAMES.include?(name)
108
+ return [
109
+ Result.new(type: type, env: env, unreachable: false),
110
+ Result.new(type: type, env: env, unreachable: false)
111
+ ]
112
+ end
113
+
114
+ truthy_result, falsy_result = evaluate_node(env: env, node: rhs)
115
+
116
+ return [
117
+ truthy_result.update_env { evaluate_assignment(node, truthy_result.env, truthy_result.type) },
118
+ falsy_result.update_env { evaluate_assignment(node, falsy_result.env, falsy_result.type) }
119
+ ]
120
+
121
+ when :masgn
122
+ _, rhs = node.children
123
+ truthy_result, falsy_result = evaluate_node(env: env, node: rhs)
124
+
125
+ return [
126
+ truthy_result.update_env { evaluate_assignment(node, truthy_result.env, truthy_result.type) },
127
+ falsy_result.update_env { evaluate_assignment(node, falsy_result.env, falsy_result.type) }
128
+ ]
129
+
130
+ when :begin
131
+ last_node = node.children.last or raise
132
+ return evaluate_node(env: env, node: last_node)
133
+
134
+ when :csend
135
+ if type.is_a?(AST::Types::Any)
136
+ type = guess_type_from_method(node) || type
137
+ end
138
+
139
+ receiver, _, *arguments = node.children
140
+ receiver_type = typing.type_of(node: receiver)
141
+
142
+ truthy_receiver, falsy_receiver = evaluate_node(env: env, node: receiver)
143
+ truthy_type, _ = factory.partition_union(type)
144
+
145
+ truthy_result, falsy_result = evaluate_node(
146
+ env: truthy_receiver.env,
147
+ node: node.updated(:send),
148
+ type: truthy_type || type
149
+ )
150
+ truthy_result.unreachable! if truthy_receiver.unreachable
151
+
152
+ falsy_result = Result.new(
153
+ env: env.join(falsy_receiver.env, falsy_result.env),
154
+ unreachable: falsy_result.unreachable && falsy_receiver.unreachable,
155
+ type: falsy_result.type
156
+ )
157
+
158
+ return [truthy_result, falsy_result]
159
+
160
+ when :send
161
+ if type.is_a?(AST::Types::Any)
162
+ type = guess_type_from_method(node) || type
163
+ end
164
+
165
+ case type
166
+ when AST::Types::Logic::Base
167
+ receiver, _, *arguments = node.children
168
+ if (truthy_result, falsy_result = evaluate_method_call(env: env, type: type, receiver: receiver, arguments: arguments))
169
+ return [truthy_result, falsy_result]
170
+ end
171
+ else
172
+ if env[node]
173
+ truthy_type, falsy_type = factory.partition_union(type)
174
+
175
+ truthy_result =
176
+ if truthy_type
177
+ Result.new(type: truthy_type, env: env.refine_types(pure_call_types: { node => truthy_type }), unreachable: false)
178
+ else
179
+ Result.new(type: type, env: env, unreachable: true)
180
+ end
181
+
182
+ falsy_result =
183
+ if falsy_type
184
+ Result.new(type: falsy_type, env: env.refine_types(pure_call_types: { node => falsy_type }), unreachable: false)
185
+ else
186
+ Result.new(type: type, env: env, unreachable: true)
187
+ end
188
+
189
+ return [truthy_result, falsy_result]
190
+ end
191
+ end
192
+ end
193
+
194
+ truthy_type, falsy_type = factory.partition_union(type)
195
+ return [
196
+ Result.new(type: truthy_type || BOT, env: env, unreachable: truthy_type.nil?),
197
+ Result.new(type: falsy_type || BOT, env: env, unreachable: falsy_type.nil?)
198
+ ]
199
+ end
200
+
201
+ def evaluate_assignment(assignment_node, env, rhs_type)
202
+ case assignment_node.type
203
+ when :lvasgn
204
+ name, _ = assignment_node.children
205
+ if TypeConstruction::SPECIAL_LVAR_NAMES.include?(name)
206
+ env
207
+ else
208
+ env.refine_types(local_variable_types: { name => rhs_type })
209
+ end
210
+ when :masgn
211
+ lhs, _ = assignment_node.children
212
+
213
+ masgn = MultipleAssignment.new()
214
+ assignments = masgn.expand(lhs, rhs_type, false)
215
+ unless assignments
216
+ rhs_type_converted = try_convert(rhs_type, :to_ary)
217
+ rhs_type_converted ||= try_convert(rhs_type, :to_a)
218
+ rhs_type_converted ||= AST::Types::Tuple.new(types: [rhs_type])
219
+ assignments = masgn.expand(lhs, rhs_type_converted, false)
220
+ end
221
+
222
+ unless assignments
223
+ raise "Multiple assignment rhs doesn't look correct: #{rhs_type.to_s} (#{assignment_node.location.expression&.source_line})"
224
+ end
225
+
226
+ assignments.each do |pair|
227
+ node, type = pair
228
+ env = evaluate_assignment(node, env, type)
229
+ end
230
+
231
+ env
232
+ else
233
+ env
234
+ end
235
+ end
236
+
237
+ def refine_node_type(env:, node:, truthy_type:, falsy_type:)
238
+ case node.type
239
+ when :lvar
240
+ name = node.children[0]
241
+
242
+ if TypeConstruction::SPECIAL_LVAR_NAMES.include?(name)
243
+ [env, env]
244
+ else
245
+ [
246
+ env.refine_types(local_variable_types: { name => truthy_type }),
247
+ env.refine_types(local_variable_types: { name => falsy_type })
248
+ ]
249
+ end
250
+
251
+ when :lvasgn
252
+ name, rhs = node.children
253
+
254
+ truthy_env, falsy_env = refine_node_type(env: env, node: rhs, truthy_type: truthy_type, falsy_type: falsy_type)
255
+
256
+ if TypeConstruction::SPECIAL_LVAR_NAMES.include?(name)
257
+ [truthy_env, falsy_env]
258
+ else
259
+ [
260
+ truthy_env.refine_types(local_variable_types: { name => truthy_type }),
261
+ falsy_env.refine_types(local_variable_types: { name => falsy_type })
262
+ ]
263
+ end
264
+
265
+ when :send
266
+ if env[node]
267
+ [
268
+ env.refine_types(pure_call_types: { node => truthy_type }),
269
+ env.refine_types(pure_call_types: { node => falsy_type })
270
+ ]
271
+ else
272
+ [env, env]
273
+ end
274
+ when :begin
275
+ last_node = node.children.last or raise
276
+ refine_node_type(env: env, node: last_node, truthy_type: truthy_type, falsy_type: falsy_type)
277
+ else
278
+ [env, env]
279
+ end
280
+ end
281
+
282
+ def evaluate_method_call(env:, type:, receiver:, arguments:)
283
+ case type
284
+ when AST::Types::Logic::ReceiverIsNil
285
+ if receiver && arguments.size.zero?
286
+ receiver_type = typing.type_of(node: receiver)
287
+ unwrap = factory.unwrap_optional(receiver_type)
288
+ truthy_receiver = AST::Builtin.nil_type
289
+ falsy_receiver = unwrap || receiver_type
290
+
291
+ truthy_env, falsy_env = refine_node_type(
292
+ env: env,
293
+ node: receiver,
294
+ truthy_type: truthy_receiver,
295
+ falsy_type: falsy_receiver
296
+ )
297
+
298
+ truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
299
+ truthy_result.unreachable! if no_subtyping?(sub_type: AST::Builtin.nil_type, super_type: receiver_type)
300
+
301
+ falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
302
+ falsy_result.unreachable! unless unwrap
303
+
304
+ [truthy_result, falsy_result]
305
+ end
306
+
307
+ when AST::Types::Logic::ReceiverIsArg
308
+ if receiver && (arg = arguments[0])
309
+ receiver_type = typing.type_of(node: receiver)
310
+ arg_type = factory.deep_expand_alias(typing.type_of(node: arg))
311
+
312
+ if arg_type.is_a?(AST::Types::Name::Singleton)
313
+ truthy_type, falsy_type = type_case_select(receiver_type, arg_type.name)
314
+ truthy_env, falsy_env = refine_node_type(
315
+ env: env,
316
+ node: receiver,
317
+ truthy_type: truthy_type || factory.instance_type(arg_type.name),
318
+ falsy_type: falsy_type || UNTYPED
319
+ )
320
+
321
+ truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
322
+ truthy_result.unreachable! unless truthy_type
323
+
324
+ falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
325
+ falsy_result.unreachable! unless falsy_type
326
+
327
+ [truthy_result, falsy_result]
328
+ end
329
+ end
330
+
331
+ when AST::Types::Logic::ArgIsReceiver
332
+ if receiver && (arg = arguments[0])
333
+ receiver_type = factory.deep_expand_alias(typing.type_of(node: receiver))
334
+ arg_type = typing.type_of(node: arg)
335
+
336
+ if receiver_type.is_a?(AST::Types::Name::Singleton)
337
+ truthy_type, falsy_type = type_case_select(arg_type, receiver_type.name)
338
+ truthy_env, falsy_env = refine_node_type(
339
+ env: env,
340
+ node: arg,
341
+ truthy_type: truthy_type || factory.instance_type(receiver_type.name),
342
+ falsy_type: falsy_type || UNTYPED
343
+ )
344
+
345
+ truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
346
+ truthy_result.unreachable! unless truthy_type
347
+
348
+ falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
349
+ falsy_result.unreachable! unless falsy_type
350
+
351
+ [truthy_result, falsy_result]
352
+ end
353
+ end
354
+ when AST::Types::Logic::ArgEqualsReceiver
355
+ if receiver && (arg = arguments[0])
356
+ arg_type = factory.expand_alias(typing.type_of(node: arg))
357
+ if (truthy_types, falsy_types = literal_var_type_case_select(receiver, arg_type))
358
+ truthy_env, falsy_env = refine_node_type(
359
+ env: env,
360
+ node: arg,
361
+ truthy_type: truthy_types.empty? ? BOT : AST::Types::Union.build(types: truthy_types),
362
+ falsy_type: falsy_types.empty? ? BOT : AST::Types::Union.build(types: falsy_types)
363
+ )
364
+
365
+ truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
366
+ truthy_result.unreachable! if truthy_types.empty?
367
+
368
+ falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
369
+ falsy_result.unreachable! if falsy_types.empty?
370
+
371
+ [truthy_result, falsy_result]
372
+ end
373
+ end
374
+
375
+ when AST::Types::Logic::ArgIsAncestor
376
+ if receiver && (arg = arguments[0])
377
+ receiver_type = typing.type_of(node: receiver)
378
+ arg_type = factory.deep_expand_alias(typing.type_of(node: arg))
379
+
380
+ if arg_type.is_a?(AST::Types::Name::Singleton)
381
+ truthy_type = arg_type
382
+ falsy_type = receiver_type
383
+ truthy_env, falsy_env = refine_node_type(
384
+ env: env,
385
+ node: receiver,
386
+ truthy_type: truthy_type,
387
+ falsy_type: falsy_type
388
+ )
389
+
390
+ truthy_result = Result.new(type: TRUE, env: truthy_env, unreachable: false)
391
+ truthy_result.unreachable! unless truthy_type
392
+
393
+ falsy_result = Result.new(type: FALSE, env: falsy_env, unreachable: false)
394
+ falsy_result.unreachable! unless falsy_type
395
+
396
+ [truthy_result, falsy_result]
397
+ end
398
+ end
399
+
400
+ when AST::Types::Logic::Not
401
+ if receiver
402
+ truthy_result, falsy_result = evaluate_node(env: env, node: receiver)
403
+ [
404
+ falsy_result.update_type { TRUE },
405
+ truthy_result.update_type { FALSE }
406
+ ]
407
+ end
408
+ end
409
+ end
410
+
411
+ def decompose_value(node)
412
+ case node.type
413
+ when :lvar
414
+ [node, Set[node.children[0]]]
415
+ when :masgn
416
+ _, rhs = node.children
417
+ decompose_value(rhs)
418
+ when :lvasgn
419
+ var, rhs = node.children
420
+ val, vars = decompose_value(rhs)
421
+ [val, vars + [var]]
422
+ when :begin
423
+ decompose_value(node.children.last)
424
+ when :and
425
+ left, right = node.children
426
+ _, left_vars = decompose_value(left)
427
+ val, right_vars = decompose_value(right)
428
+ [val, left_vars + right_vars]
429
+ else
430
+ [node, Set[]]
431
+ end
432
+ end
433
+
434
+ def literal_var_type_case_select(value_node, arg_type)
435
+ case arg_type
436
+ when AST::Types::Union
437
+ # @type var truthy_types: Array[AST::Types::t]
438
+ truthy_types = []
439
+ # @type var falsy_types: Array[AST::Types::t]
440
+ falsy_types = []
441
+
442
+ arg_type.types.each do |type|
443
+ if (ts, fs = literal_var_type_case_select(value_node, type))
444
+ truthy_types.push(*ts)
445
+ falsy_types.push(*fs)
446
+ else
447
+ return
448
+ end
449
+ end
450
+
451
+ [truthy_types, falsy_types]
452
+ when AST::Types::Boolean
453
+ [[arg_type], [arg_type]]
454
+ when AST::Types::Top, AST::Types::Any
455
+ [[arg_type], [arg_type]]
456
+ else
457
+ types = [arg_type]
458
+
459
+ case value_node.type
460
+ when :nil
461
+ types.partition do |type|
462
+ type.is_a?(AST::Types::Nil) || AST::Builtin::NilClass.instance_type?(type)
463
+ end
464
+ when :true
465
+ types.partition do |type|
466
+ AST::Builtin::TrueClass.instance_type?(type) ||
467
+ (type.is_a?(AST::Types::Literal) && type.value == true)
468
+ end
469
+ when :false
470
+ types.partition do |type|
471
+ AST::Builtin::FalseClass.instance_type?(type) ||
472
+ (type.is_a?(AST::Types::Literal) && type.value == false)
473
+ end
474
+ when :int, :str, :sym
475
+ # @type var pairs: [Array[AST::Types::t], Array[AST::Types::t]]
476
+ pairs = [[], []]
477
+
478
+ types.each_with_object(pairs) do |type, pair|
479
+ true_types, false_types = pair
480
+
481
+ case
482
+ when type.is_a?(AST::Types::Literal)
483
+ if type.value == value_node.children[0]
484
+ true_types << type
485
+ else
486
+ false_types << type
487
+ end
488
+ else
489
+ true_types << AST::Types::Literal.new(value: value_node.children[0])
490
+ false_types << type
491
+ end
492
+ end
493
+ end
494
+ end
495
+ end
496
+
497
+ def type_case_select(type, klass)
498
+ truth_types, false_types = type_case_select0(type, klass)
499
+
500
+ [
501
+ truth_types.empty? ? nil : AST::Types::Union.build(types: truth_types),
502
+ false_types.empty? ? nil : AST::Types::Union.build(types: false_types)
503
+ ]
504
+ end
505
+
506
+ def type_case_select0(type, klass)
507
+ instance_type = factory.instance_type(klass)
508
+
509
+ case type
510
+ when AST::Types::Union
511
+ truthy_types = [] # :Array[AST::Types::t]
512
+ falsy_types = [] #: Array[AST::Types::t]
513
+
514
+ type.types.each do |ty|
515
+ truths, falses = type_case_select0(ty, klass)
516
+
517
+ if truths.empty?
518
+ falsy_types.push(ty)
519
+ else
520
+ truthy_types.push(*truths)
521
+ falsy_types.push(*falses)
522
+ end
523
+ end
524
+
525
+ [truthy_types, falsy_types]
526
+
527
+ when AST::Types::Name::Alias
528
+ ty = factory.expand_alias(type)
529
+ if ty == type
530
+ [[type], [type]]
531
+ else
532
+ type_case_select0(ty, klass)
533
+ end
534
+
535
+ when AST::Types::Any, AST::Types::Top, AST::Types::Var
536
+ [
537
+ [instance_type],
538
+ [type]
539
+ ]
540
+
541
+ when AST::Types::Name::Interface
542
+ [
543
+ [instance_type],
544
+ [type]
545
+ ]
546
+
547
+ else
548
+ # There are four possible relations between `type` and `instance_type`
549
+ #
550
+ # ```ruby
551
+ # case object # object: T
552
+ # when K # K: singleton(K)
553
+ # when ...
554
+ # end
555
+ # ````
556
+ #
557
+ # 1. T <: K && K <: T (T == K, T = Integer, K = Numeric)
558
+ # 2. T <: K (example: T = Integer, K = Numeric)
559
+ # 3. K <: T (example: T = Numeric, K = Integer)
560
+ # 4. none of the above (example: T = String, K = Integer)
561
+
562
+ if subtyping?(sub_type: type, super_type: instance_type)
563
+ # 1 or 2. Satisfies the condition, no narrowing because `type` is already more specific than/equals to `instance_type`
564
+ [
565
+ [type],
566
+ []
567
+ ]
568
+ else
569
+ if subtyping?(sub_type: instance_type, super_type: type)
570
+ # 3. Satisfied the condition, narrows to `instance_type`, but cannot remove it from *falsy* list
571
+ [
572
+ [instance_type],
573
+ [type]
574
+ ]
575
+ else
576
+ # 4
577
+ [
578
+ [],
579
+ [type]
580
+ ]
581
+ end
582
+ end
583
+ end
584
+ end
585
+
586
+ def no_subtyping?(sub_type:, super_type:)
587
+ relation = Subtyping::Relation.new(sub_type: sub_type, super_type: super_type)
588
+ result = subtyping.check(relation, constraints: Subtyping::Constraints.empty, self_type: AST::Types::Self.instance, instance_type: AST::Types::Instance.instance, class_type: AST::Types::Class.instance)
589
+
590
+ if result.failure?
591
+ result
592
+ end
593
+ end
594
+
595
+ def subtyping?(sub_type:, super_type:)
596
+ !no_subtyping?(sub_type: sub_type, super_type: super_type)
597
+ end
598
+
599
+ def try_convert(type, method)
600
+ if shape = subtyping.builder.shape(type, config)
601
+ if entry = shape.methods[method]
602
+ method_type = entry.method_types.find do |method_type|
603
+ method_type.type.params.nil? ||
604
+ method_type.type.params.optional?
605
+ end
606
+
607
+ method_type.type.return_type if method_type
608
+ end
609
+ end
610
+ end
611
+ end
612
+ end
613
+ end