typeprof 0.31.1 → 0.33.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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +2 -1
  3. data/doc/report_guide.md +88 -0
  4. data/lib/typeprof/cli/cli.rb +9 -3
  5. data/lib/typeprof/code_range.rb +7 -5
  6. data/lib/typeprof/core/ast/base.rb +31 -6
  7. data/lib/typeprof/core/ast/call.rb +120 -39
  8. data/lib/typeprof/core/ast/const.rb +22 -11
  9. data/lib/typeprof/core/ast/control.rb +62 -32
  10. data/lib/typeprof/core/ast/meta.rb +279 -14
  11. data/lib/typeprof/core/ast/method.rb +82 -24
  12. data/lib/typeprof/core/ast/misc.rb +41 -12
  13. data/lib/typeprof/core/ast/module.rb +38 -4
  14. data/lib/typeprof/core/ast/pattern.rb +51 -23
  15. data/lib/typeprof/core/ast/sig_decl.rb +141 -27
  16. data/lib/typeprof/core/ast/sig_type.rb +113 -32
  17. data/lib/typeprof/core/ast/value.rb +14 -6
  18. data/lib/typeprof/core/ast/variable.rb +17 -4
  19. data/lib/typeprof/core/ast.rb +98 -14
  20. data/lib/typeprof/core/builtin.rb +184 -12
  21. data/lib/typeprof/core/env/method.rb +343 -6
  22. data/lib/typeprof/core/env/method_entity.rb +18 -15
  23. data/lib/typeprof/core/env/module_entity.rb +116 -18
  24. data/lib/typeprof/core/env/static_read.rb +4 -4
  25. data/lib/typeprof/core/env/type_alias_entity.rb +1 -1
  26. data/lib/typeprof/core/env/value_entity.rb +25 -3
  27. data/lib/typeprof/core/env.rb +113 -23
  28. data/lib/typeprof/core/graph/box.rb +508 -63
  29. data/lib/typeprof/core/graph/change_set.rb +64 -46
  30. data/lib/typeprof/core/graph/filter.rb +8 -5
  31. data/lib/typeprof/core/graph/vertex.rb +20 -19
  32. data/lib/typeprof/core/service.rb +340 -24
  33. data/lib/typeprof/core/type.rb +41 -7
  34. data/lib/typeprof/core/util.rb +6 -0
  35. data/lib/typeprof/lsp/messages.rb +5 -0
  36. data/lib/typeprof/lsp/server.rb +35 -4
  37. data/lib/typeprof/version.rb +1 -1
  38. metadata +3 -2
@@ -15,20 +15,27 @@ module TypeProf::Core
15
15
  # TODO: decl.type_params
16
16
  # TODO: decl.super_class.args
17
17
  ncref = CRef.new(@cpath, :class, nil, lenv.cref)
18
- nlenv = LocalEnv.new(@lenv.path, ncref, {}, [])
18
+ nlenv = LocalEnv.new(@lenv.file_context, ncref, {}, [])
19
19
  @members = raw_decl.members.map do |member|
20
20
  AST.create_rbs_member(member, nlenv)
21
21
  end.compact
22
22
  # TODO?: param.variance, param.unchecked, param.upper_bound
23
23
  @params = raw_decl.type_params.map {|param| param.name }
24
+ @params_default_types = raw_decl.type_params.map do |param|
25
+ ty = param.default_type
26
+ ty ? AST.create_rbs_type(ty, lenv) : nil
27
+ end
24
28
  end
25
29
 
26
- attr_reader :cpath, :members, :params
30
+ attr_reader :cpath, :members, :params, :params_default_types
27
31
 
28
- def subnodes = { members: }
32
+ def subnodes = { members:, params_default_types: }
29
33
  def attrs = { cpath:, params: }
30
34
 
31
35
  def define0(genv)
36
+ @params_default_types.each do |ty|
37
+ ty&.define(genv)
38
+ end
32
39
  @members.each do |member|
33
40
  member.define(genv)
34
41
  end
@@ -46,6 +53,9 @@ module TypeProf::Core
46
53
  def undefine0(genv)
47
54
  mod = genv.resolve_cpath(@cpath)
48
55
  mod.remove_module_decl(genv, self)
56
+ @params_default_types.each do |ty|
57
+ ty&.undefine(genv)
58
+ end
49
59
  @members.each do |member|
50
60
  member.undefine(genv)
