typeprof 0.30.1 → 0.31.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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +23 -4
  3. data/lib/typeprof/cli/cli.rb +27 -7
  4. data/lib/typeprof/code_range.rb +9 -7
  5. data/lib/typeprof/core/ast/base.rb +27 -10
  6. data/lib/typeprof/core/ast/call.rb +85 -24
  7. data/lib/typeprof/core/ast/const.rb +7 -12
  8. data/lib/typeprof/core/ast/control.rb +345 -71
  9. data/lib/typeprof/core/ast/meta.rb +5 -5
  10. data/lib/typeprof/core/ast/method.rb +15 -5
  11. data/lib/typeprof/core/ast/misc.rb +21 -2
  12. data/lib/typeprof/core/ast/module.rb +10 -7
  13. data/lib/typeprof/core/ast/pattern.rb +9 -1
  14. data/lib/typeprof/core/ast/sig_decl.rb +163 -42
  15. data/lib/typeprof/core/ast/sig_type.rb +394 -24
  16. data/lib/typeprof/core/ast/value.rb +10 -2
  17. data/lib/typeprof/core/ast/variable.rb +32 -2
  18. data/lib/typeprof/core/ast.rb +15 -4
  19. data/lib/typeprof/core/builtin.rb +15 -9
  20. data/lib/typeprof/core/env/method.rb +21 -16
  21. data/lib/typeprof/core/env/method_entity.rb +11 -2
  22. data/lib/typeprof/core/env/module_entity.rb +57 -0
  23. data/lib/typeprof/core/env/narrowing.rb +131 -0
  24. data/lib/typeprof/core/env/static_read.rb +9 -8
  25. data/lib/typeprof/core/env.rb +37 -12
  26. data/lib/typeprof/core/graph/box.rb +207 -97
  27. data/lib/typeprof/core/graph/change_set.rb +44 -37
  28. data/lib/typeprof/core/graph/vertex.rb +4 -21
  29. data/lib/typeprof/core/service.rb +30 -1
  30. data/lib/typeprof/core/type.rb +48 -123
  31. data/lib/typeprof/core.rb +1 -0
  32. data/lib/typeprof/diagnostic.rb +5 -6
  33. data/lib/typeprof/lsp/messages.rb +21 -15
  34. data/lib/typeprof/lsp/server.rb +132 -39
  35. data/lib/typeprof/lsp/text.rb +1 -0
  36. data/lib/typeprof/version.rb +1 -1
  37. data/typeprof.conf.jsonc +22 -0
  38. data/typeprof.gemspec +1 -0
  39. metadata +19 -6
@@ -17,6 +17,29 @@ module TypeProf::Core
17
17
  def retrieve_at(pos)
18
18
  yield self if code_range.include?(pos)
19
19
  end
20
+
21
+ def narrowings
22
+ @narrowings ||= [
23
+ Narrowing.new({ @var => Narrowing::NilConstraint.new(false) }),
24
+ Narrowing.new({ @var => Narrowing::NilConstraint.new(true) }),
25
+ ]
26
+ end
27
+ end
28
+
29
+ class ItLocalVariableReadNode < Node
30
+ def initialize(raw_node, lenv)
31
+ super(raw_node, lenv)
32
+ end
33
+
34
+ def attrs = {}
35
+
36
+ def install0(genv)
37
+ @lenv.get_var(:it)
38
+ end
39
+
40
+ def retrieve_at(pos)
41
+ yield self if code_range.include?(pos)
42
+ end
20
43
  end
21
44
 
22
45
  class LocalVariableWriteNode < Node
@@ -64,7 +87,7 @@ module TypeProf::Core
64
87
  case @lenv.cref.scope_level
65
88
  when :class, :instance
66
89
  box = @changes.add_ivar_read_box(genv, lenv.cref.cpath, lenv.cref.scope_level == :class, @var)
67
- @lenv.apply_read_filter(genv, self, @var, box.ret)
90
+ @lenv.apply_ivar_narrowing(genv, self, @var, box.ret)
68
91
  else
69
92
  Source.new()
70
93
  end
@@ -73,6 +96,13 @@ module TypeProf::Core
73
96
  def retrieve_at(pos)
74
97
  yield self if code_range.include?(pos)
75
98
  end
