Skip to content

Commit

Permalink
Merge pull request #1096 from 9rnsr/fix8504
Browse files Browse the repository at this point in the history
Issue 8504 - Template attribute inferrence doesn't work
  • Loading branch information
MartinNowak committed Jan 22, 2013
2 parents b426356 + 406ad56 commit 6344a72
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/delegatize.c
Expand Up @@ -37,6 +37,7 @@ Expression *Expression::toDelegate(Scope *sc, Type *t)
Type *tw = t->semantic(loc, sc);
Type *tc = t->substWildTo(MODconst)->semantic(loc, sc);
TypeFunction *tf = new TypeFunction(NULL, tc, 0, LINKd);
if (tw != tc) tf->mod = MODwild; // hack for bug7757
(tf = (TypeFunction *)tf->semantic(loc, sc))->next = tw; // hack for bug7757
FuncLiteralDeclaration *fld =
new FuncLiteralDeclaration(loc, loc, tf, TOKdelegate, NULL);
Expand Down
18 changes: 15 additions & 3 deletions src/func.c
Expand Up @@ -1197,7 +1197,7 @@ void FuncDeclaration::semantic3(Scope *sc)
{ // If no return type inferred yet, then infer a void
if (!type->nextOf())
{
((TypeFunction *)type)->next = Type::tvoid;
f->next = Type::tvoid;
//type = type->semantic(loc, sc); // Removed with 6902
}
else if (returns && f->next->ty != Tvoid)
Expand Down Expand Up @@ -1338,7 +1338,10 @@ void FuncDeclaration::semantic3(Scope *sc)
if (f->isnothrow && (global.errors != nothrowErrors) )
error("'%s' is nothrow yet may throw", toChars());
if (flags & FUNCFLAGnothrowInprocess)
{
if (type == f) f = f->copy();
f->isnothrow = !(blockexit & BEthrow);
}

int offend = blockexit & BEfallthru;
#endif
Expand Down Expand Up @@ -1683,19 +1686,28 @@ void FuncDeclaration::semantic3(Scope *sc)
if (flags & FUNCFLAGpurityInprocess)
{
flags &= ~FUNCFLAGpurityInprocess;
if (type == f) f = f->copy();
f->purity = PUREfwdref;
}

if (flags & FUNCFLAGsafetyInprocess)
{
flags &= ~FUNCFLAGsafetyInprocess;
if (type == f) f = f->copy();
f->trust = TRUSTsafe;
}

// reset deco to apply inference result to mangled name
if (f != type)
f->deco = NULL;

// Do semantic type AFTER pure/nothrow inference.
if (inferRetType)
if (!f->deco)
{
type = type->semantic(loc, sc);
sc = sc->push();
sc->linkage = linkage; // Bugzilla 8496
type = f->semantic(loc, sc);
sc = sc->pop();
}

if (global.gag && global.errors != nerrors)
Expand Down
10 changes: 8 additions & 2 deletions src/mtype.c
Expand Up @@ -5103,6 +5103,13 @@ const char *TypeFunction::kind()
return "function";
}

TypeFunction *TypeFunction::copy()
{
TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
memcpy(tf, this, sizeof(TypeFunction));
return tf;
}

Type *TypeFunction::syntaxCopy()
{
Type *treturn = next ? next->syntaxCopy() : NULL;
Expand Down Expand Up @@ -5538,8 +5545,7 @@ Type *TypeFunction::semantic(Loc loc, Scope *sc)
* This can produce redundant copies if inferring return type,
* as semantic() will get called again on this.
*/
TypeFunction *tf = (TypeFunction *)mem.malloc(sizeof(TypeFunction));
memcpy(tf, this, sizeof(TypeFunction));
TypeFunction *tf = copy();
if (parameters)
{ tf->parameters = (Parameters *)parameters->copy();
for (size_t i = 0; i < parameters->dim; i++)
Expand Down
1 change: 1 addition & 0 deletions src/mtype.h
Expand Up @@ -652,6 +652,7 @@ struct TypeFunction : TypeNext

TypeFunction(Parameters *parameters, Type *treturn, int varargs, enum LINK linkage, StorageClass stc = 0);
const char *kind();
TypeFunction *copy();
Type *syntaxCopy();
Type *semantic(Loc loc, Scope *sc);
void purityLevel();
Expand Down
30 changes: 30 additions & 0 deletions test/compilable/testInference.d
Expand Up @@ -159,6 +159,36 @@ pure string escapeShellArguments()
return escapeShellArgument!allocator();
}

/***************************************************/
// 8504

void foo8504()()
{
static assert(typeof(foo8504!()).stringof == "void()");
static assert(typeof(foo8504!()).mangleof == "FZv");
static assert(foo8504!().mangleof == "_D13testInference12__T7foo8504Z7foo8504FZv");
}

auto toDelegate8504a(F)(auto ref F fp) { return fp; }
F toDelegate8504b(F)(auto ref F fp) { return fp; }

extern(C) void testC8504() {}

void test8504()
{
static assert(typeof(foo8504!()).stringof == "pure nothrow @safe void()");
static assert(typeof(foo8504!()).mangleof == "FNaNbNfZv");
static assert(foo8504!().mangleof == "_D13testInference12__T7foo8504Z7foo8504FNaNbNfZv");

auto fp1 = toDelegate8504a(&testC8504);
auto fp2 = toDelegate8504b(&testC8504);
static assert(is(typeof(fp1) == typeof(fp2)));
static assert(typeof(fp1).stringof == "extern (C) void function()");
static assert(typeof(fp2).stringof == "extern (C) void function()");
static assert(typeof(fp1).mangleof == "PUZv");
static assert(typeof(fp2).mangleof == "PUZv");
}

/***************************************************/
// 8751

Expand Down
2 changes: 1 addition & 1 deletion test/runnable/funclit.d
Expand Up @@ -586,7 +586,7 @@ void test8198()
return f => x => f(n(f)(x));
}

auto n = &zero!uint;
uint delegate(uint) delegate(uint delegate(uint)) n = &zero!uint;
foreach (i; 0..10)
{
assert(n(x => x + 1)(0) == i);
Expand Down

0 comments on commit 6344a72

Please sign in to comment.