Skip to content

Commit af60baa

Browse files
committed
Throw error for an ambiguous call
1 parent a189156 commit af60baa

File tree

8 files changed

+106
-57
lines changed

8 files changed

+106
-57
lines changed

src/builtins.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -948,7 +948,8 @@ static void jl_check_type_tuple(jl_value_t *t, jl_sym_t *name, const char *ctx)
948948
JL_CALLABLE(jl_f_applicable)
949949
{
950950
JL_NARGSV(applicable, 1);
951-
return jl_method_lookup(jl_gf_mtable(args[0]), args, nargs, 1) != NULL ?
951+
jl_typemap_entry_t *entry;
952+
return jl_method_lookup(jl_gf_mtable(args[0]), args, nargs, 1, &entry) != NULL ?
952953
jl_true : jl_false;
953954
}
954955

src/codegen.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1096,12 +1096,14 @@ void *jl_get_llvmf(jl_tupletype_t *tt, bool getwrapper, bool getdeclarations)
10961096
if (tt != NULL) {
10971097
linfo = jl_get_specialization1(tt);
10981098
if (linfo == NULL) {
1099+
jl_typemap_entry_t *entry;
10991100
linfo = jl_method_lookup_by_type(
1100-
((jl_datatype_t*)jl_tparam0(tt))->name->mt, tt, 0, 0);
1101+
((jl_datatype_t*)jl_tparam0(tt))->name->mt, tt, 0, 0, &entry);
11011102
if (linfo == NULL) {
11021103
JL_GC_POP();
11031104
return NULL;
11041105
}
1106+
check_ambig_call(linfo->def, tt);
11051107
}
11061108
}
11071109
if (linfo == NULL) {

src/dump.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -841,6 +841,7 @@ static void jl_serialize_value_(ios_t *s, jl_value_t *v)
841841
write_int32(s, m->line);
842842
jl_serialize_value(s, (jl_value_t*)m->sig);
843843
jl_serialize_value(s, (jl_value_t*)m->tvars);
844+
jl_serialize_value(s, (jl_value_t*)m->ambig);
844845
write_int8(s, m->called);
845846
jl_serialize_value(s, (jl_value_t*)m->module);
846847
jl_serialize_value(s, (jl_value_t*)m->roots);
@@ -1444,6 +1445,8 @@ static jl_value_t *jl_deserialize_value_(ios_t *s, jl_value_t *vtag, jl_value_t
14441445
jl_gc_wb(m, m->sig);
14451446
m->tvars = (jl_svec_t*)jl_deserialize_value(s, (jl_value_t**)&m->tvars);
14461447
jl_gc_wb(m, m->tvars);
1448+
m->ambig = jl_deserialize_value(s, (jl_value_t**)&m->ambig);
1449+
jl_gc_wb(m, m->tvars);
14471450
m->called = read_int8(s);
14481451
m->module = (jl_module_t*)jl_deserialize_value(s, (jl_value_t**)&m->module);
14491452
jl_gc_wb(m, m->module);

src/gf.c

Lines changed: 76 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ jl_value_t *jl_mk_builtin_func(const char *name, jl_fptr_t fptr)
147147
li->def = jl_new_method_uninit();
148148
li->def->name = sname;
149149
li->def->lambda_template = li;
150+
li->def->ambig = jl_nothing;
150151
jl_methtable_t *mt = jl_gf_mtable(f);
151152
jl_typemap_insert(&mt->cache, (jl_value_t*)mt, jl_anytuple_type, jl_emptysvec, NULL, jl_emptysvec, (jl_value_t*)li, 0, &lambda_cache, NULL);
152153
return f;
@@ -681,26 +682,29 @@ static jl_lambda_info_t *cache_method(jl_methtable_t *mt, union jl_typemap_t *ca
681682
return newmeth;
682683
}
683684

684-
static jl_lambda_info_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *tt, int cache, int inexact)
685+
static jl_lambda_info_t *jl_mt_assoc_by_type(jl_methtable_t *mt, jl_datatype_t *tt, int cache, int inexact, jl_typemap_entry_t **entry)
685686
{
686-
jl_typemap_entry_t *m = NULL;
687+
*entry = NULL;
687688
jl_svec_t *env = jl_emptysvec;
688689
jl_method_t *func = NULL;
689690
jl_tupletype_t *sig = NULL;
690-
JL_GC_PUSH4(&env, &m, &func, &sig);
691+
JL_GC_PUSH4(&env, entry, &func, &sig);
691692

692-
m = jl_typemap_assoc_by_type(mt->defs, tt, &env, inexact, 1, 0);
693-
if (m == NULL) {
693+
*entry = jl_typemap_assoc_by_type(mt->defs, tt, &env, inexact, 1, 0);
694+
if (*entry == NULL) {
694695
JL_GC_POP();
695696
return NULL;
696697
}
697698

698-
sig = join_tsig(tt, m->sig);
699+
jl_method_t *m = (*entry)->func.method;
700+
sig = join_tsig(tt, (*entry)->sig);
699701
jl_lambda_info_t *nf;
700702
if (!cache)
701-
nf = jl_get_specialized(m->func.method, sig, env);
702-
else
703-
nf = cache_method(mt, &mt->cache, (jl_value_t*)mt, sig, tt, m, env);
703+
nf = jl_get_specialized(m, sig, env);
704+
else {
705+
check_ambig_call(m, tt); // if ambiguous, don't insert into cache
706+
nf = cache_method(mt, &mt->cache, (jl_value_t*)mt, sig, tt, *entry, env);
707+
}
704708
JL_GC_POP();
705709
return nf;
706710
}
@@ -959,34 +963,41 @@ jl_tupletype_t *arg_type_tuple(jl_value_t **args, size_t nargs)
959963
}
960964

961965
jl_lambda_info_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tupletype_t *types,
962-
int cache, int inexact)
966+
int cache, int inexact,
967+
jl_typemap_entry_t **entry)
963968
{
964-
jl_typemap_entry_t *m = jl_typemap_assoc_by_type(mt->cache, types, NULL, 0, 1, jl_cachearg_offset(mt));
969+
*entry = jl_typemap_assoc_by_type(mt->cache, types, NULL, 0, 1, jl_cachearg_offset(mt));
965970
jl_lambda_info_t *sf;
966-
if (m) {
967-
sf = m->func.linfo;
971+
if (*entry) {
972+
sf = (*entry)->func.linfo;
968973
}
969974
else {
970975
if (jl_is_leaf_type((jl_value_t*)types)) cache=1;
971-
sf = jl_mt_assoc_by_type(mt, types, cache, inexact);
976+
sf = jl_mt_assoc_by_type(mt, types, cache, inexact, entry);
972977
}
973978
return sf;
974979
}
975980

976981
JL_DLLEXPORT int jl_method_exists(jl_methtable_t *mt, jl_tupletype_t *types)
977982
{
978-
return jl_method_lookup_by_type(mt, types, 0, 0) != NULL;
983+
jl_typemap_entry_t *entry;
984+
return jl_method_lookup_by_type(mt, types, 0, 0, &entry) != NULL;
979985
}
980986

981-
jl_lambda_info_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache)
987+
jl_lambda_info_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache, jl_typemap_entry_t **entry)
982988
{
983-
jl_lambda_info_t *sf = jl_typemap_assoc_exact(mt->cache, args, nargs, jl_cachearg_offset(mt));
984-
if (sf == NULL) {
989+
jl_lambda_info_t *sf;
990+
*entry = jl_typemap_assoc_exact(mt->cache, args, nargs, jl_cachearg_offset(mt));
991+
if (*entry == NULL) {
985992
jl_tupletype_t *tt = arg_type_tuple(args, nargs);
986993
JL_GC_PUSH1(&tt);
987-
sf = jl_mt_assoc_by_type(mt, tt, cache, 0);
994+
sf = jl_mt_assoc_by_type(mt, tt, cache, 0, entry);
988995
JL_GC_POP();
989996
}
997+
else {
998+
sf = (*entry)->func.linfo;
999+
}
1000+
9901001
return sf;
9911002
}
9921003

@@ -1020,13 +1031,17 @@ jl_lambda_info_t *jl_get_specialization1(jl_tupletype_t *types)
10201031
// most of the time sf is rooted in mt, but if the method is staged it may
10211032
// not be the case
10221033
JL_GC_PUSH1(&sf);
1034+
jl_typemap_entry_t *entry;
10231035
JL_TRY {
1024-
sf = jl_method_lookup_by_type(mt, types, 1, 1);
1036+
sf = jl_method_lookup_by_type(mt, types, 1, 1, &entry);
10251037
} JL_CATCH {
10261038
goto not_found;
10271039
}
10281040
if (sf == NULL || sf->code == NULL || sf->inInference)
10291041
goto not_found;
1042+
jl_method_t *m = sf->def;
1043+
if (m->ambig != jl_nothing)
1044+
check_ambig_call(m, types);
10301045
if (sf->functionObjectsDecls.functionObject == NULL) {
10311046
if (sf->fptr != NULL)
10321047
goto not_found;
@@ -1044,6 +1059,19 @@ JL_DLLEXPORT void jl_compile_hint(jl_tupletype_t *types)
10441059
(void)jl_get_specialization1(types);
10451060
}
10461061

1062+
void check_ambig_call(jl_method_t *m, jl_tupletype_t *types)
1063+
{
1064+
if (m->ambig == jl_nothing)
1065+
return;
1066+
for (size_t i = 0; i < jl_array_len(m->ambig); i++) {
1067+
jl_method_t *mambig = (jl_method_t*)jl_cellref(m->ambig, i);
1068+
if (jl_type_intersection((jl_value_t*)mambig->sig,
1069+
(jl_value_t*)types) != (jl_value_t*)jl_bottom_type) {
1070+
jl_error("ambiguous");
1071+
}
1072+
}
1073+
}
1074+
10471075
// add type of `f` to front of argument tuple type
10481076
jl_tupletype_t *jl_argtype_with_function(jl_function_t *f, jl_tupletype_t *types)
10491077
{
@@ -1483,27 +1511,33 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs)
14831511
if no generic match, use the concrete one even if inexact
14841512
otherwise instantiate the generic method and use it
14851513
*/
1486-
jl_lambda_info_t *mfunc = jl_typemap_assoc_exact(mt->cache, args, nargs, jl_cachearg_offset(mt));
1487-
1514+
jl_typemap_entry_t *entry = jl_typemap_assoc_exact(mt->cache, args, nargs, jl_cachearg_offset(mt));
1515+
jl_lambda_info_t *mfunc = NULL;
14881516
jl_tupletype_t *tt = NULL;
1489-
if (mfunc == NULL) {
1517+
if (entry == NULL) {
14901518
// cache miss case
14911519
tt = arg_type_tuple(args, nargs);
14921520
// if running inference overwrites this particular method, it becomes
14931521
// unreachable from the method table, so root mfunc.
14941522
JL_GC_PUSH2(&tt, &mfunc);
1495-
mfunc = jl_mt_assoc_by_type(mt, tt, 1, 0);
1523+
mfunc = jl_mt_assoc_by_type(mt, tt, 1, 0, &entry);
14961524

14971525
if (mfunc == NULL) {
14981526
#ifdef JL_TRACE
14991527
if (error_en)
15001528
show_call(F, args, nargs);
15011529
#endif
15021530
JL_GC_POP();
1531+
jl_method_t *m = entry->func.method;
1532+
if (m->ambig != jl_nothing)
1533+
check_ambig_call(m, tt);
15031534
jl_no_method_error((jl_function_t*)F, args, nargs);
15041535
// unreachable
15051536
}
15061537
}
1538+
else {
1539+
mfunc = entry->func.linfo;
1540+
}
15071541
#ifdef JL_TRACE
15081542
if (traceen)
15091543
jl_printf(JL_STDOUT, " at %s:%d\n", jl_symbol_name(mfunc->file), mfunc->line);
@@ -1524,11 +1558,11 @@ JL_DLLEXPORT jl_value_t *jl_apply_generic(jl_value_t **args, uint32_t nargs)
15241558
JL_DLLEXPORT jl_value_t *jl_gf_invoke_lookup(jl_datatype_t *types)
15251559
{
15261560
jl_methtable_t *mt = ((jl_datatype_t*)jl_tparam0(types))->name->mt;
1527-
jl_typemap_entry_t *m = jl_typemap_assoc_by_type(mt->defs, types, /*don't record env*/NULL,
1561+
jl_typemap_entry_t *entry = jl_typemap_assoc_by_type(mt->defs, types, /*don't record env*/NULL,
15281562
/*exact match*/0, /*subtype*/1, /*offs*/0);
1529-
if (!m)
1563+
if (!entry)
15301564
return jl_nothing;
1531-
return (jl_value_t*)m;
1565+
return (jl_value_t*)entry;
15321566
}
15331567

15341568
// invoke()
@@ -1551,36 +1585,38 @@ jl_value_t *jl_gf_invoke(jl_tupletype_t *types0, jl_value_t **args, size_t nargs
15511585
jl_value_t *gf = args[0];
15521586
types = (jl_datatype_t*)jl_argtype_with_function(gf, (jl_tupletype_t*)types0);
15531587
jl_methtable_t *mt = jl_gf_mtable(gf);
1554-
jl_typemap_entry_t *m = (jl_typemap_entry_t*)jl_gf_invoke_lookup(types);
1588+
jl_typemap_entry_t *entry = (jl_typemap_entry_t*)jl_gf_invoke_lookup(types);
15551589

1556-
if ((jl_value_t*)m == jl_nothing) {
1590+
if ((jl_value_t*)entry == jl_nothing) {
15571591
jl_no_method_error_bare(gf, (jl_value_t*)types0);
15581592
// unreachable
15591593
}
15601594

15611595
// now we have found the matching definition.
15621596
// next look for or create a specialization of this definition.
15631597

1564-
jl_lambda_info_t *mfunc;
1565-
if (m->func.method->invokes.unknown == NULL)
1566-
mfunc = NULL;
1567-
else
1568-
mfunc = jl_typemap_assoc_exact(m->func.method->invokes, args, nargs, jl_cachearg_offset(mt));
1569-
if (mfunc == NULL) {
1598+
jl_lambda_info_t *mfunc = NULL;
1599+
jl_typemap_entry_t *tm = NULL;
1600+
if (entry->func.method->invokes.unknown != NULL)
1601+
tm = jl_typemap_assoc_exact(entry->func.method->invokes, args, nargs, jl_cachearg_offset(mt));
1602+
if (tm == NULL) {
15701603
tt = arg_type_tuple(args, nargs);
1571-
if (m->tvars != jl_emptysvec) {
1604+
if (entry->tvars != jl_emptysvec) {
15721605
jl_value_t *ti =
1573-
jl_lookup_match((jl_value_t*)tt, (jl_value_t*)m->sig, &tpenv, m->tvars);
1606+
jl_lookup_match((jl_value_t*)tt, (jl_value_t*)entry->sig, &tpenv, entry->tvars);
15741607
assert(ti != (jl_value_t*)jl_bottom_type);
15751608
(void)ti;
15761609
}
1577-
sig = join_tsig(tt, m->sig);
1578-
jl_method_t *func = m->func.method;
1610+
sig = join_tsig(tt, entry->sig);
1611+
jl_method_t *func = entry->func.method;
15791612

15801613
if (func->invokes.unknown == NULL)
15811614
func->invokes.unknown = jl_nothing;
15821615

1583-
mfunc = cache_method(mt, &m->func.method->invokes, m->func.value, sig, tt, m, tpenv);
1616+
mfunc = cache_method(mt, &func->invokes, entry->func.value, sig, tt, entry, tpenv);
1617+
}
1618+
else {
1619+
mfunc = tm->func.linfo;
15841620
}
15851621
JL_GC_POP();
15861622
if (mfunc->inInference || mfunc->inCompile) {

src/julia_internal.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,9 +214,11 @@ void jl_lambda_info_set_ast(jl_lambda_info_t *li, jl_value_t *ast);
214214

215215
jl_lambda_info_t *jl_get_unspecialized(jl_lambda_info_t *method);
216216
jl_lambda_info_t *jl_method_lookup_by_type(jl_methtable_t *mt, jl_tupletype_t *types,
217-
int cache, int inexact);
218-
jl_lambda_info_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache);
217+
int cache, int inexact,
218+
jl_typemap_entry_t **entry);
219+
jl_lambda_info_t *jl_method_lookup(jl_methtable_t *mt, jl_value_t **args, size_t nargs, int cache, jl_typemap_entry_t **entry);
219220
jl_value_t *jl_gf_invoke(jl_tupletype_t *types, jl_value_t **args, size_t nargs);
221+
void check_ambig_call(jl_method_t *m, jl_tupletype_t *types);
220222

221223
jl_array_t *jl_lam_args(jl_expr_t *l);
222224
jl_array_t *jl_lam_vinfo(jl_expr_t *l);
@@ -562,7 +564,7 @@ jl_typemap_entry_t *jl_typemap_insert(union jl_typemap_t *cache, jl_value_t *par
562564

563565
jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_tupletype_t *types, jl_svec_t **penv,
564566
int8_t subtype_inexact__sigseq_useenv, int8_t subtype, int8_t offs);
565-
jl_lambda_info_t *jl_typemap_assoc_exact(union jl_typemap_t ml_or_cache, jl_value_t **args, size_t n, int8_t offs);
567+
jl_typemap_entry_t *jl_typemap_assoc_exact(union jl_typemap_t ml_or_cache, jl_value_t **args, size_t n, int8_t offs);
566568

567569
typedef int (*jl_typemap_visitor_fptr)(jl_typemap_entry_t *l, void *closure);
568570
int jl_typemap_visitor(union jl_typemap_t a, jl_typemap_visitor_fptr fptr, void *closure);

src/typemap.c

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ jl_typemap_entry_t *jl_typemap_assoc_by_type(union jl_typemap_t ml_or_cache, jl_
623623
jl_typemap_lookup_by_type_(ml, types, subtype_inexact__sigseq_useenv);
624624
}
625625

626-
jl_lambda_info_t *jl_typemap_assoc_exact(union jl_typemap_t ml_or_cache, jl_value_t **args, size_t n, int8_t offs)
626+
jl_typemap_entry_t *jl_typemap_assoc_exact(union jl_typemap_t ml_or_cache, jl_value_t **args, size_t n, int8_t offs)
627627
{
628628
// NOTE: This function is a huge performance hot spot!!
629629
jl_typemap_entry_t *ml;
@@ -635,9 +635,9 @@ jl_lambda_info_t *jl_typemap_assoc_exact(union jl_typemap_t ml_or_cache, jl_valu
635635
assert(jl_is_datatype(ty));
636636
if (ty == (jl_value_t*)jl_datatype_type && cache->targ != (void*)jl_nothing) {
637637
ml_or_cache = mtcache_hash_lookup(cache->targ, a1, 1, offs);
638-
jl_lambda_info_t *li = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1);
639-
if (li)
640-
return li;
638+
ml = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1);
639+
if (ml)
640+
return ml;
641641
}
642642
if (cache->arg1 != (void*)jl_nothing) {
643643
ml_or_cache = mtcache_hash_lookup(cache->arg1, ty, 0, offs);
@@ -647,7 +647,7 @@ jl_lambda_info_t *jl_typemap_assoc_exact(union jl_typemap_t ml_or_cache, jl_valu
647647
jl_value_t *t0 = (jl_value_t*)jl_typeof(a0);
648648
if (ml_or_cache.leaf->next==(void*)jl_nothing && n==2 && jl_datatype_nfields(ml_or_cache.leaf->sig)==2 &&
649649
jl_tparam(ml_or_cache.leaf->sig, 1 - offs) == t0)
650-
return ml_or_cache.leaf->func.linfo;
650+
return ml_or_cache.leaf;
651651
if (n==3) {
652652
// some manually-unrolled common special cases
653653
jl_value_t *a2 = args[2];
@@ -656,18 +656,18 @@ jl_lambda_info_t *jl_typemap_assoc_exact(union jl_typemap_t ml_or_cache, jl_valu
656656
if (jl_datatype_nfields(mn->sig)==3 &&
657657
jl_tparam(mn->sig,1-offs)==t0 &&
658658
jl_tparam(mn->sig,2)==(jl_value_t*)jl_typeof(a2))
659-
return mn->func.linfo;
659+
return mn;
660660
mn = mn->next;
661661
if (mn!=(void*)jl_nothing && jl_datatype_nfields(mn->sig)==3 &&
662662
jl_tparam(mn->sig,1-offs)==t0 &&
663663
jl_tparam(mn->sig,2)==(jl_value_t*)jl_typeof(a2))
664-
return mn->func.linfo;
664+
return mn;
665665
}
666666
}
667667
}
668-
jl_lambda_info_t *li = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1);
669-
if (li)
670-
return li;
668+
ml = jl_typemap_assoc_exact(ml_or_cache, args, n, offs+1);
669+
if (ml)
670+
return ml;
671671
}
672672
}
673673
ml = cache->linear;
@@ -701,7 +701,7 @@ jl_lambda_info_t *jl_typemap_assoc_exact(union jl_typemap_t ml_or_cache, jl_valu
701701
}
702702
}
703703
if (i == l)
704-
return ml->func.linfo;
704+
return ml;
705705
}
706706
}
707707
ml = ml->next;

test/ambiguous.jl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,9 @@ for m in mt
2222
@test sort(aln) == atarget
2323
end
2424
end
25+
26+
@test foo("hi", "there") == 1
27+
@test foo(3.1, 3.2) == 5
28+
@test foo(3, 4) == 4
29+
@test_throws ErrorException foo(0x03, 4)
30+
@test_throws ErrorException foo(0x03, 4) # test that not inserted into cache

test/misc.jl

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,6 @@ func4union(::Union{Type4Union,Int}) = ()
130130
let
131131
redir_err = "redirect_stderr(STDOUT)"
132132
exename = Base.julia_cmd()
133-
134133
script = "$redir_err; module A; f() = 1; end; A.f() = 1"
135134
warning_str = readstring(`$exename -f -e $script`)
136135
@test contains(warning_str, "f()")

0 commit comments

Comments
 (0)