99
+
100
+ def narrowings
101
+ @narrowings ||= [
102
+ Narrowing.new({ @var => Narrowing::NilConstraint.new(false) }),
103
+ Narrowing.new({ @var => Narrowing::NilConstraint.new(true) }),
104
+ ]
105
+ end
76
106
  end
77
107
 
78
108
  class InstanceVariableWriteNode < Node
@@ -289,7 +319,7 @@ module TypeProf::Core
289
319
 
290
320
  def install0(genv)
291
321
  box = @changes.add_cvar_read_box(genv, lenv.cref.cpath, @var)
292
- @lenv.apply_read_filter(genv, self, @var, box.ret)
322
+ @lenv.apply_ivar_narrowing(genv, self, @var, box.ret)
293
323
  end
294
324
 
295
325
  def retrieve_at(pos)
@@ -58,6 +58,7 @@ module TypeProf::Core
58
58
  when :begin_node then BeginNode.new(raw_node, lenv)
59
59
  when :retry_node then RetryNode.new(raw_node, lenv)
60
60
  when :rescue_modifier_node then RescueModifierNode.new(raw_node, lenv)
61
+ when :rescue_node then RescueNode.new(raw_node, lenv)
61
62
 
62
63
  # constants
63
64
  when :constant_read_node, :constant_path_node
@@ -92,6 +93,8 @@ module TypeProf::Core
92
93
  # variables
93
94
  when :local_variable_read_node
94
95
  LocalVariableReadNode.new(raw_node, lenv)
96
+ when :it_local_variable_read_node
97
+ ItLocalVariableReadNode.new(raw_node, lenv)
95
98
  when :local_variable_write_node
96
99
  LocalVariableWriteNode.new(raw_node, AST.create_node(raw_node.value, lenv), lenv)
97
100
  when :local_variable_operator_write_node
@@ -223,7 +226,7 @@ module TypeProf::Core
223
226
  when :flip_flop_node then FlipFlopNode.new(raw_node, lenv)
224
227
  when :shareable_constant_node then create_node(raw_node.write, lenv)
225
228
  when :match_required_node then MatchRequiredNode.new(raw_node, lenv)
226
- when :match_predicate_node then MatchPreidcateNode.new(raw_node, lenv)
229
+ when :match_predicate_node then MatchPredicateNode.new(raw_node, lenv)
227
230
 
228
231
  # call
229
232
  when :super_node then SuperNode.new(raw_node, lenv)
@@ -343,8 +346,7 @@ module TypeProf::Core
343
346
  break
344
347
  when :constant_path_node, :constant_path_target_node
345
348
  if raw_node.parent
346
- # temporarily support old Prism https://bugs.ruby-lang.org/issues/20467
347
- names << (raw_node.respond_to?(:name) ? raw_node.name : raw_node.child.name)
349
+ names << raw_node.name
348
350
  raw_node = raw_node.parent
349
351
  else
350
352
  return names.reverse
@@ -356,7 +358,8 @@ module TypeProf::Core
356
358
  return nil
357
359
  end
358
360
  end
359
- return cref.cpath + names.reverse
361
+ cpath = cref.cpath # annotate
362
+ return cpath + names.reverse if cpath
360
363
  end
361
364
 
362
365
  def self.parse_rbs(path, src)
@@ -397,6 +400,8 @@ module TypeProf::Core
397
400
  SigDefNode.new(raw_decl, lenv)
398
401
  when RBS::AST::Members::Include
399
402
  SigIncludeNode.new(raw_decl, lenv)
403
+ when RBS::AST::Members::Prepend
404
+ SigPrependNode.new(raw_decl, lenv)
400
405
  when RBS::AST::Members::Extend
401
406
  when RBS::AST::Members::Public
402
407
  when RBS::AST::Members::Private
@@ -410,6 +415,12 @@ module TypeProf::Core
410
415
  SigAttrAccessorNode.new(raw_decl, lenv)
411
416
  when RBS::AST::Declarations::Base
412
417
  self.create_rbs_decl(raw_decl, lenv)
