Skip to content

Commit

Permalink
fix JuliaLang#3182, a subtle compile-time method matching bug
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson committed May 24, 2013
1 parent 4d87999 commit 2419758
Show file tree
Hide file tree
Showing 5 changed files with 30 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -883,7 +883,7 @@ JL_CALLABLE(jl_f_methodexists)
jl_check_type_tuple((jl_tuple_t*)args[1], jl_gf_name(args[0]),
"method_exists");
return jl_method_lookup_by_type(jl_gf_mtable(args[0]),
(jl_tuple_t*)args[1], 0) != jl_bottom_func ?
(jl_tuple_t*)args[1],0,0)!=jl_bottom_func ?
jl_true : jl_false;
}

Expand Down
2 changes: 1 addition & 1 deletion src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,7 @@ const jl_value_t *jl_dump_function(jl_function_t *f, jl_tuple_t *types)
return jl_cstr_to_string((char*)"");
jl_function_t *sf = jl_get_specialization(f, types);
if (sf == NULL || sf->linfo == NULL) {
sf = jl_method_lookup_by_type(jl_gf_mtable(f), types, 0);
sf = jl_method_lookup_by_type(jl_gf_mtable(f), types, 0, 0);
if (sf == jl_bottom_func)
return jl_cstr_to_string((char*)"");
JL_PRINTF(JL_STDERR,
Expand Down
22 changes: 15 additions & 7 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -907,7 +907,7 @@ static jl_value_t *lookup_match(jl_value_t *a, jl_value_t *b, jl_tuple_t **penv,
return ti;
}

static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, int cache)
static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, int cache, int inexact)
{
jl_methlist_t *m = mt->defs;
size_t nargs = jl_tuple_len(tt);
Expand All @@ -924,8 +924,16 @@ static jl_function_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_tuple_t *tt, in
// parametric methods only match if all typevars are matched by
// non-typevars.
for(i=1; i < jl_tuple_len(env); i+=2) {
if (jl_is_typevar(jl_tupleref(env,i)))
if (jl_is_typevar(jl_tupleref(env,i))) {
if (inexact) {
// "inexact" means the given type is compile-time,
// where a failure to determine the value of a
// static parameter is inconclusive.
// this is issue #3182, see test/core.jl
return jl_bottom_func;
}
break;
}
}
if (i >= jl_tuple_len(env))
break;
Expand Down Expand Up @@ -1270,11 +1278,11 @@ static jl_tuple_t *arg_type_tuple(jl_value_t **args, size_t nargs)
}

jl_function_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tuple_t *types,
int cache)
int cache, int inexact)
{
jl_function_t *sf = jl_method_table_assoc_exact_by_type(mt, types);
if (sf == jl_bottom_func) {
sf = jl_mt_assoc_by_type(mt, types, cache);
sf = jl_mt_assoc_by_type(mt, types, cache, inexact);
}
return sf;
}
Expand All @@ -1285,7 +1293,7 @@ jl_function_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t na
if (sf == jl_bottom_func) {
jl_tuple_t *tt = arg_type_tuple(args, nargs);
JL_GC_PUSH1(&tt);
sf = jl_mt_assoc_by_type(mt, tt, cache);
sf = jl_mt_assoc_by_type(mt, tt, cache, 0);
JL_GC_POP();
}
return sf;
Expand All @@ -1298,7 +1306,7 @@ jl_function_t *jl_get_specialization(jl_function_t *f, jl_tuple_t *types)
if (!jl_is_leaf_type((jl_value_t*)types))
return NULL;
jl_methtable_t *mt = jl_gf_mtable(f);
jl_function_t *sf = jl_method_lookup_by_type(mt, types, 1);
jl_function_t *sf = jl_method_lookup_by_type(mt, types, 1, 1);
if (sf == jl_bottom_func) {
return NULL;
}
Expand Down Expand Up @@ -1370,7 +1378,7 @@ JL_CALLABLE(jl_apply_generic)
else {
jl_tuple_t *tt = arg_type_tuple(args, nargs);
JL_GC_PUSH1(&tt);
mfunc = jl_mt_assoc_by_type(mt, tt, 1);
mfunc = jl_mt_assoc_by_type(mt, tt, 1, 0);
JL_GC_POP();
}

Expand Down
2 changes: 1 addition & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -975,7 +975,7 @@ void jl_type_infer(jl_lambda_info_t *li, jl_tuple_t *argtypes,
DLLEXPORT void jl_show_method_table(jl_value_t *outstr, jl_function_t *gf);
jl_lambda_info_t *jl_add_static_parameters(jl_lambda_info_t *l, jl_tuple_t *sp);
jl_function_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tuple_t *types,
int cache);
int cache, int inexact);
jl_function_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache);
jl_value_t *jl_gf_invoke(jl_function_t *gf, jl_tuple_t *types,
jl_value_t **args, size_t nargs);
Expand Down
12 changes: 12 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -789,3 +789,15 @@ end

@M2982.bad(T2982)
@test T2982.super === M2982.U

# issue #3182
f3182{T}(::Type{T}) = 0
f3182(x) = 1
function g3182(t::DataType)
# tricky thing here is that DataType is a concrete type, and a
# subtype of Type, but we cannot infer the T in Type{T} just
# by knowing (at compile time) that the argument is a DataType.
# however the ::Type{T} method should still match at run time.
f3182(t)
end
@test g3182(Complex) == 0

0 comments on commit 2419758

Please sign in to comment.