51
61
  end
@@ -180,22 +190,26 @@ module TypeProf::Core
180
190
  def initialize(raw_decl, lenv)
181
191
  super(raw_decl, lenv)
182
192
  @mid = raw_decl.name
183
- @mid_code_range = TypeProf::CodeRange.from_node(raw_decl.location[:name])
193
+ @mid_code_range_loc = raw_decl.location[:name]
184
194
  @singleton = raw_decl.singleton?
185
195
  @instance = raw_decl.instance?
186
- @method_types = raw_decl.overloads.map do |overload|
196
+ @method_types = OverloadSet.new(raw_decl.overloads.map do |overload|
187
197
  method_type = overload.method_type
188
198
  AST.create_rbs_func_type(method_type, method_type.type_params, method_type.block, lenv)
189
- end
199
+ end)
190
200
  @overloading = raw_decl.overloading
191
201
  end
192
202
 
193
- attr_reader :mid, :singleton, :instance, :method_types, :overloading, :mid_code_range
203
+ attr_reader :mid, :singleton, :instance, :method_types, :overloading
204
+
205
+ def mid_code_range
206
+ @mid_code_range ||= @lenv.code_range_from_node(@mid_code_range_loc) if @mid_code_range_loc
207
+ end
194
208
 
195
- def subnodes = { method_types: }
196
- def attrs = { mid:, mid_code_range:, singleton:, instance:, overloading: }
209
+ def subnodes = { method_types: @method_types.to_a }
210
+ def attrs = { mid:, singleton:, instance:, overloading: }
197
211
 
198
- def mname_code_range(_name) = @mid_code_range
212
+ def mname_code_range(_name) = mid_code_range
199
213
 
200
214
  def install0(genv)
201
215
  [[@singleton, true], [@instance, false]].each do |enabled, singleton|
@@ -222,10 +236,10 @@ module TypeProf::Core
222
236
  def define0(genv)
223
237
  @args.each {|arg| arg.define(genv) }
224
238
  const_reads = []
225
- const_read = BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref, false)
239
+ const_read = BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref, true)
226
240
  const_reads << const_read
227
241
  @cpath[1..].each do |cname|
228
- const_read = ScopedConstRead.new(cname, const_read, false)
242
+ const_read = ScopedConstRead.new(cname, const_read, true)
229
243
  const_reads << const_read
230
244
  end
231
245
  mod = genv.resolve_cpath(@lenv.cref.cpath)
@@ -271,10 +285,10 @@ module TypeProf::Core
271
285
  def define0(genv)
272
286
  @args.each {|arg| arg.define(genv) }
273
287
  const_reads = []
274
- const_read = BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref, false)
288
+ const_read = BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref, true)
275
289
  const_reads << const_read
276
290
  @cpath[1..].each do |cname|
277
- const_read = ScopedConstRead.new(cname, const_read, false)
291
+ const_read = ScopedConstRead.new(cname, const_read, true)
278
292
  const_reads << const_read
279
293
  end
280
294
  mod = genv.resolve_cpath(@lenv.cref.cpath)
@@ -304,6 +318,55 @@ module TypeProf::Core
304
318
  end
305
319
  end
306
320
 
321
+ class SigExtendNode < Node
322
+ def initialize(raw_decl, lenv)
323
+ super(raw_decl, lenv)
324
+ name = raw_decl.name
325
+ @cpath = name.namespace.path + [name.name]
326
+ @toplevel = name.namespace.absolute?
327
+ @args = raw_decl.args.map {|arg| AST.create_rbs_type(arg, lenv) }
328
+ end
329
+
330
+ attr_reader :cpath, :toplevel, :args
331
+ def subnodes = { args: }
332
+ def attrs = { cpath:, toplevel: }
333
+
334
+ def define0(genv)
335
+ @args.each {|arg| arg.define(genv) }
336
+ const_reads = []
337
+ const_read = BaseConstRead.new(genv, @cpath.first, @toplevel ? CRef::Toplevel : @lenv.cref, true)
338
+ const_reads << const_read
339
+ @cpath[1..].each do |cname|
340
+ const_read = ScopedConstRead.new(cname, const_read, true)
341
+ const_reads << const_read
342
+ end
343
+ mod = genv.resolve_cpath(@lenv.cref.cpath)
344
+ const_read.followers << mod
345
+ mod.add_extend_decl(genv, self)
346
+ const_reads
347
+ end
348
+
349
+ def define_copy(genv)
350
+ mod = genv.resolve_cpath(@lenv.cref.cpath)
351
+ mod.add_extend_decl(genv, self)
352
+ mod.remove_extend_decl(genv, @prev_node)
353
+ super(genv)
354
+ end
355
+
356
+ def undefine0(genv)
357
+ mod = genv.resolve_cpath(@lenv.cref.cpath)
358
+ mod.remove_extend_decl(genv, self)
359
+ @static_ret.each do |const_read|
360
+ const_read.destroy(genv)
361
+ end
362
+ @args.each {|arg| arg.undefine(genv) }
363
+ end
364
+
365
+ def install0(genv)
366
+ Source.new
367
+ end
368
+ end
369
+
307
370
  class SigAliasNode < Node