418
+ when RBS::AST::Members::InstanceVariable
419
+ SigInstanceVariableNode.new(raw_decl, lenv, false)
420
+ when RBS::AST::Members::ClassInstanceVariable
421
+ SigInstanceVariableNode.new(raw_decl, lenv, true)
422
+ when RBS::AST::Members::ClassVariable
423
+ SigClassVariableNode.new(raw_decl, lenv)
413
424
  else
414
425
  raise "unsupported: #{ raw_decl.class }"
415
426
  end
@@ -5,12 +5,11 @@ module TypeProf::Core
5
5
  end
6
6
 
7
7
  def class_new(changes, node, ty, a_args, ret)
8
- if ty.is_a?(Type::Singleton)
9
- ty = ty.get_instance_type(@genv)
10
- recv = Source.new(ty)
11
- changes.add_method_call_box(@genv, recv, :initialize, a_args, false)
12
- changes.add_edge(@genv, Source.new(ty), ret)
13
- end
8
+ type_param_vtxs = ty.mod.type_params.map { Vertex.new(node) }
9
+ temp_instance_ty = Type::Instance.new(@genv, ty.mod, type_param_vtxs)
10
+ recv = Source.new(temp_instance_ty)
11
+ changes.add_method_call_box(@genv, recv, :initialize, a_args, false)
12
+ changes.add_edge(@genv, recv, ret)
14
13
  true
15
14
  end
16
15
 
@@ -26,7 +25,8 @@ module TypeProf::Core
26
25
  def proc_call(changes, node, ty, a_args, ret)
27
26
  case ty
28
27
  when Type::Proc
29
- ty.block.accept_args(@genv, changes, a_args.positionals, ret, false)
28
+ ty.block.accept_args(@genv, changes, a_args.positionals)
29
+ ty.block.add_ret(@genv, changes, ret)
30
30
  true
31
31
  else
32
32
  false
@@ -90,10 +90,16 @@ module TypeProf::Core
90
90
  def hash_aref(changes, node, ty, a_args, ret)
91
91
  if a_args.positionals.size == 1
92
92
  case ty
93
- when Type::Hash
93
+ when Type::Hash, Type::Record
94
94
  idx = node.positional_args[0]
95
95
  idx = idx.is_a?(AST::SymbolNode) ? idx.lit : nil
96
- changes.add_edge(@genv, ty.get_value(idx), ret)
96
+ value = ty.get_value(idx)
97
+ if value
98
+ changes.add_edge(@genv, value, ret)
99
+ else
100
+ # Return untyped for unknown fields
101
+ changes.add_edge(@genv, Source.new(), ret)
102
+ end
97
103
  true
98
104
  else
99
105
  false
@@ -41,7 +41,7 @@ module TypeProf::Core
41
41
  ActualArguments.new(positionals, splat_flags, keywords, block)
42
42
  end
43
43
 
44
- def get_rest_args(genv, start_rest, end_rest)
44
+ def get_rest_args(genv, changes, start_rest, end_rest)
45
45
  vtxs = []
46
46
 
47
47
  start_rest.upto(end_rest - 1) do |i|
@@ -50,7 +50,7 @@ module TypeProf::Core
50
50
  a_arg.each_type do |ty|
51
51
  ty = ty.base_type(genv)
52
52
  if ty.is_a?(Type::Instance) && ty.mod == genv.mod_ary && ty.args[0]
53
- vtxs << ty.args[0].new_vertex(genv, self)
53
+ vtxs << changes.new_vertex(genv, self, ty.args[0])
54
54
  else
55
55
  "???"
56
56
  end
@@ -82,6 +82,7 @@ module TypeProf::Core
82
82
  end
83
83
 
84
84
  class Block
85
+ #: (AST::CallBaseNode, Vertex, Array[Vertex], Array[EscapeBox]) -> void
85
86
  def initialize(node, f_ary_arg, f_args, next_boxes)
86
87
  @node = node
87
88
  @f_ary_arg = f_ary_arg
@@ -89,25 +90,26 @@ module TypeProf::Core
89
90
  @next_boxes = next_boxes
90
91
  end
91
92
 
92
- attr_reader :node, :f_args, :ret
93
+ attr_reader :node, :f_args, :next_boxes
93
94
 
94
- def accept_args(genv, changes, caller_positionals, caller_ret, ret_check)
95
+ def accept_args(genv, changes, caller_positionals)
95
96
  if caller_positionals.size == 1 && @f_args.size >= 2
