Skip to content

Commit

Permalink
Prevent the analysis from getting stuck
Browse files Browse the repository at this point in the history
Creating a new vertex in argument matching may cause infinite loop.
See scenario/misc/ivar-stuck-case.rb.
  • Loading branch information
mame committed Aug 10, 2024
1 parent c7c39ee commit 335fe6d
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 24 deletions.
40 changes: 20 additions & 20 deletions lib/typeprof/core/ast/sig_type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -80,13 +80,13 @@ def attrs = { type_params:, block_required: }

class SigTyNode < Node
def covariant_vertex(genv, changes, subst)
vtx = changes.new_vertex(genv, self)
vtx = changes.new_covariant_vertex(genv, self)
covariant_vertex0(genv, changes, vtx, subst)
vtx
end

def contravariant_vertex(genv, changes, subst)
vtx = Vertex.new(self)
vtx = changes.new_contravariant_vertex(genv, self)
contravariant_vertex0(genv, changes, vtx, subst)
vtx
end
Expand All @@ -98,7 +98,7 @@ def covariant_vertex0(genv, changes, vtx, subst)
end

def contravariant_vertex0(genv, changes, vtx, subst)
Source.new(genv.true_type, genv.false_type).add_edge(genv, vtx)
changes.add_edge(genv, Source.new(genv.true_type, genv.false_type), vtx)
end

def show
Expand All @@ -112,7 +112,7 @@ def covariant_vertex0(genv, changes, vtx, subst)
end

def contravariant_vertex0(genv, changes, vtx, subst)
Source.new(genv.nil_type).add_edge(genv, vtx)
changes.add_edge(genv, Source.new(genv.nil_type), vtx)
end

def show
Expand All @@ -126,7 +126,7 @@ def covariant_vertex0(genv, changes, vtx, subst)
end

def contravariant_vertex0(genv, changes, vtx, subst)
subst[:"*self"].add_edge(genv, vtx)
changes.add_edge(genv, subst[:"*self"], vtx)
end

def show
Expand All @@ -140,7 +140,7 @@ def covariant_vertex0(genv, changes, vtx, subst)
end

def contravariant_vertex0(genv, changes, vtx, subst)
Source.new(genv.obj_type).add_edge(genv, vtx)
changes.add_edge(genv, Source.new(genv.obj_type), vtx)
end

def show
Expand Down Expand Up @@ -181,7 +181,7 @@ def covariant_vertex0(genv, changes, vtx, subst)
end

def contravariant_vertex0(genv, changes, vtx, subst)
Source.new(Type::Bot.new(genv)).add_edge(genv, vtx)
changes.add_edge(genv, Source.new(Type::Bot.new(genv)), vtx)
end

def show
Expand All @@ -195,7 +195,7 @@ def covariant_vertex0(genv, changes, vtx, subst)
end

def contravariant_vertex0(genv, changes, vtx, subst)
subst[:"*instance"].add_edge(genv, vtx)
changes.add_edge(genv, subst[:"*instance"], vtx)
end

def show
Expand All @@ -209,7 +209,7 @@ def covariant_vertex0(genv, changes, vtx, subst)
end

def contravariant_vertex0(genv, changes, vtx, subst)
subst[:"*class"].add_edge(genv, vtx)
changes.add_edge(genv, subst[:"*class"], vtx)
end

def show
Expand Down Expand Up @@ -375,7 +375,7 @@ def contravariant_vertex0(genv, changes, vtx, subst)
cpath = @static_ret.last.cpath
return unless cpath
mod = genv.resolve_cpath(cpath)
Source.new(Type::Singleton.new(genv, mod)).add_edge(genv, vtx)
changes.add_edge(genv, Source.new(Type::Singleton.new(genv, mod)), vtx)
end

def show
Expand Down Expand Up @@ -436,7 +436,7 @@ def contravariant_vertex0(genv, changes, vtx, subst)
return unless cpath
mod = genv.resolve_cpath(cpath)
args = @args.map {|arg| arg.contravariant_vertex(genv, changes, subst) }
Source.new(Type::Instance.new(genv, mod, args)).add_edge(genv, vtx)
changes.add_edge(genv, Source.new(Type::Instance.new(genv, mod, args)), vtx)
end

def show
Expand All @@ -458,23 +458,23 @@ def initialize(raw_decl, lenv)
def subnodes = { types: }

def covariant_vertex0(genv, changes, vtx, subst)
unified_elem = Vertex.new(self) # TODO
unified_elem = changes.new_covariant_vertex(genv, [self, :Elem]) # TODO
elems = @types.map do |type|
nvtx = type.covariant_vertex(genv, changes, subst)
nvtx.add_edge(genv, unified_elem)
changes.add_edge(genv, nvtx, unified_elem)
nvtx
end
changes.add_edge(genv, Source.new(Type::Array.new(genv, elems, genv.gen_ary_type(unified_elem))), vtx)
end

def contravariant_vertex0(genv, changes, vtx, subst)
unified_elem = Vertex.new(self)
unified_elem = changes.new_contravariant_vertex(genv, [self, :Elem]) # TODO
elems = @types.map do |type|
nvtx = type.contravariant_vertex(genv, changes, subst)
nvtx.add_edge(genv, unified_elem)
changes.add_edge(genv, nvtx, unified_elem)
nvtx
end
Source.new(Type::Array.new(genv, elems, genv.gen_ary_type(unified_elem))).add_edge(genv, vtx)
changes.add_edge(genv, Source.new(Type::Array.new(genv, elems, genv.gen_ary_type(unified_elem))), vtx)
end

