Skip to content

Commit fc29dfe

Browse files
committed
show failing clauses in template constraint match attempts
1 parent 081a4df commit fc29dfe

5 files changed

Lines changed: 154 additions & 54 deletions

File tree

src/dmd/cond.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -855,7 +855,7 @@ extern (C++) final class StaticIfCondition : Condition
855855

856856
import dmd.staticcond;
857857
bool errors;
858-
bool result = evalStaticCondition(sc, exp, exp, errors);
858+
bool result = evalStaticCondition(sc, exp, exp, errors).result;
859859

860860
// Prevent repeated condition evaluation.
861861
// See: fail_compilation/fail7815.d

src/dmd/dtemplate.d

Lines changed: 53 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -684,10 +684,11 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
684684
return protection;
685685
}
686686

687+
import dmd.staticcond;
687688
/****************************
688689
* Check to see if constraint is satisfied.
689690
*/
690-
extern (D) bool evaluateConstraint(TemplateInstance ti, Scope* sc, Scope* paramscope, Objects* dedargs, FuncDeclaration fd)
691+
extern (D) StaticConditionResult evaluateConstraint(TemplateInstance ti, Scope* sc, Scope* paramscope, Objects* dedargs, FuncDeclaration fd)
691692
{
692693
/* Detect recursive attempts to instantiate this template declaration,
693694
* https://issues.dlang.org/show_bug.cgi?id=4072
@@ -713,7 +714,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
713714
for (Scope* scx = sc; scx; scx = scx.enclosing)
714715
{
715716
if (scx == p.sc)
716-
return false;
717+
return new StaticConditionResult(null, false, false);
717718
}
718719
}
719720
/* BUG: should also check for ref param differences
@@ -788,13 +789,13 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
788789
ti.inst = ti; // temporary instantiation to enable genIdent()
789790
scx.flags |= SCOPE.constraint;
790791
bool errors;
791-
bool result = evalStaticCondition(scx, constraint, e, errors);
792+
auto result = evalStaticCondition(scx, constraint, e, errors);
792793
ti.inst = null;
793794
ti.symtab = null;
794795
scx = scx.pop();
795796
previous = pr.prev; // unlink from threaded list
796797
if (errors)
797-
return false;
798+
return new StaticConditionResult(null, false, false);
798799
return result;
799800
}
800801

@@ -833,7 +834,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
833834
* dedtypes deduced arguments
834835
* Return match level.
835836
*/
836-
extern (D) MATCH matchWithInstance(Scope* sc, TemplateInstance ti, Objects* dedtypes, Expressions* fargs, int flag)
837+
extern (D) MatchWithSupplementalInformation matchWithInstance(Scope* sc, TemplateInstance ti, Objects* dedtypes, Expressions* fargs, int flag)
837838
{
838839
enum LOGM = 0;
839840
static if (LOGM)
@@ -848,11 +849,12 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
848849
}
849850
MATCH m;
850851
size_t dedtypes_dim = dedtypes.dim;
852+
StaticConditionResult supplementalInformation;
851853

852854
dedtypes.zero();
853855

854856
if (errors)
855-
return MATCH.nomatch;
857+
return MatchWithSupplementalInformation(MATCH.nomatch);
856858

857859
size_t parameters_dim = parameters.dim;
858860
int variadic = isVariadic() !is null;
@@ -864,7 +866,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
864866
{
865867
printf(" no match: more arguments than parameters\n");
866868
}
867-
return MATCH.nomatch;
869+
return MatchWithSupplementalInformation(MATCH.nomatch);
868870
}
869871

870872
assert(dedtypes_dim == parameters_dim);
@@ -970,7 +972,8 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
970972
}
971973

972974
// TODO: dedtypes => ti.tiargs ?
973-
if (!evaluateConstraint(ti, sc, paramscope, dedtypes, fd))
975+
supplementalInformation = evaluateConstraint(ti, sc, paramscope, dedtypes, fd);
976+
if (!supplementalInformation.result)
974977
goto Lnomatch;
975978
}
976979