308
371
  def initialize(raw_decl, lenv)
309
372
  super(raw_decl, lenv)
@@ -336,6 +399,7 @@ module TypeProf::Core
336
399
  location: raw_decl.type.location
337
400
  )
338
401
  @method_type = AST.create_rbs_func_type(rbs_method_type, [], nil, lenv)
402
+ @method_types = OverloadSet.new([@method_type])
339
403
  end
340
404
 
341
405
  attr_reader :mid, :method_type
@@ -344,7 +408,7 @@ module TypeProf::Core
344
408
  def attrs = { mid: }
345
409
 
346
410
  def install0(genv)
347
- @changes.add_method_decl_box(genv, @lenv.cref.cpath, false, @mid, [@method_type], false)
411
+ @changes.add_method_decl_box(genv, @lenv.cref.cpath, false, @mid, @method_types, false)
348
412
  Source.new
349
413
  end
350
414
  end
@@ -371,6 +435,7 @@ module TypeProf::Core
371
435
  location: raw_decl.type.location
372
436
  )
373
437
  @method_type = AST.create_rbs_func_type(rbs_method_type, [], nil, lenv)
438
+ @method_types = OverloadSet.new([@method_type])
374
439
  end
375
440
 
376
441
  attr_reader :mid, :method_type
@@ -379,7 +444,7 @@ module TypeProf::Core
379
444
  def attrs = { mid: }
380
445
 
381
446
  def install0(genv)
382
- @changes.add_method_decl_box(genv, @lenv.cref.cpath, false, @mid, [@method_type], false)
447
+ @changes.add_method_decl_box(genv, @lenv.cref.cpath, false, @mid, @method_types, false)
383
448
  Source.new
384
449
  end
385
450
  end
@@ -402,6 +467,52 @@ module TypeProf::Core
402
467
  end
403
468
  end
404
469
 
470
+ class SigModuleAliasBaseNode < Node
471
+ def initialize(raw_decl, lenv)
472
+ super(raw_decl, lenv)
473
+ @cpath = AST.resolve_rbs_name(raw_decl.new_name, lenv)
474
+ @old_cpath = AST.resolve_rbs_name(raw_decl.old_name, lenv)
475
+ end
476
+
477
+ attr_reader :cpath, :old_cpath
478
+ def attrs = { cpath:, old_cpath: }
479
+
480
+ def define0(genv)
481
+ outer = genv.resolve_cpath(@cpath[0..-2])
482
+ cname = @cpath.last
483
+ alias_mod = outer.inner_modules[cname] ||= ModuleEntity.new(outer.cpath + [cname], outer)
484
+ target_mod = genv.resolve_cpath(@old_cpath)
485
+ alias_mod.add_alias_decl(genv, self, target_mod)
486
+ end
487
+
488
+ def define_copy(genv)
489
+ outer = genv.resolve_cpath(@cpath[0..-2])
490
+ alias_mod = outer.inner_modules[@cpath.last]
491
+ target_mod = genv.resolve_cpath(@old_cpath)
492
+ alias_mod.add_alias_decl(genv, self, target_mod)
493
+ alias_mod.remove_alias_decl(genv, @prev_node)
494
+ super(genv)
495
+ end
496
+
497
+ def undefine0(genv)
498
+ outer = genv.resolve_cpath(@cpath[0..-2])
499
+ alias_mod = outer.inner_modules[@cpath.last]
500
+ alias_mod.remove_alias_decl(genv, self)
501
+ end
502
+
503
+ def install0(genv)
504
+ mod_val = Source.new(Type::Singleton.new(genv, genv.resolve_cpath(@cpath)))
505
+ @changes.add_edge(genv, mod_val, @static_ret.vtx)
506
+ Source.new
507
+ end
508
+ end
509
+
510
+ class SigClassAliasNode < SigModuleAliasBaseNode
511
+ end
512
+
513
+ class SigModuleAliasNode < SigModuleAliasBaseNode
514
+ end
515
+
405
516
  class SigConstNode < Node