def show
Expand Down Expand Up @@ -513,7 +513,7 @@ def covariant_vertex0(genv, changes, vtx, subst)

def contravariant_vertex0(genv, changes, vtx, subst)
raise "unknown type variable: #{ @var }" unless subst[@var]
Source.new(Type::Var.new(genv, @var, subst[@var])).add_edge(genv, vtx)
changes.add_edge(genv, Source.new(Type::Var.new(genv, @var, subst[@var])), vtx)
end

def show
Expand All @@ -537,7 +537,7 @@ def covariant_vertex0(genv, changes, vtx, subst)

def contravariant_vertex0(genv, changes, vtx, subst)
@type.contravariant_vertex0(genv, changes, vtx, subst)
Source.new(genv.nil_type).add_edge(genv, vtx)
changes.add_edge(genv, Source.new(genv.nil_type), vtx)
end

def show
Expand Down Expand Up @@ -576,7 +576,7 @@ def covariant_vertex0(genv, changes, vtx, subst)
end

def contravariant_vertex0(genv, changes, vtx, subst)
Source.new(get_type(genv)).add_edge(genv, vtx)
changes.add_edge(genv, Source.new(get_type(genv)), vtx)
end

def show
Expand Down Expand Up @@ -648,7 +648,7 @@ def contravariant_vertex0(genv, changes, vtx, subst)
return unless cpath
mod = genv.resolve_cpath(cpath)
args = @args.map {|arg| arg.contravariant_vertex(genv, changes, subst) }
Source.new(Type::Instance.new(genv, mod, args)).add_edge(genv, vtx)
changes.add_edge(genv, Source.new(Type::Instance.new(genv, mod, args)), vtx)
end

def show
Expand Down
9 changes: 6 additions & 3 deletions lib/typeprof/core/graph/box.rb
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,7 @@ def resolve_overloads(changes, genv, node, param_map, a_args, ret)
@method_types.each do |method_type|
param_map0 = param_map.dup
if method_type.type_params
method_type.type_params.map do |var|
vtx = Vertex.new(node)
method_type.type_params.zip(yield(method_type)) do |var, vtx|
param_map0[var] = vtx
end
end
Expand All @@ -210,6 +209,7 @@ def resolve_overloads(changes, genv, node, param_map, a_args, ret)
end
end
ret_vtx = method_type.return_type.covariant_vertex(genv, changes, param_map0)

changes.add_edge(genv, ret_vtx, ret)
match_any_overload = true
end
Expand Down Expand Up @@ -644,6 +644,7 @@ def initialize(node, genv, recv, mid, a_args, subclasses)
@a_args.block.add_edge(genv, self) if @a_args.block
@ret = Vertex.new(node)
@subclasses = subclasses
@generics = {}
end

attr_reader :recv, :mid, :ret
Expand Down Expand Up @@ -673,7 +674,9 @@ def run0(genv, changes)
ty_env[param] = arg
end
end
mdecl.resolve_overloads(changes, genv, @node, ty_env, @a_args, @ret)
mdecl.resolve_overloads(changes, genv, @node, ty_env, @a_args, @ret) do |method_type|
@generics[method_type] ||= method_type.type_params.map {|var| Vertex.new(@node) }
end
end
elsif !me.defs.empty?
me.defs.each do |mdef|
Expand Down
8 changes: 7 additions & 1 deletion lib/typeprof/core/graph/change_set.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ def initialize(node, target)
@node = node
@target = target
@covariant_types = {}
@contravariant_types = {}
@edges = []
@new_edges = []
@boxes = {}
Expand Down Expand Up @@ -44,11 +45,16 @@ def copy_from(other)
other.diagnostics.clear
end

def new_vertex(genv, sig_type_node)
def new_covariant_vertex(genv, sig_type_node)
# This is used to avoid duplicated vertex generation for the same sig node
@covariant_types[sig_type_node] ||= Vertex.new(sig_type_node)
end

def new_contravariant_vertex(genv, sig_type_node)
# This is used to avoid duplicated vertex generation for the same sig node
@contravariant_types[sig_type_node] ||= Vertex.new(sig_type_node)
end

def add_edge(genv, src, dst)
raise src.class.to_s unless src.is_a?(BasicVertex)
src.add_edge(genv, dst) if !@edges.include?([src, dst]) && !@new_edges.include?([src, dst])
Expand Down
1 change: 1 addition & 0 deletions lib/typeprof/core/graph/vertex.rb
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ def initialize(origin)
when RBS::AST::Declarations::Base
when ValueEntity
when ActualArguments
when Array
else
raise "unknown class: #{ origin.class }"
end
Expand Down
12 changes: 12 additions & 0 deletions scenario/misc/ivar-stuck-case.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
## update: test.rbs
class Foo
def check: [T] (T) -> [T]
end

## update: test.rb
class Foo
def foo
@foo = []
@foo = check(@foo)
end
end

0 comments on commit 335fe6d

Please sign in to comment.