Skip to content

Commit

Permalink
improve compile-time method matching logic
Browse files Browse the repository at this point in the history
don't consider typevars unmatched if we can prove that they would be
matched by any actual call.

fixes #5575

slightly expand some array constructor signatures so `Type{<:Top}` matches
them, not just `Type{<:Any}`.
  • Loading branch information
JeffBezanson committed Jul 26, 2014
1 parent 3c129b7 commit 98a1165
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 4 deletions.
2 changes: 1 addition & 1 deletion base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ cell(dims::(Integer...)) = Array(Any, convert((Int...), dims))

for (fname, felt) in ((:zeros,:zero), (:ones,:one))
@eval begin
($fname){T}(::Type{T}, dims...) = fill!(Array(T, dims...), ($felt)(T))
($fname)(T::Type, dims...) = fill!(Array(T, dims...), ($felt)(T))
($fname)(dims...) = fill!(Array(Float64, dims...), ($felt)(Float64))
($fname){T}(A::AbstractArray{T}) = fill!(similar(A), ($felt)(T))
end
Expand Down
27 changes: 26 additions & 1 deletion src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -1580,6 +1580,28 @@ DLLEXPORT jl_tuple_t *jl_match_method(jl_value_t *type, jl_value_t *sig,
return result;
}

// Determine whether a typevar exists inside at most one DataType.
// These are the typevars that will always be matched by any matching
// arguments.
static int tvar_exists_at_top_level(jl_value_t *tv, jl_tuple_t *sig, int attop)
{
int i, l=jl_tuple_len(sig);
for(i=0; i < l; i++) {
jl_value_t *a = jl_tupleref(sig, i);
if (jl_is_vararg_type(a))
a = jl_tparam0(a);
if (a == tv)
return 1;
if (jl_is_tuple(a) && tvar_exists_at_top_level(tv, (jl_tuple_t*)a, attop))
return 1;
if (attop && jl_is_datatype(a)) {
if (tvar_exists_at_top_level(tv, ((jl_datatype_t*)a)->parameters, 0))
return 1;
}
}
return 0;
}

// returns a match as (argtypes, static_params, Method)
static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type,
jl_sym_t *name, int lim)
Expand Down Expand Up @@ -1641,7 +1663,10 @@ static jl_value_t *ml_matches(jl_methlist_t *ml, jl_value_t *type,
int matched_all_typevars = 1;
size_t l = jl_tuple_len(env);
for(i=1; i < l; i+=2) {
if (jl_is_typevar(jl_tupleref(env,i))) {
if (jl_is_typevar(jl_tupleref(env,i)) &&
// if tvar is at the top level it will definitely be matched.
// see issue #5575
!tvar_exists_at_top_level(jl_tupleref(env,i-1), ml->sig, 1)) {
matched_all_typevars = 0;
break;
}
Expand Down
3 changes: 1 addition & 2 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -3179,8 +3179,7 @@ void jl_init_types(void)

// Type{T}
jl_typetype_tvar = jl_new_typevar(jl_symbol("T"),
(jl_value_t*)jl_bottom_type,
jl_top_type);
(jl_value_t*)jl_bottom_type,jl_top_type);
jl_typetype_type = (jl_datatype_t*)jl_apply_type((jl_value_t*)jl_type_type,
jl_tuple(1,jl_typetype_tvar));

Expand Down

0 comments on commit 98a1165

Please sign in to comment.