406
517
  def initialize(raw_decl, lenv)
407
518
  super(raw_decl, lenv)
@@ -415,9 +526,10 @@ module TypeProf::Core
415
526
 
416
527
  def define0(genv)
417
528
  @type.define(genv)
418
- mod = genv.resolve_const(@cpath)
419
- mod.add_decl(self)
420
- mod
529
+ cdef = genv.resolve_const(@cpath)
530
+ cdef.on_const_added(genv, @cpath)
531
+ cdef.add_decl(self)
532
+ cdef
421
533
  end
422
534
 
423
535
  def define_copy(genv)
@@ -428,7 +540,9 @@ module TypeProf::Core
428
540
  end
429
541
 
430
542
  def undefine0(genv)
431
- genv.resolve_const(@cpath).remove_decl(self)
543
+ cdef = genv.resolve_const(@cpath)
544
+ cdef.remove_decl(self)
545
+ cdef.on_const_removed(genv, @cpath)
432
546
  @type.undefine(genv)
433
547
  end
434
548
 
@@ -490,20 +604,20 @@ module TypeProf::Core
490
604
 
491
605
  def define0(genv)
492
606
  @type.define(genv)
493
- mod = genv.resolve_ivar(cpath, @class_scope, @var)
494
- mod.add_decl(self)
495
- mod
607
+ mod = genv.resolve_cpath(cpath)
608
+ mod.add_ivar_decl(genv, @class_scope, @var, self)
496
609
  end
497
610
 
498
611
  def define_copy(genv)
499
- mod = genv.resolve_ivar(cpath, @class_scope, @var)
500
- mod.add_decl(self)
501
- mod.remove_decl(@prev_node)
612
+ mod = genv.resolve_cpath(cpath)
613
+ mod.add_ivar_decl(genv, @class_scope, @var, self)
614
+ mod.remove_ivar_decl(genv, @class_scope, @var, @prev_node)
502
615
  super(genv)
503
616
  end
504
617
 
505
618
  def undefine0(genv)
506
- genv.resolve_ivar(cpath, @class_scope, @var).remove_decl(self)
619
+ mod = genv.resolve_cpath(cpath)
620
+ mod.remove_ivar_decl(genv, @class_scope, @var, self)
507
621
  @type.undefine(genv)
508
622
  end
509
623
 
@@ -2,7 +2,10 @@ module TypeProf::Core
2
2
  class AST
3
3
  def self.typecheck_for_module(genv, changes, f_mod, f_args, a_vtx, subst)
4
4
  changes.add_edge(genv, a_vtx, changes.target)
5
+ found_any = false
5
6
  a_vtx.each_type do |ty|
7
+ next if ty.is_a?(Type::Bot)
8
+ found_any = true
6
9
  ty = ty.base_type(genv)
7
10
  while ty
8
11
  if ty.mod == f_mod && ty.is_a?(Type::Instance)
@@ -20,12 +23,15 @@ module TypeProf::Core
20
23
  if f_mod.module?
21
24
  return true if typecheck_for_prepended_modules(genv, changes, ty, f_mod, f_args, subst)
22
25
  return true if typecheck_for_included_modules(genv, changes, ty, f_mod, f_args, subst)
26
+ if ty.is_a?(Type::Singleton)
27
+ return true if typecheck_for_extended_modules(genv, changes, ty, f_mod, f_args, subst)
28
+ end
23
29
  end
24
30
 
25
31
  ty = genv.get_superclass_type(ty, changes, {})
26
32
  end
27
33
  end
28
- return false
34
+ return !found_any
29
35
  end
30
36
 
31
37
  def self.typecheck_for_prepended_modules(genv, changes, a_ty, f_mod, f_args, subst)
@@ -33,7 +39,7 @@ module TypeProf::Core
33
39
  if prep_decl.is_a?(AST::SigPrependNode) && prep_mod.type_params
34
40
  prep_ty = genv.get_instance_type(prep_mod, prep_decl.args, changes, {}, a_ty)