96
- # TODO: support splat "do |a, *b, c|"
97
- changes.add_edge(genv, caller_positionals[0].new_vertex(genv, @node), @f_ary_arg)
97
+ single_arg = caller_positionals[0]
98
+
99
+ @f_args.each_with_index do |f_arg, i|
100
+ elem_vtx = changes.add_splat_box(genv, single_arg, i).ret
101
+ changes.add_edge(genv, elem_vtx, f_arg)
102
+ end
98
103
  else
99
104
  caller_positionals.zip(@f_args) do |a_arg, f_arg|
100
105
  changes.add_edge(genv, a_arg, f_arg) if f_arg
101
106
  end
102
107
  end
103
- if ret_check
104
- @next_boxes.each do |box|
105
- changes.add_edge(genv, caller_ret, box.f_ret)
106
- end
107
- else
108
- @next_boxes.each do |box|
109
- changes.add_edge(genv, box.a_ret, caller_ret)
110
- end
108
+ end
109
+
110
+ def add_ret(genv, changes, ret)
111
+ @next_boxes.each do |box|
112
+ changes.add_edge(genv, box.a_ret, ret)
111
113
  end
112
114
  end
113
115
  end
@@ -126,12 +128,15 @@ module TypeProf::Core
126
128
 
127
129
  attr_reader :node, :f_args, :ret, :used
128
130
 
129
- def accept_args(genv, changes, caller_positionals, caller_ret, ret_check)
131
+ def accept_args(genv, changes, caller_positionals)
130
132
  @used = true
131
133
  caller_positionals.each_with_index do |a_arg, i|
132
134
  changes.add_edge(genv, a_arg.new_vertex(genv, @node), get_f_arg(i))
133
135
  end
134
- changes.add_edge(genv, caller_ret, @ret)
136
+ end
137
+
138
+ def add_ret(genv, changes, ret)
139
+ changes.add_edge(genv, ret, @ret)
135
140
  end
136
141
  end
137
142
  end
@@ -3,6 +3,7 @@ module TypeProf::Core
3
3
  def initialize
4
4
  @builtin = nil
5
5
  @decls = Set[]
6
+ @overloading_decls = Set[]
6
7
  @defs = Set[]
7
8
  @aliases = {}
8
9
  @method_call_boxes = Set[]
@@ -12,11 +13,19 @@ module TypeProf::Core
12
13
  attr_accessor :builtin
13
14
 
14
15
  def add_decl(decl)
15
- @decls << decl
16
+ if decl.overloading
17
+ @overloading_decls << decl
18
+ else
19
+ @decls << decl
20
+ end
16
21
  end
17
22
 
18
23
  def remove_decl(decl)
19
- @decls.delete(decl) || raise
24
+ if decl.overloading
25
+ @overloading_decls.delete(decl) || raise
26
+ else
27
+ @decls.delete(decl) || raise
28
+ end
20
29
  end
21
30
 
22
31
  def add_def(mdef)
@@ -7,6 +7,8 @@ module TypeProf::Core
7
7
  @module_defs = Set[]
8
8
  @include_decls = Set[]
9
9
  @include_defs = Set[]
10
+ @prepend_decls = []
11
+ @prepend_defs = []
10
12
 
11
13
  @inner_modules = {}
12
14
  @outer_module = outer_module
@@ -15,6 +17,7 @@ module TypeProf::Core
15
17
  @superclass = nil
16
18
  @self_types = {}
17
19
  @included_modules = {}
20
+ @prepended_modules = {}
18
21
  @basic_object = @cpath == [:BasicObject]
19
22
 
20
23
  # child modules (subclasses and all modules that include me)
@@ -46,6 +49,7 @@ module TypeProf::Core
46
49
  attr_reader :superclass
47
50
  attr_reader :self_types
48
51
  attr_reader :included_modules
52
+ attr_reader :prepended_modules
49
53
  attr_reader :child_modules
50
54
 
51
55
  attr_reader :superclass_type_args
@@ -192,6 +196,26 @@ module TypeProf::Core
192
196
  genv.add_static_eval_queue(:parent_modules_changed, self)
193
197
  end
194
198
 
