typeprof 0.21.11 → 0.30.0

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 (73) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -31
  3. data/bin/typeprof +5 -0
  4. data/doc/doc.ja.md +134 -0
  5. data/doc/doc.md +136 -0
  6. data/lib/typeprof/cli/cli.rb +180 -0
  7. data/lib/typeprof/cli.rb +2 -133
  8. data/lib/typeprof/code_range.rb +112 -0
  9. data/lib/typeprof/core/ast/base.rb +263 -0
  10. data/lib/typeprof/core/ast/call.rb +251 -0
  11. data/lib/typeprof/core/ast/const.rb +126 -0
  12. data/lib/typeprof/core/ast/control.rb +432 -0
  13. data/lib/typeprof/core/ast/meta.rb +150 -0
  14. data/lib/typeprof/core/ast/method.rb +335 -0
  15. data/lib/typeprof/core/ast/misc.rb +263 -0
  16. data/lib/typeprof/core/ast/module.rb +123 -0
  17. data/lib/typeprof/core/ast/pattern.rb +140 -0
  18. data/lib/typeprof/core/ast/sig_decl.rb +471 -0
  19. data/lib/typeprof/core/ast/sig_type.rb +663 -0
  20. data/lib/typeprof/core/ast/value.rb +319 -0
  21. data/lib/typeprof/core/ast/variable.rb +315 -0
  22. data/lib/typeprof/core/ast.rb +472 -0
  23. data/lib/typeprof/core/builtin.rb +146 -0
  24. data/lib/typeprof/core/env/method.rb +137 -0
  25. data/lib/typeprof/core/env/method_entity.rb +55 -0
  26. data/lib/typeprof/core/env/module_entity.rb +408 -0
  27. data/lib/typeprof/core/env/static_read.rb +155 -0
  28. data/lib/typeprof/core/env/type_alias_entity.rb +27 -0
  29. data/lib/typeprof/core/env/value_entity.rb +32 -0
  30. data/lib/typeprof/core/env.rb +360 -0
  31. data/lib/typeprof/core/graph/box.rb +991 -0
  32. data/lib/typeprof/core/graph/change_set.rb +224 -0
  33. data/lib/typeprof/core/graph/filter.rb +155 -0
  34. data/lib/typeprof/core/graph/vertex.rb +222 -0
  35. data/lib/typeprof/core/graph.rb +3 -0
  36. data/lib/typeprof/core/service.rb +522 -0
  37. data/lib/typeprof/core/type.rb +348 -0
  38. data/lib/typeprof/core/util.rb +81 -0
  39. data/lib/typeprof/core.rb +32 -0
  40. data/lib/typeprof/diagnostic.rb +35 -0
  41. data/lib/typeprof/lsp/messages.rb +430 -0
  42. data/lib/typeprof/lsp/server.rb +177 -0
  43. data/lib/typeprof/lsp/text.rb +69 -0
  44. data/lib/typeprof/lsp/util.rb +61 -0
  45. data/lib/typeprof/lsp.rb +4 -907
  46. data/lib/typeprof/version.rb +1 -1
  47. data/lib/typeprof.rb +4 -18
  48. data/typeprof.gemspec +5 -7
  49. metadata +48 -35
  50. data/.github/dependabot.yml +0 -6
  51. data/.github/workflows/main.yml +0 -39
  52. data/.gitignore +0 -9
  53. data/Gemfile +0 -17
  54. data/Gemfile.lock +0 -41
  55. data/Rakefile +0 -10
  56. data/exe/typeprof +0 -10
  57. data/lib/typeprof/analyzer.rb +0 -2598
  58. data/lib/typeprof/arguments.rb +0 -414
  59. data/lib/typeprof/block.rb +0 -176
  60. data/lib/typeprof/builtin.rb +0 -893
  61. data/lib/typeprof/code-range.rb +0 -177
  62. data/lib/typeprof/config.rb +0 -158
  63. data/lib/typeprof/container-type.rb +0 -912
  64. data/lib/typeprof/export.rb +0 -589
  65. data/lib/typeprof/import.rb +0 -852
  66. data/lib/typeprof/insns-def.rb +0 -65
  67. data/lib/typeprof/iseq.rb +0 -864
  68. data/lib/typeprof/method.rb +0 -355
  69. data/lib/typeprof/type.rb +0 -1140
  70. data/lib/typeprof/utils.rb +0 -212
  71. data/tools/coverage.rb +0 -14
  72. data/tools/setup-insns-def.rb +0 -30
  73. data/typeprof-lsp +0 -3