35
41
  else
36
- type_params = prep_mod.type_params.map {|ty_param| Source.new() } # TODO: better support
42
+ type_params = prep_mod.type_params.map {|(_name, _default_ty)| Source.new() } # TODO: better support
37
43
  prep_ty = Type::Instance.new(genv, prep_mod, type_params)
38
44
  end
39
45
  if prep_ty.mod == f_mod
@@ -58,7 +64,7 @@ module TypeProf::Core
58
64
  if inc_decl.is_a?(AST::SigIncludeNode) && inc_mod.type_params
59
65
  inc_ty = genv.get_instance_type(inc_mod, inc_decl.args, changes, {}, a_ty)
60
66
  else
61
- type_params = inc_mod.type_params.map {|ty_param| Source.new() } # TODO: better support
67
+ type_params = inc_mod.type_params.map {|(_name, _default_ty)| Source.new() } # TODO: better support
62
68
  inc_ty = Type::Instance.new(genv, inc_mod, type_params)
63
69
  end
64
70
  if inc_ty.mod == f_mod
@@ -78,6 +84,32 @@ module TypeProf::Core
78
84
  return false
79
85
  end
80
86
 
87
+ def self.typecheck_for_extended_modules(genv, changes, a_ty, f_mod, f_args, subst)
88
+ a_ty.mod.extended_modules.each do |ext_decl, ext_mod|
89
+ if ext_decl.is_a?(AST::SigExtendNode) && ext_mod.type_params
90
+ ext_ty = genv.get_instance_type(ext_mod, ext_decl.args, changes, {}, a_ty)
91
+ else
92
+ type_params = ext_mod.type_params.map {|(_name, _default_ty)| Source.new() } # TODO: better support
93
+ ext_ty = Type::Instance.new(genv, ext_mod, type_params)
94
+ end
95
+ if ext_ty.mod == f_mod
96
+ args_all_match = true
97
+ f_args.zip(ext_ty.args) do |f_arg_node, a_arg_vtx|
98
+ unless f_arg_node.typecheck(genv, changes, a_arg_vtx, subst)
99
+ args_all_match = false
100
+ break
101
+ end
102
+ end
103
+ return true if args_all_match
104
+ end
105
+ changes.add_depended_superclass(ext_ty.mod)
106
+
107
+ # The extended module may itself include other modules
108
+ return true if typecheck_for_included_modules(genv, changes, ext_ty, f_mod, f_args, subst)
109
+ end
110
+ return false
111
+ end
112
+
81
113
  class SigFuncType < Node
82
114
  def initialize(raw_decl, raw_type_params, raw_block, lenv)
83
115
  super(raw_decl, lenv)
@@ -108,13 +140,19 @@ module TypeProf::Core
108
140
  param = raw_decl.type.rest_positionals
109
141
  @rest_positionals = param ? AST.create_rbs_type(param.type, lenv) : nil
110
142
 
111
- @req_keywords = raw_decl.type.required_keywords.to_h do |key, ty|
143
+ @req_keyword_keys = []
144
+ @req_keyword_values = []
145
+ raw_decl.type.required_keywords.each do |key, ty|
112
146
  raise "unsupported argument type: #{ ty.class }" if !ty.is_a?(RBS::Types::Function::Param)
113
- [key, AST.create_rbs_type(ty.type, lenv)]
147
+ @req_keyword_keys << key
148
+ @req_keyword_values << AST.create_rbs_type(ty.type, lenv)
114
149
  end
115
- @opt_keywords = raw_decl.type.optional_keywords.to_h do |key, ty|
150
+ @opt_keyword_keys = []
151
+ @opt_keyword_values = []
152
+ raw_decl.type.optional_keywords.each do |key, ty|
116
153
  raise "unsupported argument type: #{ ty.class }" if !ty.is_a?(RBS::Types::Function::Param)
117
- [key, AST.create_rbs_type(ty.type, lenv)]
154
+ @opt_keyword_keys << key
155
+ @opt_keyword_values << AST.create_rbs_type(ty.type, lenv)
118
156
  end
119
157
  param = raw_decl.type.rest_keywords
120
158
  @rest_keywords = param ? AST.create_rbs_type(param.type, lenv) : nil
@@ -124,8 +162,10 @@ module TypeProf::Core
124
162
  @post_positionals = []
125
163
  @opt_positionals = []
