Skip to content
Open
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
11 changes: 11 additions & 0 deletions compiler/src/dmd/func.d
Original file line number Diff line number Diff line change
Expand Up @@ -1534,6 +1534,17 @@
}
else
{
foreach (v; closureVars)
{
if (v.isRef() &&
(global.params.useDIP1000 == FeatureState.enabled && isSafe()))
{
error(loc, "%s `%s` cannot close over `ref` variable `%s`", kind, toPrettyChars, v.toChars());
if (global.gag) // need not report supplemental errors
return true;

Check warning on line 1544 in compiler/src/dmd/func.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/func.d#L1542-L1544

Added lines #L1542 - L1544 were not covered by tests
}
}

printGCUsage(loc, "using closure causes GC allocation");
return false;
}
Expand Down
7 changes: 4 additions & 3 deletions compiler/test/fail_compilation/test15544.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
REQUIRED_ARGS: -preview=dip1000
TEST_OUTPUT:
---
fail_compilation/test15544.d(20): Error: reference to local `this` assigned to non-scope `_del` in @safe code
fail_compilation/test15544.d(22): Error: reference to local `this` assigned to non-scope `_del` in @safe code
fail_compilation/test15544.d(21): Error: reference to local `this` assigned to non-scope `_del` in @safe code
fail_compilation/test15544.d(23): Error: reference to local `this` assigned to non-scope `_del` in @safe code
fail_compilation/test15544.d(18): Error: function `test15544.S.test` cannot close over `ref` variable `this`
---
*/

Expand All @@ -26,7 +27,7 @@ struct S {
/*
TEST_OUTPUT:
---
fail_compilation/test15544.d(46): Error: reference to local `y` assigned to non-scope `dg` in @safe code
fail_compilation/test15544.d(47): Error: reference to local `y` assigned to non-scope `dg` in @safe code
---
*/

Expand Down
5 changes: 3 additions & 2 deletions compiler/test/fail_compilation/test17423.d
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
/* REQUIRED_ARGS: -preview=dip1000
TEST_OUTPUT:
---
fail_compilation/test17423.d(27): Error: reference to local `this` assigned to non-scope parameter `dlg` calling `opApply`
fail_compilation/test17423.d(16): which is not `scope` because of `this.myDlg = dlg`
fail_compilation/test17423.d(28): Error: reference to local `this` assigned to non-scope parameter `dlg` calling `opApply`
fail_compilation/test17423.d(17): which is not `scope` because of `this.myDlg = dlg`
fail_compilation/test17423.d(27): Error: constructor `test17423.Foo.this` cannot close over `ref` variable `this`
---
*/

Expand Down
19 changes: 19 additions & 0 deletions compiler/test/fail_compilation/test20956.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/* REQUIRED_ARGS: -preview=dip1000
TEST_OUTPUT:
---
fail_compilation/test20956.d(105): Error: function `test20956.forwardDg` cannot close over `ref` variable `c`
---
*/

// https://issues.dlang.org/show_bug.cgi?id=20956

#line 100

@safe:

alias DG = void delegate() @safe;

DG forwardDg(ref int c)
{
return () {assert(c == 42);};
}
Comment on lines +16 to +19
Copy link
Member

Choose a reason for hiding this comment

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

Shouldn't the compiler infer the closure to be scope in this case ?
Regardless if it does/can infer it currently, we should not have this error for scope delegate, should we ?

Copy link
Member Author

Choose a reason for hiding this comment

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

ref parameters are implicitly pointers, and are automatically not allowed to escape the function. No need for scope.

The trouble here is the delegate escapes the function, thereby escaping the reference to c.

Copy link
Member

Choose a reason for hiding this comment

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

Right, we're returning the delegate. Can we add a test that not escaping the delegate (the delegate being scope) does not trigger error ?

Copy link
Member Author

Choose a reason for hiding this comment

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

The error is triggered when the delegate is tested to see if a dynamic closure is being created. So the tests for @nogc already do this.