data/lib/typeprof/type.rb DELETED
@@ -1,1140 +0,0 @@
1
- module TypeProf
2
- class Type # or AbstractValue
3
- include Utils::StructuralEquality
4
-
5
- def initialize
6
- raise "cannot instantiate abstract type"
7
- end
8
-
9
- Builtin = {}
10
-
11
- def globalize(_env, _visited, _depth)
12
- self
13
- end
14
-
15
- def localize(env, _alloc_site, _depth)
16
- return env, self
17
- end
18
-
19
- def limit_size(limit)
20
- self
21
- end
22
-
23
- def self.match?(ty1, ty2)
24
- # both ty1 and ty2 should be global
25
- # ty1 is always concrete; it should not have type variables
26
- # ty2 might be abstract; it may have type variables
27
- case ty2
28
- when Type::Var
29
- { ty2 => ty1 }
30
- when Type::Any
31
- {}
32
- when Type::Union
33
- subst = nil
34
- ty2.each_child_global do |ty2|
35
- # this is very conservative to create subst:
36
- # Type.match?( int | str, int | X) creates { X => int | str } but should be { X => str }???
37
- subst2 = Type.match?(ty1, ty2)
38
- next unless subst2
39
- subst = Type.merge_substitution(subst, subst2)
40
- end
41
- subst
42
- else
43
- case ty1
44
- when Type::Var then raise "should not occur"
45
- when Type::Any
46
- subst = {}
47
- ty2.each_free_type_variable do |tyvar|
48
- subst[tyvar] = Type.any
49
- end
50
- subst
51
- when Type::Union
52
- subst = nil
53
- ty1.each_child_global do |ty1|
54
- subst2 = Type.match?(ty1, ty2)
55
- next unless subst2
56
- subst = Type.merge_substitution(subst, subst2)
57
- end
58
- subst
59
- else
60
- if ty2.is_a?(Type::ContainerType)
61
- # ty2 may have type variables
62
- if ty1.class == ty2.class
63
- ty1.match?(ty2)
64
- else
65
- Type.match?(ty1, ty2.base_type)
66
- end
67
- elsif ty1.is_a?(Type::ContainerType)
68
- Type.match?(ty1.base_type, ty2)
69
- else
70
- ty1.consistent?(ty2) ? {} : nil
71
- end
72
- end
73
- end
74
- end
75
-
76
- def self.merge_substitution(subst1, subst2)
77
- if subst1
78
- subst1 = subst1.dup
79
- subst2.each do |tyvar, ty|
80
- if subst1[tyvar]
81
- subst1[tyvar] = subst1[tyvar].union(ty)
82
- else
83
- subst1[tyvar] = ty
84
- end
85
- end
86
- subst1
87
- else
88
- subst2
89
- end
90
- end
91
-
92
- def each_child
93
- yield self
94
- end
95
-
96
- def each_child_global
97
- yield self
98
- end
99
-
100
- def each_free_type_variable
101
- end
102
-
103
- def union(other)
104
- return self if self == other # fastpath
105
-
106
- ty1, ty2 = self, other
107
-
108
- case
109
- when ty1.is_a?(Union)
110
- ty1_types = ty1.types
111
- ty1_elems = ty1.elems
112
- when ty1.is_a?(Array) || ty1.is_a?(Hash)
113
- ty1_types = Utils::Set[]
114
- ty1_elems = {[ty1.class, ty1.base_type] => ty1.elems}
115
- else
116
- ty1_types = ty1_elems = nil
117
- end
118
-
119
- case
120
- when ty2.is_a?(Union)
121
- ty2_types = ty2.types
122
- ty2_elems = ty2.elems
123
- when ty2.is_a?(Array) || ty2.is_a?(Hash)
124
- ty2_types = Utils::Set[]
125
- ty2_elems = {[ty2.class, ty2.base_type] => ty2.elems}
126
- else
127
- ty2_types = ty2_elems = nil
128
- end
129
-
130
- if ty1_types && ty2_types
131
- ty = ty1_types.sum(ty2_types)
132
- all_elems = ty1_elems.dup || {}
133
- ty2_elems&.each do |key, elems|
134
- all_elems[key] = union_elems(all_elems[key], elems)
135
- end
136
- all_elems = nil if all_elems.empty?
137
-
138
- Type::Union.create(ty, all_elems)
139
- elsif ty1_types
140
- Type::Union.create(ty1_types.add(ty2), ty1_elems)
141
- elsif ty2_types
142
- Type::Union.create(ty2_types.add(ty1), ty2_elems)
143
- else
144
- Type::Union.create(Utils::Set[ty1, ty2], nil)
145
- end
146
- end
147
-
148
- private def union_elems(e1, e2)
149
- if e1
150
- if e2
151
- e1.union(e2)
152
- else
153
- e1
154
- end
155
- else
156
- e2
157
- end
158
- end
159
-
160
- def substitute(_subst, _depth)
161
- raise "cannot substitute abstract type: #{ self.class }"
162
- end
163
-
164
- def generate_substitution
165
- {}
166
- end
167
-
168
- DummySubstitution = Object.new
169
- def DummySubstitution.[](_)
170
- Type.any
171
- end
172
-
173
- def remove_type_vars
174
- substitute(DummySubstitution, Config.current.options[:type_depth_limit])
175
- end
176
-
177
- def include_untyped?(_scratch)
178
- false
179
- end
180
-
181
- class Any < Type
182
- def initialize
183
- end
184
-
185
- def inspect
186
- "Type::Any"
187
- end
188
-
189
- def screen_name(scratch)
190
- "untyped"
191
- end
192
-
193
- def method_dispatch_info
194
- nil
195
- end
196
-
197
- def consistent?(_other)
198
- raise "should not be called"
199
- end
200
-
201
- def substitute(_subst, _depth)
202
- self
203
- end
204
-
205
- def include_untyped?(_scratch)
206
- true
207
- end
208
- end
209
-
210
- class Void < Any
211
- def inspect
212
- "Type::Void"
213
- end
214
-
215
- def screen_name(scratch)
216
- "void"
217
- end
218
- end
219
-
220
-
221
- class Union < Type
222
- def self.create(tys, elems)
223
- if tys.size == 1 && !elems
224
- tys.each {|ty| return ty }
225
- elsif tys.size == 0
226
- if elems && elems.size == 1
227
- (container_kind, base_type), nelems = elems.first
228
- # container_kind = Type::Array or Type::Hash
229
- container_kind.new(nelems, base_type)
230
- else
231
- new(tys, elems)
232
- end
233
- else
234
- class_instances = []
235
- non_class_instances = []
236
- degenerated = false
237
- tys.each do |ty|
238
- if ty != Type::Instance.new(Type::Builtin[:nil]) && ty.is_a?(Type::Instance) && ty.klass.kind == :class
239
- class_instances << ty
240
- degenerated = true if ty.include_subclasses
241
- else
242
- non_class_instances << ty
243
- end
244
- end
245
- if (Config.current.options[:union_width_limit] >= 2 && class_instances.size >= Config.current.options[:union_width_limit]) || (degenerated && class_instances.size >= 2)
246
- create(Utils::Set[Instance.new_degenerate(class_instances), *non_class_instances], elems)
247
- else
248
- new(tys, elems)
249
- end
250
- end
251
- end
252
-
253
- def initialize(tys, elems)
254
- raise unless tys.is_a?(Utils::Set)
255
- @types = tys # Set
256
-
257
- # invariant check
258
- local = nil
259
- tys.each do |ty|
260
- raise ty.inspect unless ty.is_a?(Type)
261
- local = true if ty.is_a?(Local)
262
- end
263
- raise if local && elems
264
-
265
- @elems = elems
266
- raise elems.inspect if elems && !elems.is_a?(::Hash)
267
- end
268
-
269
- def each_free_type_variable(&blk)
270
- each_child_global do |ty|
271
- ty.each_free_type_variable(&blk)
272
- end
273
- end
274
-
275
- def limit_size(limit)
276
- return Type.any if limit <= 0
277
- tys = Utils::Set[]
278
- @types.each do |ty|
279
- tys = tys.add(ty.limit_size(limit - 1))
280
- end
281
- elems = @elems&.to_h do |key, elems|
282
- [key, elems.limit_size(limit - 1)]
283
- end
284
- Union.new(tys, elems)
285
- end
286
-
287
- attr_reader :types, :elems
288
-
289
- def each_child(&blk) # local
290
- @types.each(&blk)
291
- raise if @elems
292
- end
293
-
294
- def each_child_global(&blk)
295
- @types.each(&blk)
296
- @elems&.each do |(container_kind, base_type), elems|
297
- yield container_kind.new(elems, base_type)
298
- end
299
- end
300
-
301
- def inspect
302
- a = []
303
- a << "Type::Union{#{ @types.to_a.map {|ty| ty.inspect }.join(", ") }"
304
- @elems&.each do |(container_kind, base_type), elems|
305
- a << ", #{ container_kind.new(elems, base_type).inspect }"
306
- end
307
- a << "}"
308
- a.join
309
- end
310
-
311
- def screen_name(scratch)
312
- types = @types.to_a
313
- @elems&.each do |(container_kind, base_type), elems|
314
- types << container_kind.new(elems, base_type)
315
- end
316
- if types.size == 0
317
- "bot"
318
- else
319
- types = types.to_a
320
- optional = !!types.delete(Type::Instance.new(Type::Builtin[:nil]))
321
- bool = false
322
- if types.include?(Type::Instance.new(Type::Builtin[:false])) &&
323
- types.include?(Type::Instance.new(Type::Builtin[:true]))
324
- types.delete(Type::Instance.new(Type::Builtin[:false]))
325
- types.delete(Type::Instance.new(Type::Builtin[:true]))
326
- bool = true
327
- end
328
- types.delete(Type.any) unless Config.current.options[:show_untyped]
329
- proc_tys, types = types.partition {|ty| ty.is_a?(Proc) }
330
- types = types.map {|ty| ty.screen_name(scratch) }
331
- types << scratch.show_proc_signature(proc_tys) unless proc_tys.empty?
332
- types << "bool" if bool
333
- types = types.sort
334
- if optional
335
- case types.size
336
- when 0 then "nil"
337
- when 1 then types.first + "?"
338
- else
339
- "(#{ types.join (" | ") })?"
340
- end
341
- else
342
- types.join (" | ")
343
- end
344
- end
345
- end
346
-
347
- def globalize(env, visited, depth)
348
- return Type.any if depth <= 0
349
- tys = Utils::Set[]
350
- if @elems
351
- # XXX: If @elems is non nil, the Union type should global, so calling globalize against such a type should not occur.
352
- # However, currently, ActualArguments may contain global types for flag_args_kw_splat case.
353
- # This should be fixed in future in ActualArguments side. See Scratch#setup_actual_arguments.
354
- #raise
355
- end
356
-
357
- elems = @elems ? @elems.dup : {}
358
- @types.each do |ty|
359
- ty = ty.globalize(env, visited, depth - 1)
360
- case ty
361
- when Type::Array, Type::Hash
362
- key = [ty.class, ty.base_type]
363
- elems[key] = union_elems(elems[key], ty.elems)
364
- else
365
- tys = tys.add(ty)
366
- end
367
- end
368
- elems = nil if elems.empty?
369
-
370
- Type::Union.create(tys, elems)
371
- end
372
-
373
- def localize(env, alloc_site, depth)
374
- return env, Type.any if depth <= 0
375
- tys = @types.map do |ty|
376
- env, ty2 = ty.localize(env, alloc_site, depth - 1)
377
- ty2
378
- end
379
- @elems&.each do |(container_kind, base_type), elems|
380
- ty = container_kind.new(elems, base_type)
381
- env, ty = ty.localize(env, alloc_site, depth - 1)
382
- tys = tys.add(ty)
383
- end
384
- ty = Union.create(tys, nil)
385
- return env, ty
386
- end
387
-
388
- def consistent?(_other)
389
- raise "should not be called"
390
- end
391
-
392
- def substitute(subst, depth)
393
- return Type.any if depth <= 0
394
- unions = []
395
- tys = Utils::Set[]
396
- @types.each do |ty|
397
- ty = ty.substitute(subst, depth - 1)
398
- case ty
399
- when Union
400
- unions << ty
401
- else
402
- tys = tys.add(ty)
403
- end
404
- end
405
- elems = @elems&.to_h do |(container_kind, base_type), elems|
406
- [[container_kind, base_type], elems.substitute(subst, depth - 1)]
407
- end
408
- ty = Union.create(tys, elems)
409
- unions.each do |ty0|
410
- ty = ty.union(ty0)
411
- end
412
- ty
413
- end
414
-
415
- def include_untyped?(scratch)
416
- @types.each do |ty|
417
- return true if ty.include_untyped?(scratch)
418
- end
419
- @elems&.each do |(container_kind, base_type), elems|
420
- return true if base_type.include_untyped?(scratch)
421
- return true if elems.include_untyped?(scratch)
422
- end
423
- false
424
- end
425
- end
426
-
427
- def self.any
428
- Thread.current[:any] ||= Any.new
429
- end
430
-
431
- def self.bot
432
- Thread.current[:bot] ||= Union.new(Utils::Set[], nil)
433
- end
434
-
435
- def self.bool
436
- Thread.current[:bool] ||= Union.new(Utils::Set[
437
- Instance.new(Type::Builtin[:true]),
438
- Instance.new(Type::Builtin[:false])
439
- ], nil)
440
- end
441
-
442
- def self.nil
443
- Thread.current[:nil] ||= Instance.new(Type::Builtin[:nil])
444
- end
445
-
446
- def self.optional(ty)
447
- ty.union(Type.nil)
448
- end
449
-
450
- class Var < Type
451
- def initialize(name)
452
- @name = name
453
- end
454
-
455
- def screen_name(scratch)
456
- "Var[#{ @name }]"
457
- end
458
-
459
- def each_free_type_variable
460
- yield self
461
- end
462
-
463
- def substitute(subst, depth)
464
- if subst[self]
465
- subst[self].limit_size(depth)
466
- else
467
- self
468
- end
469
- end
470
-
471
- def consistent?(_other)
472
- raise "should not be called: #{ self }"
473
- end
474
-
475
- def add_subst!(ty, subst)
476
- if subst[self]
477
- subst[self] = subst[self].union(ty)
478
- else
479
- subst[self] = ty
480
- end
481
- true
482
- end
483
- end
484
-
485
- class Class < Type # or Module
486
- def initialize(kind, idx, type_params, superclass, name)
487
- @kind = kind # :class | :module
488
- @idx = idx
489
- @type_params = type_params
490
- @superclass = superclass
491
- raise if @kind == :class && !@superclass
492
- @_name = name
493
- end
494
-
495
- attr_reader :kind, :idx, :type_params, :superclass
496
- attr_accessor :superclass_type_args
497
-
498
- def inspect
499
- if @_name
500
- "#{ @_name }@#{ @idx }"
501
- else
502
- "Class[#{ @idx }]"
503
- end
504
- end
505
-
506
- def screen_name(scratch)
507
- "singleton(#{ scratch.get_class_name(self) })"
508
- end
509
-
510
- def method_dispatch_info
511
- [self, true, false]
512
- end
513
-
514
- def consistent?(other)
515
- case other
516
- when Type::Class
517
- ty = self
518
- loop do
519
- # ad-hoc
520
- return false if !ty || !other # module
521
-
522
- return true if ty.idx == other.idx
523
- return false if ty.idx == 0 # Object
524
- ty = ty.superclass
525
- end
526
- when Type::Instance
527
- return true if other.klass == Type::Builtin[:obj] || other.klass == Type::Builtin[:class] || other.klass == Type::Builtin[:module]
528
- return false
529
- else
530
- false
531
- end
532
- end
533
-
534
- def substitute(_subst, _depth)
535
- self
536
- end
537
- end
538
-
539
- class Instance < Type
540
- def initialize(klass, include_subclasses=false)
541
- raise unless klass
542
- raise if klass == Type.any
543
- raise if klass.is_a?(Type::Instance)
544
- raise if klass.is_a?(Type::Union)
545
- @klass = klass
546
- @include_subclasses = include_subclasses
547
- end
548
-
549
- def self.new_degenerate(instances)
550
- klass = instances.first.klass
551
- ancestors = []
552
- ancestor_idxs = {}
553
- while klass != :__root__
554
- ancestor_idxs[klass] = ancestors.size
555
- ancestors << klass
556
- klass = klass.superclass
557
- end
558
- common_superclass = nil
559
- instances[1..].each do |instance|
560
- klass = instance.klass
561
- while !ancestor_idxs[klass]
562
- klass = klass.superclass
563
- end
564
- common_superclass = klass
565
- ancestor_idxs[klass].times do |i|
566
- ancestor_idxs.delete(ancestors[i])
567
- ancestors[i] = nil
568
- end
569
- end
570
- new(common_superclass, true)
571
- end
572
-
573
- attr_reader :klass, :include_subclasses
574
-
575
- def inspect
576
- "I[#{ @klass.inspect }]"
577
- end
578
-
579
- def screen_name(scratch)
580
- case @klass
581
- when Type::Builtin[:nil] then "nil"
582
- when Type::Builtin[:true] then "true"
583
- when Type::Builtin[:false] then "false"
584
- else
585
- scratch.get_class_name(@klass) + (@include_subclasses ? "" : "")
586
- end
587
- end
588
-
589
- def method_dispatch_info
590
- [@klass, false, @include_subclasses]
591
- end
592
-
593
- def consistent?(other)
594
- case other
595
- when Type::Instance
596
- @klass.consistent?(other.klass)
597
- when Type::Class
598
- return true if @klass == Type::Builtin[:obj] || @klass == Type::Builtin[:class] || @klass == Type::Builtin[:module]
599
- return false
600
- else
601
- false
602
- end
603
- end
604
-
605
- def substitute(subst, depth)
606
- Instance.new(@klass.substitute(subst, depth))
607
- end
608
- end
609
-
610
- # This is an internal object in MRI, so a user program cannot create this object explicitly
611
- class ISeq < Type
612
- def initialize(iseq)
613
- @iseq = iseq
614
- end
615
-
616
- attr_reader :iseq
617
-
618
- def inspect
619
- "Type::ISeq[#{ @iseq }]"
620
- end
621
-
622
- def screen_name(_scratch)
623
- raise NotImplementedError
624
- end
625
- end
626
-
627
- class Proc < Type
628
- def initialize(block_body, base_type)
629
- @block_body, @base_type = block_body, base_type
630
- end
631
-
632
- attr_reader :block_body, :base_type
633
-
634
- def consistent?(other)
635
- case other
636
- when Type::Proc
637
- @block_body.consistent?(other.block_body)
638
- else
639
- self == other
640
- end
641
- end
642
-
643
- def method_dispatch_info
644
- @base_type.method_dispatch_info
645
- end
646
-
647
- def substitute(subst, depth)
648
- Proc.new(@block_body.substitute(subst, depth), @base_type)
649
- end
650
-
651
- def screen_name(scratch)
652
- scratch.show_proc_signature([self])
653
- end
654
-
655
- def include_untyped?(scratch)
656
- false # XXX: need to check the block signatures recursively
657
- end
658
- end
659
-
660
- class Symbol < Type
661
- def initialize(sym, base_type)
662
- @sym = sym
663
- @base_type = base_type
664
- end
665
-
666
- attr_reader :sym, :base_type
667
-
668
- def inspect
669
- "Type::Symbol[#{ @sym ? @sym.inspect : "(dynamic symbol)" }, #{ @base_type.inspect }]"
670
- end
671
-
672
- def consistent?(other)
673
- case other
674
- when Symbol
675
- @sym == other.sym
676
- else
677
- @base_type.consistent?(other)
678
- end
679
- end
680
-
681
- def screen_name(scratch)
682
- if @sym
683
- @sym.inspect
684
- else
685
- @base_type.screen_name(scratch)
686
- end
687
- end
688
-
689
- def method_dispatch_info
690
- @base_type.method_dispatch_info
691
- end
692
-
693
- def substitute(_subst, _depth)
694
- self # dummy
695
- end
696
- end
697
-
698
- # A local type
699
- class Literal < Type
700
- def initialize(lit, base_type)
701
- @lit = lit
702
- @base_type = base_type
703
- end
704
-
705
- attr_reader :lit, :base_type
706
-
707
- def inspect
708
- "Type::Literal[#{ @lit.inspect }, #{ @base_type.inspect }]"
709
- end
710
-
711
- def screen_name(scratch)
712
- @base_type.screen_name(scratch) + "<#{ @lit.inspect }>"
713
- end
714
-
715
- def globalize(_env, _visited, _depth)
716
- @base_type
717
- end
718
-
719
- def method_dispatch_info
720
- @base_type.method_dispatch_info
721
- end
722
-
723
- def consistent?(_other)
724
- raise "should not called"
725
- end
726
- end
727
-
728
- class HashGenerator
729
- def initialize
730
- @map_tys = {}
731
- end
732
-
733
- attr_reader :map_tys
734
-
735
- def []=(k_ty, v_ty)
736
- k_ty.each_child_global do |k_ty|
737
- if k_ty.is_a?(Type::Union)
738
- # Flatten recursive union
739
- self[k_ty] = v_ty
740
- else
741
- # This is a temporal hack to mitigate type explosion
742
- k_ty = Type.any if k_ty.is_a?(Type::Array)
743
- k_ty = Type.any if k_ty.is_a?(Type::Hash)
744
-
745
- if @map_tys[k_ty]
746
- @map_tys[k_ty] = @map_tys[k_ty].union(v_ty)
747
- else
748
- @map_tys[k_ty] = v_ty
749
- end
750
- end
751
- end
752
- end
753
- end
754
-
755
- def self.gen_hash(base_ty = Type::Instance.new(Type::Builtin[:hash]))
756
- hg = HashGenerator.new
757
- yield hg
758
- Type::Hash.new(Type::Hash::Elements.new(hg.map_tys), base_ty)
759
- end
760
-
761
- def self.guess_literal_type(obj)
762
- case obj
763
- when ::Symbol
764
- Type::Symbol.new(obj, Type::Instance.new(Type::Builtin[:sym]))
765
- when ::Integer
766
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:int]))
767
- when ::Rational
768
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:rational]))
769
- when ::Complex
770
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:complex]))
771
- when ::Float
772
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:float]))
773
- when ::Class
774
- return Type.any if obj < Exception
775
- case obj
776
- when ::Object
777
- Type::Builtin[:obj]
778
- when ::Array
779
- Type::Builtin[:ary]
780
- else
781
- raise "unknown class: #{ obj.inspect }"
782
- end
783
- when ::TrueClass
784
- Type::Instance.new(Type::Builtin[:true])
785
- when ::FalseClass
786
- Type::Instance.new(Type::Builtin[:false])
787
- when ::Array
788
- base_ty = Type::Instance.new(Type::Builtin[:ary])
789
- lead_tys = obj.map {|arg| guess_literal_type(arg) }
790
- Type::Array.new(Type::Array::Elements.new(lead_tys), base_ty)
791
- when ::Hash
792
- Type.gen_hash do |h|
793
- obj.each do |k, v|
794
- k_ty = guess_literal_type(k).globalize(nil, {}, Config.current.options[:type_depth_limit])
795
- v_ty = guess_literal_type(v)
796
- h[k_ty] = v_ty
797
- end
798
- end
799
- when ::String
800
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:str]))
801
- when ::Regexp
802
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:regexp]))
803
- when ::NilClass
804
- Type.nil
805
- when ::Range
806
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:range]))
807
- when ::Encoding
808
- Type::Literal.new(obj, Type::Instance.new(Type::Builtin[:encoding]))
809
- else
810
- raise "unknown object: #{ obj.inspect }"
811
- end
812
- end
813
-
814
- def self.builtin_global_variable_type(var)
815
- case var
816
- when :$_, :$/, :$\, :$,, :$;
817
- Type.optional(Type::Instance.new(Type::Builtin[:str]))
818
- when :$0, :$PROGRAM_NAME
819
- Type::Instance.new(Type::Builtin[:str])
820
- when :$~
821
- # optional type is tentatively disabled; it is too conservative
822
- #Type.optional(Type::Instance.new(Type::Builtin[:matchdata]))
823
- Type::Instance.new(Type::Builtin[:matchdata])
824
- when :$., :$$
825
- Type::Instance.new(Type::Builtin[:int])
826
- when :$?
827
- Type.optional(Type::Instance.new(Type::Builtin[:int]))
828
- when :$!
829
- Type.optional(Type::Instance.new(Type::Builtin[:exc]))
830
- when :$@
831
- str = Type::Instance.new(Type::Builtin[:str])
832
- base_ty = Type::Instance.new(Type::Builtin[:ary])
833
- Type.optional(Type::Array.new(Type::Array::Elements.new([], str), base_ty))
834
- when :$*, :$:, :$LOAD_PATH, :$", :$LOADED_FEATURES
835
- str = Type::Instance.new(Type::Builtin[:str])
836
- base_ty = Type::Instance.new(Type::Builtin[:ary])
837
- Type::Array.new(Type::Array::Elements.new([], str), base_ty)
838
- when :$<
839
- :ARGF
840
- when :$>
841
- :STDOUT
842
- when :$DEBUG
843
- Type.bool
844
- when :$FILENAME
845
- Type::Instance.new(Type::Builtin[:str])
846
- when :$stdin
847
- :STDIN
848
- when :$stdout
849
- :STDOUT
850
- when :$stderr
851
- :STDERR
852
- when :$VERBOSE
853
- Type.bool.union(Type.nil)
854
- else
855
- nil
856
- end
857
- end
858
- end
859
-
860
- class Signature
861
- include Utils::StructuralEquality
862
-
863
- def screen_name(iseq, scratch)
864
- fargs_str = "("
865
- sig_help = {}
866
- add_farg = -> farg, name, help: false, key: sig_help.size do
867
- name = "`#{ name }`" if RBS::Parser::KEYWORDS.key?(name.to_s)
868
- name = "noname" if name.is_a?(Integer) || name == :"*"
869
- fargs_str << ", " if fargs_str != "("
870
- i = fargs_str.size
871
- fargs_str << (Config.current.options[:show_parameter_names] && name ? "#{ farg } #{ name }" : farg)
872
- sig_help[key] = (i...fargs_str.size)
873
- end
874
-
875
- @lead_tys.zip(iseq ? iseq.locals : []) do |ty, name|
876
- add_farg.call(ty.screen_name(scratch), name, help: true)
877
- end
878
-
879
- @opt_tys&.zip(iseq ? iseq.locals[@lead_tys.size, @opt_tys.size] : []) do |ty, name|
880
- add_farg.call("?" + ty.screen_name(scratch), name, help: true)
881
- end
882
-
883
- if @rest_ty
884
- if iseq
885
- rest_index = iseq.fargs_format[:rest_start]
886
- name = rest_index ? iseq.locals[rest_index] : nil
887
- end
888
- add_farg.call("*" + @rest_ty.screen_name(scratch), name)
889
- end
890
-
891
- if iseq
892
- post_start = iseq.fargs_format[:post_start]
893
- names = post_start ? iseq.locals[post_start, @post_tys.size] : []
894
- end
895
- @post_tys&.zip(names || []) do |ty, name|
896
- add_farg.call(ty.screen_name(scratch), name)
897
- end
898
-
899
- @kw_tys&.each do |req, sym, ty|
900
- opt = req ? "" : "?"
901
- add_farg.call("#{ opt }#{ sym }: #{ ty.screen_name(scratch) }", nil, help: true, key: sym)
902
- end
903
-
904
- if @kw_rest_ty
905
- all_val_ty = Type.bot
906
- @kw_rest_ty.each_child_global do |ty|
907
- if ty == Type.any
908
- val_ty = ty
909
- else
910
- # ty is a Type::Hash
911
- _key_ty, val_ty = ty.elems.squash
912
- end
913
- all_val_ty = all_val_ty.union(val_ty)
914
- end
915
- add_farg.call("**" + all_val_ty.screen_name(scratch), nil)
916
- end
917
-
918
- fargs_str << ")"
919
-
920
- fargs_str = "" if fargs_str == "()"
921
-
922
- # Dirty Hack: Stop the iteration at most once!
923
- # I'll remove this hack if RBS removes the limitation of nesting blocks
924
- return fargs_str, sig_help if caller_locations.any? {|frame| frame.label =~ /\bshow_block_signature\z/ }
925
-
926
- optional = false
927
- blks = []
928
- @blk_ty.each_child_global do |ty|
929
- if ty.is_a?(Type::Proc)
930
- blks << ty
931
- else
932
- # XXX: how should we handle types other than Type.nil
933
- optional = true
934
- end
935
- end
936
- if blks != []
937
- fargs_str << " " if fargs_str != ""
938
- fargs_str << "?" if optional
939
- fargs_str << scratch.show_block_signature(blks)
940
- end
941
-
942
- return fargs_str, sig_help
943
- end
944
- end
945
-
946
- class MethodSignature < Signature
947
- def initialize(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty)
948
- @lead_tys = lead_tys
949
- @opt_tys = opt_tys
950
- raise unless opt_tys.is_a?(Array)
951
- @rest_ty = rest_ty
952
- @post_tys = post_tys
953
- raise unless post_tys
954
- @kw_tys = kw_tys
955
- kw_tys.each {|a| raise if a.size != 3 } if kw_tys
956
- @kw_rest_ty = kw_rest_ty
957
- kw_rest_ty&.each_child_global do |ty|
958
- raise ty.inspect if ty != Type.any && !ty.is_a?(Type::Hash)
959
- end
960
- @blk_ty = blk_ty
961
- end
962
-
963
- def include_untyped?(scratch)
964
- return true if @lead_tys.any? {|ty| ty.include_untyped?(scratch) }
965
- return true if @opt_tys.any? {|ty| ty.include_untyped?(scratch) }
966
- return true if @rest_ty&.include_untyped?(scratch)
967
- return true if @post_tys.any? {|ty| ty.include_untyped?(scratch) }
968
- return true if @kw_tys&.any? {|_, _, ty| ty.include_untyped?(scratch) }
969
- return true if @kw_rest_ty&.include_untyped?(scratch)
970
- return true if @blk_ty&.include_untyped?(scratch)
971
- false
972
- end
973
-
974
- attr_reader :lead_tys, :opt_tys, :rest_ty, :post_tys, :kw_tys, :kw_rest_ty, :blk_ty
975
-
976
- def substitute(subst, depth)
977
- lead_tys = @lead_tys.map {|ty| ty.substitute(subst, depth - 1) }
978
- opt_tys = @opt_tys.map {|ty| ty.substitute(subst, depth - 1) }
979
- rest_ty = @rest_ty&.substitute(subst, depth - 1)
980
- post_tys = @post_tys.map {|ty| ty.substitute(subst, depth - 1) }
981
- kw_tys = @kw_tys.map {|req, key, ty| [req, key, ty.substitute(subst, depth - 1)] }
982
- kw_rest_ty = @kw_rest_ty&.substitute(subst, depth - 1)
983
- blk_ty = @blk_ty.substitute(subst, depth - 1)
984
- MethodSignature.new(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty)
985
- end
986
-
987
- def merge_as_block_arguments(other)
988
- lead_tys1, opt_tys1, rest_ty1, post_tys1 = @lead_tys, @opt_tys, @rest_ty, @post_tys
989
- lead_tys2, opt_tys2, rest_ty2, post_tys2 = other.lead_tys, other.opt_tys, other.rest_ty, other.post_tys
990
-
991
- case
992
- when lead_tys1.size > lead_tys2.size
993
- n = lead_tys2.size
994
- lead_tys1, opt_tys1 = lead_tys1[0, n], lead_tys1[n..] + opt_tys1
995
- when lead_tys1.size < lead_tys2.size
996
- n = lead_tys1.size
997
- lead_tys2, opt_tys2 = lead_tys2[0, n], lead_tys2[n..] + opt_tys2
998
- end
999
- case
1000
- when post_tys1.size > post_tys2.size
1001
- i = post_tys1.size - post_tys2.size
1002
- if rest_ty1
1003
- rest_ty1 = post_tys[0, i].inject(rest_ty1) {|ty1, ty2| ty1.union(ty2) }
1004
- post_tys1 = post_tys1[i..]
1005
- else
1006
- opt_tys1, post_tys1 = opt_tys1 + post_tys1[0, i], post_tys1[i..]
1007
- end
1008
- when post_tys1.size < post_tys2.size
1009
- i = post_tys2.size - post_tys1.size
1010
- if rest_ty2
1011
- rest_ty2 = post_tys[0, i].inject(rest_ty2) {|ty1, ty2| ty1.union(ty2) }
1012
- post_tys2 = post_tys2[i..]
1013
- else
1014
- opt_tys2, post_tys2 = opt_tys2 + post_tys2[0, i], post_tys2[i..]
1015
- end
1016
- end
1017
-
1018
- # XXX: tweak keywords too
1019
-
1020
- msig1 = MethodSignature.new(lead_tys1, opt_tys1, rest_ty1, post_tys1, @kw_tys, @kw_rest_ty, @blk_ty)
1021
- msig2 = MethodSignature.new(lead_tys2, opt_tys2, rest_ty2, post_tys2, other.kw_tys, other.kw_rest_ty, other.blk_ty)
1022
- msig1.merge(msig2)
1023
- end
1024
-
1025
- def merge(other)
1026
- raise if @lead_tys.size != other.lead_tys.size
1027
- raise if @post_tys.size != other.post_tys.size
1028
- if @kw_tys && other.kw_tys
1029
- kws1 = {}
1030
- @kw_tys.each {|req, kw, _| kws1[kw] = req }
1031
- kws2 = {}
1032
- other.kw_tys.each {|req, kw, _| kws2[kw] = req }
1033
- (kws1.keys & kws2.keys).each do |kw|
1034
- raise if !!kws1[kw] != !!kws2[kw]
1035
- end
1036
- elsif @kw_tys || other.kw_tys
1037
- (@kw_tys || other.kw_tys).each do |req,|
1038
- raise if req
1039
- end
1040
- end
1041
- lead_tys = @lead_tys.zip(other.lead_tys).map {|ty1, ty2| ty1.union(ty2) }
1042
- if @opt_tys || other.opt_tys
1043
- opt_tys = []
1044
- [@opt_tys.size, other.opt_tys.size].max.times do |i|
1045
- ty1 = @opt_tys[i]
1046
- ty2 = other.opt_tys[i]
1047
- ty = ty1 ? ty2 ? ty1.union(ty2) : ty1 : ty2
1048
- opt_tys << ty
1049
- end
1050
- end
1051
- if @rest_ty || other.rest_ty
1052
- if @rest_ty && other.rest_ty
1053
- rest_ty = @rest_ty.union(other.rest_ty)
1054
- else
1055
- rest_ty = @rest_ty || other.rest_ty
1056
- end
1057
- end
1058
- post_tys = @post_tys.zip(other.post_tys).map {|ty1, ty2| ty1.union(ty2) }
1059
- if @kw_tys && other.kw_tys
1060
- kws1 = {}
1061
- @kw_tys.each {|req, kw, ty| kws1[kw] = [req, ty] }
1062
- kws2 = {}
1063
- other.kw_tys.each {|req, kw, ty| kws2[kw] = [req, ty] }
1064
- kw_tys = (kws1.keys | kws2.keys).map do |kw|
1065
- req1, ty1 = kws1[kw]
1066
- _req2, ty2 = kws2[kw]
1067
- ty1 ||= Type.bot
1068
- ty2 ||= Type.bot
1069
- [!!req1, kw, ty1.union(ty2)]
1070
- end
1071
- elsif @kw_tys || other.kw_tys
1072
- kw_tys = @kw_tys || other.kw_tys
1073
- else
1074
- kw_tys = nil
1075
- end
1076
- if @kw_rest_ty || other.kw_rest_ty
1077
- if @kw_rest_ty && other.kw_rest_ty
1078
- kw_rest_ty = @kw_rest_ty.union(other.kw_rest_ty)
1079
- else
1080
- kw_rest_ty = @kw_rest_ty || other.kw_rest_ty
1081
- end
1082
- end
1083
- blk_ty = @blk_ty.union(other.blk_ty) if @blk_ty
1084
- MethodSignature.new(lead_tys, opt_tys, rest_ty, post_tys, kw_tys, kw_rest_ty, blk_ty)
1085
- end
1086
- end
1087
-
1088
- class BlockSignature < Signature
1089
- def initialize(lead_tys, opt_tys, rest_ty, blk_ty)
1090
- @lead_tys = lead_tys
1091
- @opt_tys = opt_tys
1092
- @rest_ty = rest_ty
1093
- @blk_ty = blk_ty
1094
- # TODO: kw_tys
1095
- end
1096
-
1097
- attr_reader :lead_tys, :opt_tys, :rest_ty, :blk_ty
1098
-
1099
- def merge(bsig)
1100
- if @rest_ty && bsig.rest_ty
1101
- rest_ty = @rest_ty.union(bsig.rest_ty)
1102
- BlockSignature.new(@lead_tys, [], rest_ty, @blk_ty.union(bsig.blk_ty))
1103
- elsif @rest_ty || bsig.rest_ty
1104
- rest_ty = @rest_ty || bsig.rest_ty
1105
- rest_ty = @opt_tys.inject(rest_ty, &:union)
1106
- rest_ty = bsig.opt_tys.inject(rest_ty, &:union)
1107
-
1108
- lead_tys = []
1109
- [@lead_tys.size, bsig.lead_tys.size].max.times do |i|
1110
- ty1 = @lead_tys[i]
1111
- ty2 = bsig.lead_tys[i]
1112
- if ty1 && ty2
1113
- lead_tys << ty1.union(ty2)
1114
- else
1115
- rest_ty = rest_ty.union(ty1 || ty2)
1116
- end
1117
- end
1118
-
1119
- BlockSignature.new(lead_tys, [], rest_ty, @blk_ty.union(bsig.blk_ty))
1120
- else
1121
- lead_tys = []
1122
- n = [@lead_tys.size, bsig.lead_tys.size].min
1123
- n.times do |i|
1124
- lead_tys << @lead_tys[i].union(bsig.lead_tys[i])
1125
- end
1126
- opt_tys1 = @lead_tys[n..] + @opt_tys
1127
- opt_tys2 = bsig.lead_tys[n..] + bsig.opt_tys
1128
- opt_tys = []
1129
- [opt_tys1.size, opt_tys2.size].max.times do |i|
1130
- if opt_tys1[i] && opt_tys2[i]
1131
- opt_tys << opt_tys1[i].union(opt_tys2[i])
1132
- else
1133
- opt_tys << (opt_tys1[i] || opt_tys2[i])
1134
- end
1135
- end
1136
- BlockSignature.new(lead_tys, opt_tys, nil, @blk_ty.union(bsig.blk_ty))
1137
- end
1138
- end
1139
- end
1140
- end