126
164
  @rest_positionals = SigTyBaseAnyNode.new(raw_decl, lenv)
127
- @req_keywords = {}
128
- @opt_keywords = {}
165
+ @req_keyword_keys = []
166
+ @req_keyword_values = []
167
+ @opt_keyword_keys = []
168
+ @opt_keyword_values = []
129
169
  @rest_keywords = nil
130
170
  end
131
171
 
@@ -137,8 +177,10 @@ module TypeProf::Core
137
177
  attr_reader :post_positionals
138
178
  attr_reader :opt_positionals
139
179
  attr_reader :rest_positionals
140
- attr_reader :req_keywords
141
- attr_reader :opt_keywords
180
+ attr_reader :req_keyword_keys
181
+ attr_reader :req_keyword_values
182
+ attr_reader :opt_keyword_keys
183
+ attr_reader :opt_keyword_values
142
184
  attr_reader :rest_keywords
143
185
  attr_reader :return_type
144
186
 
@@ -148,12 +190,17 @@ module TypeProf::Core
148
190
  post_positionals:,
149
191
  opt_positionals:,
150
192
  rest_positionals:,
151
- req_keywords:,
152
- opt_keywords:,
193
+ req_keyword_values:,
194
+ opt_keyword_values:,
153
195
  rest_keywords:,
154
196
  return_type:,
155
197
  }
156
- def attrs = { type_params:, block_required: }
198
+ def attrs = {
199
+ type_params:,
200
+ req_keyword_keys:,
201
+ opt_keyword_keys:,
202
+ block_required:,
203
+ }
157
204
  end
158
205
 
159
206
  class SigTyNode < Node
@@ -182,6 +229,7 @@ module TypeProf::Core
182
229
  def typecheck(genv, changes, vtx, subst)
183
230
  changes.add_edge(genv, vtx, changes.target)
184
231
  vtx.each_type do |ty|
232
+ next if ty.is_a?(Type::Bot)
185
233
  return false unless ty == genv.true_type || ty == genv.false_type
186
234
  end
187
235
  true
@@ -204,6 +252,7 @@ module TypeProf::Core
204
252
  def typecheck(genv, changes, vtx, subst)
205
253
  changes.add_edge(genv, vtx, changes.target)
206
254
  vtx.each_type do |ty|
255
+ next if ty.is_a?(Type::Bot)
207
256
  return false unless ty == genv.nil_type
208
257
  end
209
258
  true
@@ -287,11 +336,11 @@ module TypeProf::Core
287
336
 
288
337
  class SigTyBaseBottomNode < SigTyNode
289
338
  def covariant_vertex0(genv, changes, vtx, subst)
290
- changes.add_edge(genv, Source.new(Type::Bot.new(genv)), vtx)
339
+ changes.add_edge(genv, Source.new(genv.bot_type), vtx)
291
340
  end
292
341
 
293
342
  def contravariant_vertex0(genv, changes, vtx, subst)
294
- changes.add_edge(genv, Source.new(Type::Bot.new(genv)), vtx)
343
+ changes.add_edge(genv, Source.new(genv.bot_type), vtx)
295
344
  end
296
345
 
297
346
  def typecheck(genv, changes, vtx, subst)
@@ -445,7 +494,13 @@ module TypeProf::Core
445
494
  decl = tae.decls.each {|decl| break decl }
446
495
  subst0 = subst.dup
447
496
  decl.params.zip(@args) do |param, arg|
448
- subst0[param] = arg.covariant_vertex(genv, changes, subst0)
497
+ if arg.is_a?(SigTyVarNode) && subst[arg.var]
498
+ # Share the vertex so that the types inferred in the alias body flow
499
+ # back into the variable, which makes `U` of `(array[U])` inferrable
500
+ subst0[param] = subst[arg.var]
501
+ else
502
+ subst0[param] = arg.covariant_vertex(genv, changes, subst0)
503
+ end
449
504
  end
450
505
  tae.type.typecheck(genv, changes, vtx, subst0)
451
506
  end
@@ -530,6 +585,8 @@ module TypeProf::Core
530
585
  name = raw_decl.name
531
586
  @cpath = name.namespace.path + [name.name]
532
587
  @toplevel = name.namespace.absolute?
588
+ # RBS::Types::ClassSingleton#args was added in RBS 4.0
589
+ @args = raw_decl.respond_to?(:args) ? raw_decl.args.map {|arg| AST.create_rbs_type(arg, lenv) } : []
533
590
  end
