Consider the following example:
-----
// REQUIRED_ARGS: -preview=dip1000 -preview=dip1021
struct A
{
void* p;
@safe nothrow pure void f();
}
@safe nothrow pure void g(ref A);
@safe void e(ref scope A a)
{
a.f(); // (1)
g(a); // (2)
}
-----
Call (1) fails to compile with:
scope variable `a` calling non-scope member function `A.f()`
despite A.f being nothrow pure.
Call (2) succeeds to compile because nothrow pure implies scope on the argument to g.
This discrepancy requires explicitly annotating non-static nothrow pure struct methods as scope.
Comment #1 by dkorpel — 2024-05-30T13:50:42Z
I think both calls should fail to compile, because they can escape through self-assignment:
```D
struct A
{
A* p;
@safe nothrow pure void f()
{
this.p.p = p;
}
}
@trusted nothrow pure void g(ref A a)
{
a.p.p = a.p;
}
@safe void e(ref scope A a)
{
a.f(); // (1)
g(a); // (2)
}
```
Comment #2 by zopsicle — 2024-05-30T13:53:23Z
Adding const would mitigate that, but still does not infer scope on f:
-----
struct A
{
void* p;
@safe nothrow pure void f() const;
}
@safe nothrow pure void g(ref const(A));
@safe void e(ref scope const(A) a)
{
a.f();
g(a);
}
-----
Comment #3 by robert.schadek — 2024-12-13T19:35:30Z