@@ -1016,7 +1019,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
10161019
{
10171020
printf("-TemplateDeclaration.matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m);
10181021
}
1019-
return m;
1022+
return MatchWithSupplementalInformation(m);
10201023
}
10211024

10221025
/********************************************
@@ -1025,7 +1028,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
10251028
* match this is at least as specialized as td2
10261029
* 0 td2 is more specialized than this
10271030
*/
1028-
MATCH leastAsSpecialized(Scope* sc, TemplateDeclaration td2, Expressions* fargs)
1031+
MatchWithSupplementalInformation leastAsSpecialized(Scope* sc, TemplateDeclaration td2, Expressions* fargs)
10291032
{
10301033
enum LOG_LEASTAS = 0;
10311034
static if (LOG_LEASTAS)
@@ -1061,8 +1064,8 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
10611064
Objects dedtypes = Objects(td2.parameters.dim);
10621065

10631066
// Attempt a type deduction
1064-
MATCH m = td2.matchWithInstance(sc, ti, &dedtypes, fargs, 1);
1065-
if (m > MATCH.nomatch)
1067+
auto m = td2.matchWithInstance(sc, ti, &dedtypes, fargs, 1);
1068+
if (m.match > MATCH.nomatch)
10661069
{
10671070
/* A non-variadic template is more specialized than a
10681071
* variadic one.
@@ -1082,7 +1085,12 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
10821085
{
10831086
printf(" doesn't match, so is not as specialized\n");
10841087
}
1085-
return MATCH.nomatch;
1088+
return MatchWithSupplementalInformation(MATCH.nomatch);
1089+
}
1090+
1091+
struct MatchWithSupplementalInformation {
1092+
MATCH match;
1093+
StaticConditionResult supplementalInformation;
10861094
}
10871095

10881096
/*************************************************
@@ -1101,13 +1109,14 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
11011109
* bit 0-3 Match template parameters by inferred template arguments
11021110
* bit 4-7 Match template parameters by initial template arguments
11031111
*/
1104-
extern (D) MATCH deduceFunctionTemplateMatch(TemplateInstance ti, Scope* sc, ref FuncDeclaration fd, Type tthis, Expressions* fargs)
1112+
extern (D) MatchWithSupplementalInformation deduceFunctionTemplateMatch(TemplateInstance ti, Scope* sc, ref FuncDeclaration fd, Type tthis, Expressions* fargs)
11051113
{
11061114
size_t nfparams;
11071115
size_t nfargs;
11081116
size_t ntargs; // array size of tiargs
11091117
size_t fptupindex = IDX_NOTFOUND;
11101118
MATCH match = MATCH.exact;
1119+
StaticConditionResult supplementalInformation;
11111120
MATCH matchTiargs = MATCH.exact;
11121121
ParameterList fparameters; // function parameter list
11131122
VarArg fvarargs; // function varargs
@@ -1142,7 +1151,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
11421151
dedtypes.zero();
11431152

11441153
if (errors || fd.errors)
1145-
return MATCH.nomatch;
1154+
return MatchWithSupplementalInformation(MATCH.nomatch);
11461155

11471156
// Set up scope for parameters
11481157
Scope* paramscope = scopeForTemplateParameters(ti,sc);
@@ -2003,8 +2012,11 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
20032012

20042013
if (constraint)
20052014
{
2006-
if (!evaluateConstraint(ti, sc, paramscope, dedargs, fd))
2015+
supplementalInformation = evaluateConstraint(ti, sc, paramscope, dedargs, fd);
2016+
if (!supplementalInformation.result)
2017+
{
20072018
goto Lnomatch;
2019+
}
20082020
}
20092021

20102022
version (none)
@@ -2018,18 +2030,18 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
20182030

20192031
paramscope.pop();
20202032
//printf("\tmatch %d\n", match);
2021-
return cast(MATCH)(match | (matchTiargs << 4));
2033+
return MatchWithSupplementalInformation(cast(MATCH)(match | (matchTiargs << 4)));
20222034

20232035
Lnomatch:
20242036
paramscope.pop();
20252037
//printf("\tnomatch\n");
2026-
return MATCH.nomatch;
2038+
return MatchWithSupplementalInformation(MATCH.nomatch, supplementalInformation);
20272039

20282040
Lerror:
20292041
// todo: for the future improvement
20302042
paramscope.pop();
20312043
//printf("\terror\n");
2032-
return MATCH.nomatch;
2044+
return MatchWithSupplementalInformation(MATCH.nomatch);
20332045
}
20342046

20352047
/**************************************************
@@ -2592,10 +2604,14 @@ void functionResolve(Match* m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiar
25922604
auto ti = new TemplateInstance(loc, td, tiargs);
25932605
Objects dedtypes = Objects(td.parameters.dim);
25942606
assert(td.semanticRun != PASS.init);
2595-
MATCH mta = td.matchWithInstance(sc, ti, &dedtypes, fargs, 0);
2607+
auto mta = td.matchWithInstance(sc, ti, &dedtypes, fargs, 0);
25962608
//printf("matchWithInstance = %d\n", mta);
2597-
if (mta <= MATCH.nomatch || mta < ta_last) // no match or less match
2609+
if (mta.match <= MATCH.nomatch || mta.match < ta_last) // no match or less match
2610+
{
2611+
if(pMessage && mta.supplementalInformation)
2612+
*pMessage = mta.supplementalInformation.toChars();
25982613
return 0;
2614+
}
25992615

26002616
ti.templateInstanceSemantic(sc, fargs);
26012617
if (!ti.inst) // if template failed to expand
@@ -2665,8 +2681,8 @@ void functionResolve(Match* m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiar
26652681
if (mfa < m.last)
26662682
return 0;
26672683

2668-
if (mta < ta_last) goto Ltd_best2;
2669-
if (mta > ta_last) goto Ltd2;
2684+
if (mta.match < ta_last) goto Ltd_best2;
2685+
if (mta.match > ta_last) goto Ltd2;
26702686

26712687
if (mfa < m.last) goto Ltd_best2;
26722688
if (mfa > m.last) goto Ltd2;
@@ -2686,7 +2702,7 @@ void functionResolve(Match* m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiar
26862702
td_best = td;
26872703
ti_best = null;
26882704
property = 0; // (backward compatibility)
2689-
ta_last = mta;
2705+
ta_last = mta.match;
26902706
m.last = mfa;
26912707
m.lastf = fd;
26922708
tthis_best = tthis_fd;
@@ -2708,12 +2724,17 @@ void functionResolve(Match* m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiar
27082724
ti.parent = td.parent; // Maybe calculating valid 'enclosing' is unnecessary.
27092725

27102726
auto fd = f;
2711-
int x = td.deduceFunctionTemplateMatch(ti, sc, fd, tthis, fargs);
2727+
auto information = td.deduceFunctionTemplateMatch(ti, sc, fd, tthis, fargs);
2728+
int x = information.match;
27122729
MATCH mta = cast(MATCH)(x >> 4);
27132730
MATCH mfa = cast(MATCH)(x & 0xF);
27142731
//printf("match:t/f = %d/%d\n", mta, mfa);
27152732
if (!fd || mfa == MATCH.nomatch)
2733+
{
2734+
if(pMessage && information.supplementalInformation)
2735+
*pMessage = information.supplementalInformation.toChars();
27162736
continue;
2737+
}
27172738

27182739
Type tthis_fd = fd.needThis() ? tthis : null;
27192740

@@ -2743,8 +2764,8 @@ void functionResolve(Match* m, Dsymbol dstart, Loc loc, Scope* sc, Objects* tiar
27432764
if (td_best)
27442765
{
27452766
// Disambiguate by picking the most specialized TemplateDeclaration
2746-
MATCH c1 = td.leastAsSpecialized(sc, td_best, fargs);
2747-
MATCH c2 = td_best.leastAsSpecialized(sc, td, fargs);
2767+
MATCH c1 = td.leastAsSpecialized(sc, td_best, fargs).match;
2768+
MATCH c2 = td_best.leastAsSpecialized(sc, td, fargs).match;
27482769
//printf("1: c1 = %d, c2 = %d\n", c1, c2);
27492770
if (c1 > c2) goto Ltd;
27502771
if (c1 < c2) goto Ltd_best;
@@ -6897,7 +6918,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
68976918
assert(tempdecl._scope);
68986919
// Deduce tdtypes
68996920
tdtypes.setDim(tempdecl.parameters.dim);
6900-
if (!tempdecl.matchWithInstance(sc, this, &tdtypes, fargs, 2))
6921+
if (!tempdecl.matchWithInstance(sc, this, &tdtypes, fargs, 2).match)
69016922
{
69026923
error("incompatible arguments for template instantiation");
69036924
return false;
@@ -6952,7 +6973,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
69526973
dedtypes.zero();
69536974
assert(td.semanticRun != PASS.init);
69546975

6955-
MATCH m = td.matchWithInstance(sc, this, &dedtypes, fargs, 0);
6976+
MATCH m = td.matchWithInstance(sc, this, &dedtypes, fargs, 0).match;
69566977
//printf("matchWithInstance = %d\n", m);
69576978
if (m <= MATCH.nomatch) // no match at all
69586979
return 0;
@@ -6961,8 +6982,8 @@ extern (C++) class TemplateInstance : ScopeDsymbol
69616982

69626983
// Disambiguate by picking the most specialized TemplateDeclaration
69636984
{
6964-
MATCH c1 = td.leastAsSpecialized(sc, td_best, fargs);
6965-
MATCH c2 = td_best.leastAsSpecialized(sc, td, fargs);
6985+
MATCH c1 = td.leastAsSpecialized(sc, td_best, fargs).match;
6986+
MATCH c2 = td_best.leastAsSpecialized(sc, td, fargs).match;
69666987
//printf("c1 = %d, c2 = %d\n", c1, c2);
69676988
if (c1 > c2) goto Ltd;
69686989
if (c1 < c2) goto Ltd_best;
@@ -7182,7 +7203,7 @@ extern (C++) class TemplateInstance : ScopeDsymbol
71827203
return 1;
71837204
}
71847205
}
7185-
MATCH m = td.matchWithInstance(sc, this, &dedtypes, null, 0);
7206+
MATCH m = td.matchWithInstance(sc, this, &dedtypes, null, 0).match;
71867207
if (m <= MATCH.nomatch)
71877208
return 0;
71887209
}

src/dmd/func.d

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2718,7 +2718,8 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
27182718

27192719
Match m;
27202720
m.last = MATCH.nomatch;
2721-
functionResolve(&m, s, loc, sc, tiargs, tthis, fargs, null);
2721+
const(char)* supplementalInformation;
2722+
functionResolve(&m, s, loc, sc, tiargs, tthis, fargs, &supplementalInformation);
27222723
auto orig_s = s;
27232724

27242725
if (m.last > MATCH.nomatch && m.lastf)
@@ -2777,6 +2778,9 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
27772778
tiargsBuf.peekString(), fargsBuf.peekString());
27782779

27792780
printCandidates(loc, td);
2781+
2782+
if(supplementalInformation)
2783+
.errorSupplemental(loc, "%s", supplementalInformation);
27802784
}
27812785
else if (od)
27822786
{

src/dmd/semantic2.d

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ private extern(C++) final class Semantic2Visitor : Visitor
101101

102102
import dmd.staticcond;
103103
bool errors;
104-
bool result = evalStaticCondition(sc, sa.exp, sa.exp, errors);
104+
bool result = evalStaticCondition(sc, sa.exp, sa.exp, errors).result;
105105
sc = sc.pop();
106106
if (errors)
107107
{

0 commit comments

Comments
 (0)