199
+ def add_prepend_decl(genv, node)
200
+ @prepend_decls << node
201
+ genv.add_static_eval_queue(:parent_modules_changed, self)
202
+ end
203
+
204
+ def remove_prepend_decl(genv, node)
205
+ @prepend_decls.delete(node) || raise
206
+ genv.add_static_eval_queue(:parent_modules_changed, self)
207
+ end
208
+
209
+ def add_prepend_def(genv, node)
210
+ @prepend_defs << node
211
+ genv.add_static_eval_queue(:parent_modules_changed, self)
212
+ end
213
+
214
+ def remove_prepend_def(genv, node)
215
+ @prepend_defs.delete(node) || raise
216
+ genv.add_static_eval_queue(:parent_modules_changed, self)
217
+ end
218
+
195
219
  def update_parent(genv, origin, old_parent, new_parent_cpath)
196
220
  new_parent = new_parent_cpath ? genv.resolve_cpath(new_parent_cpath) : nil
197
221
  if old_parent != new_parent
@@ -323,6 +347,30 @@ module TypeProf::Core
323
347
  any_updated = true
324
348
  end
325
349
  end
350
+ @prepend_decls.each do |pdecl|
351
+ new_parent_cpath = pdecl.static_ret.last.cpath
352
+ new_parent, updated = update_parent(genv, pdecl, @prepended_modules[pdecl], new_parent_cpath)
353
+ if updated
354
+ if new_parent
355
+ @prepended_modules[pdecl] = new_parent
356
+ else
357
+ @prepended_modules.delete(pdecl) || raise
358
+ end
359
+ any_updated = true
360
+ end
361
+ end
362
+ @prepend_defs.each do |pdef|
363
+ new_parent_cpath = pdef.static_ret ? pdef.static_ret.cpath : nil
364
+ new_parent, updated = update_parent(genv, pdef, @prepended_modules[pdef], new_parent_cpath)
365
+ if updated
366
+ if new_parent
367
+ @prepended_modules[pdef] = new_parent
368
+ else
369
+ @prepended_modules.delete(pdef) || raise
370
+ end
371
+ any_updated = true
372
+ end
373
+ end
326
374
  @included_modules.delete_if do |origin, old_mod|
327
375
  if @include_decls.include?(origin) || @include_defs.include?(origin)
328
376
  false
@@ -332,6 +380,15 @@ module TypeProf::Core
332
380
  true
333
381
  end
334
382
  end
383
+ @prepended_modules.delete_if do |origin, old_mod|
384
+ if @prepend_decls.include?(origin) || @prepend_defs.include?(origin)
385
+ false
386
+ else
387
+ _new_parent, updated = update_parent(genv, origin, old_mod, nil)
388
+ any_updated ||= updated
389
+ true
390
+ end
391
+ end
335
392
 
336
393
  if any_updated
337
394
  @subclass_checks.each do |mcall_box|