534
591
 
535
592
  attr_reader :cpath, :toplevel
@@ -578,7 +635,10 @@ module TypeProf::Core
578
635
  return unless cpath
579
636
  f_mod = genv.resolve_cpath(cpath)
580
637
  changes.add_edge(genv, vtx, changes.target)
638
+ found_any = false
581
639
  vtx.each_type do |ty|
640
+ next if ty.is_a?(Type::Bot)
641
+ found_any = true
582
642
  case ty
583
643
  when Type::Singleton
584
644
  if f_mod.module?
@@ -593,7 +653,7 @@ module TypeProf::Core
593
653
  end
594
654
  end
595
655
  end
596
- false
656
+ !found_any
597
657
  end
598
658
 
599
659
  def show
@@ -714,7 +774,10 @@ module TypeProf::Core
714
774
 
715
775
  def typecheck(genv, changes, vtx, subst)
716
776
  changes.add_edge(genv, vtx, changes.target)
777
+ found_any = false
717
778
  vtx.each_type do |ty|
779
+ next if ty.is_a?(Type::Bot)
780
+ found_any = true
718
781
  case ty
719
782
  when Type::Array
720
783
  next if ty.elems.size != @types.size
@@ -729,7 +792,7 @@ module TypeProf::Core
729
792
  return true
730
793
  end
731
794
  end
732
- false
795
+ !found_any
733
796
  end
734
797
 
735
798
  def show
@@ -740,16 +803,18 @@ module TypeProf::Core
740
803
  class SigTyRecordNode < SigTyNode
741
804
  def initialize(raw_decl, lenv)
742
805
  super(raw_decl, lenv)
743
- @fields = raw_decl.fields.transform_values { |val| AST.create_rbs_type(val, lenv) }
806
+ @keys = raw_decl.fields.keys
807
+ @vals = raw_decl.fields.values.map { |val| AST.create_rbs_type(val, lenv) }
744
808
  end
745
809
 
746
- attr_reader :fields
747
- def subnodes = { fields: }
810
+ attr_reader :keys, :vals
811
+ def subnodes = { vals: }
812
+ def attrs = { keys: }
748
813
 
749
814
  def covariant_vertex0(genv, changes, vtx, subst)
750
815
  field_vertices = {}
751
- @fields.each do |key, field_node|
752
- field_vertices[key] = field_node.covariant_vertex(genv, changes, subst)
816
+ @keys.zip(@vals) do |key, val_node|
817
+ field_vertices[key] = val_node.covariant_vertex(genv, changes, subst)
753
818
  end
754
819
 
755
820
  # Create base Hash type for Record
@@ -766,8 +831,8 @@ module TypeProf::Core
766
831
 
767
832
  def contravariant_vertex0(genv, changes, vtx, subst)
768
833
  field_vertices = {}
769
- @fields.each do |key, field_node|
770
- field_vertices[key] = field_node.contravariant_vertex(genv, changes, subst)
834
+ @keys.zip(@vals) do |key, val_node|
835
+ field_vertices[key] = val_node.contravariant_vertex(genv, changes, subst)
771
836
  end
772
837
 
773
838
  # Create base Hash type for Record
@@ -784,22 +849,25 @@ module TypeProf::Core
784
849
 
785
850
  def typecheck(genv, changes, vtx, subst)
786
851
  changes.add_edge(genv, vtx, changes.target)
852
+ found_any = false
787
853
  vtx.each_type do |ty|
854
+ next if ty.is_a?(Type::Bot)
855
+ found_any = true
788
856
  case ty
789
857
  when Type::Hash
790
- @fields.each do |key, field_node|
858
+ @keys.zip(@vals) do |key, val_node|
791
859
  val_vtx = ty.get_value(key)
792
- return false unless field_node.typecheck(genv, changes, val_vtx, subst)
860
+ return false unless val_node.typecheck(genv, changes, val_vtx, subst)
793
861
  end
794
862
  return true
795
863
  end
796
864
  end
797
- false
865
+ !found_any
798
866
  end
799
867
 
800
868
  def show
801
- field_strs = @fields.map do |key, field_node|
802
- "#{ key }: #{ field_node.show }"
869
+ field_strs = @keys.zip(@vals).map do |key, val_node|
870
+ "#{ key }: #{ val_node.show }"
803
871
  end
