From be0c9d0a6135abb172f69fe2056033c3f0a87801 Mon Sep 17 00:00:00 2001 From: Walter Bright Date: Fri, 12 Aug 2022 00:18:30 -0700 Subject: [PATCH] fix Issue 20956 - [DIP1000] @safe defeated by closure capturing ref parameter --- compiler/src/dmd/func.d | 11 +++++++++++ compiler/test/fail_compilation/test15544.d | 7 ++++--- compiler/test/fail_compilation/test17423.d | 5 +++-- compiler/test/fail_compilation/test20956.d | 19 +++++++++++++++++++ 4 files changed, 37 insertions(+), 5 deletions(-) create mode 100644 compiler/test/fail_compilation/test20956.d diff --git a/compiler/src/dmd/func.d b/compiler/src/dmd/func.d index e39849e467a4..34f30d6e8739 100644 --- a/compiler/src/dmd/func.d +++ b/compiler/src/dmd/func.d @@ -1534,6 +1534,17 @@ extern (C++) class FuncDeclaration : Declaration } else { + foreach (v; closureVars) + { + if (v.isRef() && + (global.params.useDIP1000 == FeatureState.enabled && isSafe())) + { + error("cannot close over `ref` variable `%s`", v.toChars()); + if (global.gag) // need not report supplemental errors + return true; + } + } + printGCUsage(loc, "using closure causes GC allocation"); return false; } diff --git a/compiler/test/fail_compilation/test15544.d b/compiler/test/fail_compilation/test15544.d index 91ac675c9595..613783a5528f 100644 --- a/compiler/test/fail_compilation/test15544.d +++ b/compiler/test/fail_compilation/test15544.d @@ -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` --- */ @@ -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 --- */ diff --git a/compiler/test/fail_compilation/test17423.d b/compiler/test/fail_compilation/test17423.d index faa98063e65f..a0017728c058 100644 --- a/compiler/test/fail_compilation/test17423.d +++ b/compiler/test/fail_compilation/test17423.d @@ -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` --- */ diff --git a/compiler/test/fail_compilation/test20956.d b/compiler/test/fail_compilation/test20956.d new file mode 100644 index 000000000000..e6ba41aef0fb --- /dev/null +++ b/compiler/test/fail_compilation/test20956.d @@ -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);}; +}