Skip to content

Commit

Permalink
improve handling of TypeConstructor Types in the generic function cac…
Browse files Browse the repository at this point in the history
…he. fixes #11840

when TypeConstructors showed up as parameters of Type objects in the generic function cache,
the type intersection result would trick inference into caching it in the wrong place
and using it when it didn't apply. fix that by checking explicitly for arguments declared
with ::TypeConstructor and ensuring they are matched and cached correctly
  • Loading branch information
vtjnash committed Aug 25, 2015
1 parent 6ae7707 commit 139f888
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 9 deletions.
6 changes: 2 additions & 4 deletions examples/typetree.jl
Original file line number Diff line number Diff line change
Expand Up @@ -80,11 +80,9 @@ end
# examine all symbols in module and store those that are types
function store_all_from(m::Module)
for expr = names(m,true)
try
t = eval(m,expr)
if isdefined(m,expr)
t = getfield(m, expr)
isa(t, Type) && store_type(string(expr), t)
#catch ex
# println("Error adding ", string(expr), m, " (", ex, ")")
end
end
end
Expand Down
33 changes: 28 additions & 5 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,26 @@ static int cache_match_by_type(jl_value_t **types, size_t n, jl_tupletype_t *sig
}
}
jl_value_t *a = types[i];
if (jl_is_datatype(a) && jl_is_datatype(decl) &&
((jl_datatype_t*)decl)->name == jl_type_type->name &&
((jl_datatype_t*)a )->name == jl_type_type->name) {
if (jl_is_type_type(a) && jl_is_type_type(decl)) {
jl_value_t *tp0 = jl_tparam0(decl);
if (tp0 == (jl_value_t*)jl_typetype_tvar) {
// in the case of Type{T}, the types don't have
// to match exactly either. this is cached as Type{T}.
// analogous to the situation with tuples.
}
else {
if (!jl_types_equal(jl_tparam0(a), tp0))
return 0;
jl_value_t *a0 = jl_tparam0(a);
if (jl_is_typector(a0)) {
// in the case where a is exactly a
// Type{::TypeConstructor}, tp0 must be exactly
// Type{TypeConstructor}
if (tp0 != (jl_value_t*)jl_typector_type)
return 0;
}
else {
if (!jl_types_equal(a0, tp0))
return 0;
}
}
}
else if (decl == (jl_value_t*)jl_any_type) {
Expand Down Expand Up @@ -134,6 +142,13 @@ static inline int cache_match(jl_value_t **args, size_t n, jl_tupletype_t *sig,
// to match exactly either. this is cached as Type{T}.
// analogous to the situation with tuples.
}
else if (jl_is_typector(a)) {
// in the case where a is exactly a
// TypeConstructor, tp0 must be exactly
// Type{TypeConstructor}
if (tp0 != (jl_value_t*)jl_typector_type)
return 0;
}
else {
if (a!=tp0 && !jl_types_equal(a,tp0))
return 0;
Expand Down Expand Up @@ -553,6 +568,14 @@ static jl_function_t *cache_method(jl_methtable_t *mt, jl_tupletype_t *type,
need_guard_entries = 1;
assert(jl_svecref(newparams,i) != (jl_value_t*)jl_bottom_type);
}
else if (jl_is_type_type(elt) && jl_is_typector(jl_tparam0(elt)) &&
decl_i == (jl_value_t*)jl_typector_type) {
// TypeConstructors are problematic because they can be alternate
// representations of any type. If we matched this method because
// it matched the leaf type TypeConstructor, then don't
// cache something different since that doesn't necessarily actually apply
jl_svecset(newparams, i, jl_typector_type);
}
else if (jl_is_type_type(elt) && very_general_type(decl_i) &&
!jl_has_typevars(decl_i)) {
/*
Expand Down

0 comments on commit 139f888

Please sign in to comment.