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)