@@ -0,0 +1,131 @@
1
+ module TypeProf::Core
2
+ class Narrowing
3
+ def initialize(map)
4
+ raise unless map.is_a?(Hash)
5
+ @map = map
6
+ end
7
+
8
+ attr_reader :map
9
+
10
+ def and(other)
11
+ new_map = @map.dup
12
+ other.map.each do |var, constraint|
13
+ new_map[var] = new_map[var] ? new_map[var].and(constraint) : constraint
14
+ end
15
+ Narrowing.new(new_map)
16
+ end
17
+
18
+ def or(other)
19
+ new_map = {}
20
+ @map.each do |var, constraint|
21
+ new_map[var] = constraint.or(other.map[var]) if other.map[var]
22
+ end
23
+ Narrowing.new(new_map)
24
+ end
25
+
26
+ EmptyNarrowings = [Narrowing.new({}), Narrowing.new({})]
27
+
28
+ # Narrowing system for type refinement
29
+ class Constraint
30
+ def and(other)
31
+ AndConstraint.new(self, other)
32
+ end
33
+
34
+ def or(other)
35
+ OrConstraint.new(self, other)
36
+ end
37
+ end
38
+
39
+ class IsAConstraint < Constraint
40
+ def initialize(arg, neg)
41
+ @arg = arg
42
+ @neg = neg
43
+ end
44
+
45
+ attr_reader :arg, :neg
46
+
47
+ def negate
48
+ IsAConstraint.new(@arg, !@neg)
49
+ end
50
+
51
+ def inspect
52
+ @neg ? "!#{@arg}" : "#{@arg}"
53
+ end
54
+
55
+ def narrow(genv, node, vtx)
56
+ if @arg.static_ret
57
+ IsAFilter.new(genv, node, vtx, @neg, @arg.static_ret).next_vtx
58
+ else
59
+ vtx
60
+ end
61
+ end
62
+ end
63
+
64
+ class NilConstraint < Constraint
65
+ def initialize(neg)
66
+ @neg = neg
67
+ end
68
+
69
+ attr_reader :neg
70
+
71
+ def inspect
72
+ @neg ? "!nil" : "nil"
73
+ end
74
+
75
+ def negate
76
+ NilConstraint.new(!@neg)
77
+ end
78
+
79
+ def narrow(genv, node, vtx)
80
+ NilFilter.new(genv, node, vtx, @neg).next_vtx
81
+ end
82
+ end
83
+
84
+ class AndConstraint < Constraint
85
+ def initialize(left, right)
86
+ @left = left
87
+ @right = right
88
+ end
89
+
90
+ attr_reader :left, :right
91
+
92
+ def inspect
93
+ "(#{@left.inspect} & #{@right.inspect})"
94
+ end
95
+
96
+ def negate
97
+ OrConstraint.new(@left.negate, @right.negate)
98
+ end
99
+
100
+ def narrow(genv, node, vtx)
101
+ @left.narrow(genv, node, @right.narrow(genv, node, vtx))
102
+ end
103
+ end
104
+
105
+ class OrConstraint < Constraint
106
+ def initialize(left, right)
107
+ @left = left
108
+ @right = right
109
+ end
110
+
111
+ attr_reader :left, :right
112
+
113
+ def inspect
114
+ "(#{@left.inspect} | #{@right.inspect})"
115
+ end
116
+
117
+ def negate
118
+ AndConstraint.new(@left.negate, @right.negate)
119
+ end
120
+
121
+ def narrow(genv, node, vtx)
122
+ ret = Vertex.new(node)
123
+ vtx1 = @left.narrow(genv, node, vtx)
124
+ vtx2 = @right.narrow(genv, node, vtx)
125
+ vtx1.add_edge(genv, ret)
126
+ vtx2.add_edge(genv, ret)
127
+ ret
128
+ end
129
+ end
130
+ end
131
+ end
@@ -30,10 +30,9 @@ module TypeProf::Core
30
30
  @source_modules.clear
31
31
  end
32
32
 
33
- def resolve(genv, cref, break_object)
33
+ def resolve(genv, cref, search_ancestors, break_object)
34
34
  destroy(genv)
35
35
 
36
- first = true
37
36
  while cref
38
37
  scope = cref.cpath
39
38
  mod = genv.resolve_cpath(scope)
@@ -47,9 +46,9 @@ module TypeProf::Core
47
46
 
48
47
  return if check_module(genv, mod)
49
48
 
50
- break unless first
49
+ break unless search_ancestors
51
50
  end
52
- first = false
51
+ search_ancestors = false
53
52
  cref = cref.outer
54
53
  end
55
54
  resolution_failed(genv)
@@ -57,29 +56,31 @@ module TypeProf::Core
57
56
  end
58
57
 
59
58
  class BaseStaticRead < StaticRead
60
- def initialize(genv, name, cref)
59
+ def initialize(genv, name, cref, strict_const_scope)
61
60
  super(name)
62
61
  @cref = cref
62
+ @search_ancestors = !strict_const_scope
63
63
  genv.add_static_eval_queue(:static_read_changed, self)
64
64
  end
65
65
 
66
66
  attr_reader :cref
67
67
 
68
68
  def on_scope_updated(genv)
69
- resolve(genv, @cref, false)
69
+ resolve(genv, @cref, @search_ancestors, false)
70
70
  end
71
71
  end
72
72
 
73
73
  class ScopedStaticRead < StaticRead
74
- def initialize(name, cbase)
74
+ def initialize(name, cbase, strict_const_scope)
75
75
  super(name)
76
76
  @cbase = cbase
77
77
  @cbase.followers << self if @cbase
78
+ @search_ancestors = !strict_const_scope
78
79
  end
