Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/dmd/dtemplate.d
Original file line number Diff line number Diff line change
Expand Up @@ -689,6 +689,12 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
*/
extern (D) bool evaluateConstraint(TemplateInstance ti, Scope* sc, Scope* paramscope, Objects* dedargs, FuncDeclaration fd)
{
// circular evaluation of the constraint, see https://issues.dlang.org/show_bug.cgi?id=11856
if (constraint.inuse == constraint.inuse.max)
return false;
constraint.inuse++;
scope(exit)
constraint.inuse--;
/* Detect recursive attempts to instantiate this template declaration,
* https://issues.dlang.org/show_bug.cgi?id=4072
* void foo(T)(T x) if (is(typeof(foo(x)))) { }
Expand Down
1 change: 1 addition & 0 deletions src/dmd/expression.d
Original file line number Diff line number Diff line change
Expand Up @@ -642,6 +642,7 @@ extern (C++) abstract class Expression : ASTNode
ubyte parens; // if this is a parenthesized expression
Type type; // !=null means that semantic() has been run
Loc loc; // file location
ubyte inuse; // detect expressionSemantic() loops
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please open a PR to update the .h file.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

damn again... yes coming soon


extern (D) this(const ref Loc loc, TOK op, int size)
{
Expand Down
6 changes: 6 additions & 0 deletions src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -11094,6 +11094,12 @@ Expression binSemanticProp(BinExp e, Scope* sc)
// entrypoint for semantic ExpressionSemanticVisitor
extern (C++) Expression expressionSemantic(Expression e, Scope* sc)
{
const inConstraint = sc ? (sc.flags & SCOPE.constraint) == SCOPE.constraint : false;
if (e.inuse == 2 && inConstraint)
{
e.error("circular evaluation of constraint `%s`", e.toChars());
return new ErrorExp();
}
scope v = new ExpressionSemanticVisitor(sc);
e.accept(v);
return v.result;
Expand Down
3 changes: 3 additions & 0 deletions src/dmd/traits.d
Original file line number Diff line number Diff line change
Expand Up @@ -1533,9 +1533,12 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
}
if (ex)
{
const bool inConstraint = (sc2.flags & SCOPE.constraint) == SCOPE.constraint;
ex.inuse += inConstraint;
ex = ex.expressionSemantic(sc2);
ex = resolvePropertiesOnly(sc2, ex);
ex = ex.optimize(WANTvalue);
ex.inuse -= inConstraint;
if (sc2.func && sc2.func.type.ty == Tfunction)
{
const tf = cast(TypeFunction)sc2.func.type;
Expand Down
16 changes: 16 additions & 0 deletions test/fail_compilation/ice11856_0.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice11856_0.d(16): Error: template `ice11856_0.f` cannot deduce function from argument types `!()(int)`, candidates are:
fail_compilation/ice11856_0.d(10): `ice11856_0.f(T)(T t) if (!__traits(compiles, .f!T))`
fail_compilation/ice11856_0.d(13): `ice11856_0.f(T)(T t) if (!__traits(compiles, .f!T))`
---
*/

int f(T)(T t) if(!__traits(compiles,.f!T)) {
return 0;
}
int f(T)(T t) if(!__traits(compiles,.f!T)) {
return 1;
}
enum x=f(2);
13 changes: 13 additions & 0 deletions test/fail_compilation/ice11856_1.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
TEST_OUTPUT:
---
fail_compilation/ice11856_1.d(13): Error: template `ice11856_1.g` cannot deduce function from argument types `!()(A)`, candidates are:
fail_compilation/ice11856_1.d(11): `ice11856_1.g(T)(T x) if (is(typeof(x.f())))`
---
*/
struct A {}

void f(T)(T x) if (is(typeof(x.g()))) {}
void g(T)(T x) if (is(typeof(x.f()))) {}

void main() { A().g(); }