Bug 21341 – [REG2.092] Wrong reference escape error when parameter is stored in this
Status
RESOLVED
Resolution
INVALID
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2020-10-25T12:58:34Z
Last change time
2023-05-09T20:59:36Z
Keywords
industry, rejects-valid, safe
Assigned to
No Owner
Creator
johanengelen
Comments
Comment #0 by johanengelen — 2020-10-25T12:58:34Z
```
struct A {
bool delegate() dlg;
}
struct Watcher {
bool b;
bool func() const { return b; }
}
struct S {
A[] watchers;
void registerWatcher(return ref Watcher watcher) {
watchers ~= A(&watcher.func); // line 13
}
}
S s;
Watcher watcher;
void foo()
{
s.registerWatcher(watcher);
}
```
Compile with `-w de` and it shows a wrong deprecation message:
<source>(13): Deprecation: copying `A(&watcher.func)` into allocated memory escapes a reference to parameter variable `watcher`
The `return` on parameter `watcher` means that the reference escapes to the `this` parameter. See spec 19.6.5.4.
Happens since dlang 2.092.
Comment #1 by johanengelen — 2020-10-25T13:05:24Z
Workaround: use explicit pointer parameter (`Watcher*`) instead of reference (`ref Watcher`).
Comment #2 by dkorpel — 2023-05-09T20:59:36Z
The code compiles now because the check is no longer performed in `@system` code, but the error comes back when you add `@safe:`.
However, the behavior is as intended, and comes down to the infamous 'scope is not transitive' limitation.
> The `return` on parameter `watcher` means that the reference escapes to the `this` parameter.
`scope` on `this` applies to the array (`watchers.ptr`), not any pointers in the array elements. Line 13 is equivalent to:
```D
this.watchers ~= [A(&watcher.func)];
```
And the problem isn't the `this.watchers ~=` part, but the `[A(&watcher.func)];` part putting it into a GC array literal (the 'allocated memory' that the error talks about)