79
80
 
80
81
  def on_cbase_updated(genv)
81
82
  if @cbase && @cbase.cpath
82
- resolve(genv, CRef.new(@cbase.cpath, :class, nil, nil), true)
83
+ resolve(genv, CRef.new(@cbase.cpath, :class, nil, nil), @search_ancestors, true)
83
84
  else
84
85
  resolution_failed(genv)
85
86
  end
@@ -8,6 +8,8 @@ module TypeProf::Core
8
8
  @run_queue = []
9
9
  @run_queue_set = Set[]
10
10
 
11
+ @pending_diagnostic_paths = Set[]
12
+
11
13
  @mod_object = ModuleEntity.new([])
12
14
  @mod_object.inner_modules[:Object] = @mod_object
13
15
 
@@ -112,7 +114,7 @@ module TypeProf::Core
112
114
  ty_env = base_ty_env.dup
113
115
  if base_ty.is_a?(Type::Instance)
114
116
  base_ty.mod.type_params.zip(base_ty.args) do |param, arg|
115
- ty_env[param] = arg
117
+ ty_env[param] = arg || Source.new
116
118
  end
117
119
  end
118
120
  args = mod.type_params.zip(type_args).map do |param, arg|
@@ -179,6 +181,19 @@ module TypeProf::Core
179
181
  @run_count += run_count
180
182
  end
181
183
 
184
+ def process_diagnostic_paths
185
+ processed_paths = []
186
+ @pending_diagnostic_paths.each do |path|
187
+ processed = yield path
188
+ processed_paths << path if processed
189
+ end
190
+ processed_paths.each {|path| @pending_diagnostic_paths.delete(path) }
191
+ end
192
+
193
+ def add_diagnostic_path(path)
194
+ @pending_diagnostic_paths << path unless @pending_diagnostic_paths.include?(path)
195
+ end
196
+
182
197
  # just for validation
183
198
  def get_vertexes(vtxs)
184
199
  @mod_object.get_vertexes(vtxs)
@@ -284,10 +299,11 @@ module TypeProf::Core
284
299
  @return_boxes = return_boxes
285
300
  @break_vtx = nil
286
301
  @next_boxes = []
287
- @filters = {}
302
+ @ivar_narrowings = {}
303
+ @strict_const_scope = false
288
304
  end
289
305
 
290
- attr_reader :path, :cref, :locals, :return_boxes, :break_vtx, :next_boxes
306
+ attr_reader :path, :cref, :locals, :return_boxes, :break_vtx, :next_boxes, :strict_const_scope
291
307
 
292
308
  def new_var(name, node)
293
309
  @locals[name] = Vertex.new(node)
@@ -318,23 +334,32 @@ module TypeProf::Core
318
334
  end
319
335
 
320
336
 
321
- def push_read_filter(name, type)
322
- (@filters[name] ||= []) << type
337
+ def push_ivar_narrowing(name, narrowing)
338
+ raise unless narrowing.is_a?(Narrowing::Constraint)
339
+ (@ivar_narrowings[name] ||= []) << narrowing
323
340
  end
324
341
 
325
- def pop_read_filter(name)
326
- (@filters[name] ||= []).pop
342
+ def pop_ivar_narrowing(name)
343
+ (@ivar_narrowings[name] ||= []).pop
327
344
  end
328
345
 
329
- def apply_read_filter(genv, node, name, vtx)
330
- if @filters[name] && !@filters[name].empty?
331
- case @filters[name].last
332
- when :non_nil
333
- return NilFilter.new(genv, node, vtx, false).next_vtx
346
+ def apply_ivar_narrowing(genv, node, name, vtx)
347
+ if @ivar_narrowings[name] && !@ivar_narrowings[name].empty?
348
+ # Apply all accumulated narrowings in order
349
+ @ivar_narrowings[name].each do |narrowing|
350
+ vtx = narrowing.narrow(genv, node, vtx)
334
351
  end
352
+ return vtx
335
353
  end
336
354
  vtx
337
355
  end
356
+
357
+ def use_strict_const_scope
358
+ @strict_const_scope = true
359
+ yield
360
+ ensure
361
+ @strict_const_scope = false
362
+ end
338
363
  end
339
364
 
340
365
  class CRef