From fc1752604c5cc740eae4ed6bc98d21a3f2e40fdd 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/test20956.d | 19 +++++++++++++++++++ 3 files changed, 34 insertions(+), 3 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 4c0947415cd1..27f4d60d8b64 100644 --- a/compiler/src/dmd/func.d +++ b/compiler/src/dmd/func.d @@ -2197,6 +2197,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/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);}; +}