804
872
  "{ #{ field_strs.join(", ") } }"
805
873
  end
@@ -855,6 +923,16 @@ module TypeProf::Core
855
923
  end
856
924
 
857
925
  def typecheck(genv, changes, vtx, subst)
926
+ # For optional type T?, check if all non-nil types match T.
927
+ # nil is always acceptable.
928
+ changes.add_edge(genv, vtx, changes.target)
929
+ has_non_nil = false
930
+ vtx.each_type do |ty|
931
+ next if ty.is_a?(Type::Bot)
932
+ next if ty == genv.nil_type
933
+ has_non_nil = true
934
+ end
935
+ return true unless has_non_nil
858
936
  @type.typecheck(genv, changes, vtx, subst)
859
937
  end
860
938
 
@@ -900,13 +978,16 @@ module TypeProf::Core
900
978
  def typecheck(genv, changes, vtx, subst)
901
979
  if @lit.is_a?(::Symbol)
902
980
  changes.add_edge(genv, vtx, changes.target)
981
+ found_any = false
903
982
  vtx.each_type do |ty|
983
+ next if ty.is_a?(Type::Bot)
984
+ found_any = true
904
985
  case ty
905
986
  when Type::Symbol
906
987
  return true if ty.sym == @lit
907
988
  end
908
989
  end
909
- return false
990
+ return !found_any
910
991
  end
911
992
  f_mod = get_type(genv).mod
912
993
  AST.typecheck_for_module(genv, changes, f_mod, [], vtx, subst)
@@ -5,7 +5,7 @@ module TypeProf::Core
5
5
  when :string_node
6
6
  AST.create_node(raw_part, lenv)
7
7
  when :embedded_statements_node
8
- raw_part.statements ? AST.create_node(raw_part.statements, lenv) : DummyNilNode.new(TypeProf::CodeRange.from_node(raw_part), lenv)
8
+ raw_part.statements ? AST.create_node(raw_part.statements, lenv) : DummyNilNode.new(lenv.code_range_from_node(raw_part), lenv)
9
9
  when :embedded_variable_node
10
10
  AST.create_node(raw_part.variable, lenv)
11
11
  else
@@ -275,7 +275,7 @@ module TypeProf::Core
275
275
  if raw_elem.value
276
276
  @vals << AST.create_node(raw_elem.value, lenv)
277
277
  else
278
- @vals << DummyNilNode.new(code_range, lenv)
278
+ @vals << nil
279
279
  end
280
280
  @splat = true
281
281
  else
@@ -293,15 +293,20 @@ module TypeProf::Core
293
293
  unified_key = Vertex.new(self)
294
294
  unified_val = Vertex.new(self)
295
295
  literal_pairs = {}
296
+ all_symbol_keys = true
296
297
  @keys.zip(@vals) do |key, val|
297
298
  if key
298
299
  k = key.install(genv).new_vertex(genv, self)
299
300
  v = val.install(genv).new_vertex(genv, self)
300
301
  @changes.add_edge(genv, k, unified_key)
301
302
  @changes.add_edge(genv, v, unified_val)
302
- literal_pairs[key.lit] = v if key.is_a?(SymbolNode)
303
+ if key.is_a?(SymbolNode)
304
+ literal_pairs[key.lit] = v
305
+ else
306
+ all_symbol_keys = false
307
+ end
303
308
  else
304
- if val.is_a?(DummyNilNode)
309
+ if val.nil?
305
310
  h = @lenv.get_var(:"**anonymous_keyword")
306
311
  else
307
312
  h = val.install(genv)
@@ -310,10 +315,13 @@ module TypeProf::Core
310
315
  @changes.add_hash_splat_box(genv, h, unified_key, unified_val)
311
316
  end
312
317
  end
318
+ base_hash_type = genv.gen_hash_type(unified_key, unified_val)
313
319
  if @splat
314
- Source.new(genv.gen_hash_type(unified_key, unified_val))
320
+ Source.new(base_hash_type)
321
+ elsif all_symbol_keys
322
+ Source.new(Type::Record.new(genv, literal_pairs, base_hash_type))
315
323
  else
316
- Source.new(Type::Hash.new(genv, literal_pairs, genv.gen_hash_type(unified_key, unified_val)))
324
+ Source.new(Type::Hash.new(genv, literal_pairs, base_hash_type))
317
325
  end
318
326
  end
319
327
  end