Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue 14846 - Insufficient context deduction with implicit nested lambda #4848

Merged
merged 1 commit into from Aug 7, 2015
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/declaration.c
Expand Up @@ -51,6 +51,8 @@ bool checkFrameAccess(Loc loc, Scope *sc, AggregateDeclaration *ad, size_t iStar
{
if (!fd->isThis() && !fd->isNested())
break;
if (FuncLiteralDeclaration *fld = fd->isFuncLiteralDeclaration())
fld->tok = TOKdelegate;
Copy link
Member

Choose a reason for hiding this comment

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

checkFrameAccess is supposed to be a pure function, merely checking things. But here it is now modifying global state. There's got to be a better way. I do note that checkNestedReference does it, too, so there's an excuse for it. I hope that when we switch to ddmd, we can migrate to a better design.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Or, the problem is in the function name - checkSomething VS checkAndFixSomething.

}
if (AggregateDeclaration *ad2 = s->isAggregateDeclaration())
{
Expand Down
15 changes: 11 additions & 4 deletions src/expression.c
Expand Up @@ -4385,9 +4385,6 @@ Expression *StructLiteralExp::semantic(Scope *sc)
if (!sd->fit(loc, sc, elements, stype))
return new ErrorExp();

if (checkFrameAccess(loc, sc, sd, elements->dim))
return new ErrorExp();

/* Fill out remainder of elements[] with default initializers for fields[]
*/
if (!sd->fill(loc, elements, false))
Expand All @@ -4399,6 +4396,10 @@ Expression *StructLiteralExp::semantic(Scope *sc)
global.increaseErrorCount();
return new ErrorExp();
}

if (checkFrameAccess(loc, sc, sd, elements->dim))
return new ErrorExp();

type = stype ? stype : sd->type;
return this;
}
Expand Down Expand Up @@ -5070,14 +5071,18 @@ Expression *NewExp::semantic(Scope *sc)

member = f->isCtorDeclaration();
assert(member);

if (checkFrameAccess(loc, sc, sd, sd->fields.dim))
return new ErrorExp();
}
else
{
if (!sd->fit(loc, sc, arguments, tb))
return new ErrorExp();

if (!sd->fill(loc, arguments, false))
return new ErrorExp();
if (checkFrameAccess(loc, sc, sd, arguments ? arguments->dim : 0))
return new ErrorExp();
}

type = type->pointerTo();
Expand Down Expand Up @@ -8447,6 +8452,8 @@ Expression *CallExp::semantic(Scope *sc)
StructLiteralExp *sle = new StructLiteralExp(loc, sd, NULL, e1->type);
if (!sd->fill(loc, sle->elements, true))
return new ErrorExp();
if (checkFrameAccess(loc, sc, sd, sle->elements->dim))
return new ErrorExp();
// Bugzilla 14556: Set concrete type to avoid further redundant semantic().
sle->type = e1->type;

Expand Down
31 changes: 31 additions & 0 deletions test/runnable/nested.d
Expand Up @@ -2455,6 +2455,36 @@ void test14398()
assert(outer == 42); // inner is copied successfully
}

/*******************************************/
// 14846

void foo14846(Dg)(scope Dg code)
{
static assert(is(Dg == delegate));
code();
}

void test14846()
{
int x;

struct S
{
this(int n) { x = n; }
~this() { x = 99; }
}

foo14846({ S s; });
foo14846({ S s = S(); });
foo14846({ S s = S(1); });
foo14846({ S[3] s; });

foo14846({ S* p = new S(); });
foo14846({ S* p = new S(1); });
foo14846({ S[] a = [S()]; });
foo14846({ S[] a = [S(1)]; });
}

/*******************************************/

int main()
Expand Down Expand Up @@ -2546,6 +2576,7 @@ int main()
test12234();
test13861();
test14398();
test14846();

printf("Success\n");
return 0;
Expand Down