The garbage collection specification (https://dlang.org/spec/garbage.html) mentions it's undefined behavior to have interior pointers in a struct:
> Do not have pointers in a struct instance that point back to the same instance.
> The trouble with this is if the instance gets moved in memory, the pointer will
> point back to where it came from, with likely disastrous results.
Undefined behavior is not allowed in `@safe` code, but creating an interior pointer is, which can break dip1000:
```
// compile with -preview=dip1000
@safe:
struct S {
int storage;
int* ptr;
this(int dummy) {
ptr = &storage;
}
int* get() return scope {
return ptr;
}
}
int* escape() {
S s = S(0);
return s.get; // escapes a pointer to stack variable `s`
}
```
Comment #1 by fw — 2022-02-13T11:03:49Z
I get an error for this with dmd as of commit 05a27e287e546e8553741fffccea0059f0c11f63:
t.d(8): Error: address of variable `this` assigned to `this` with longer lifetime
Comment #2 by dkorpel — 2022-02-13T11:22:19Z
(In reply to Florian Weimer from comment #1)
> I get an error for this with dmd as of commit
> 05a27e287e546e8553741fffccea0059f0c11f63:
>
> t.d(8): Error: address of variable `this` assigned to `this` with longer
> lifetime
I think this was fixed by https://github.com/dlang/dmd/pull/13577 then
Comment #3 by dkorpel — 2022-03-03T11:22:01Z
Re-opening, because:
- the error message makes no sense
- this is not yet tested for in the test suite
- hence, the accidental 'fix' will quietly be reverted when issue 22801 gets fixed
Comment #4 by bugzilla — 2022-08-15T15:48:08Z
The error message isn't great, but it is correctly identifying the problem.
ptr = &storage;
*is* taking the address of `this`, and assigning it to `this`.
As in`storage` is *(this+0), and `ptr` is *(this+8)
Comment #5 by dkorpel — 2022-08-15T17:18:51Z
(In reply to Walter Bright from comment #4)
> The error message isn't great, but it is correctly identifying the problem.
It's saying `this` has longer lifetime than `this`. Since when does `x > x` evaluate to true?
It also still works when you add `return scope` to the constructor:
```
@safe:
struct S {
int storage;
int* ptr;
this(int dummy) return scope {
ptr = &storage;
}
int* get() return scope {
return ptr;
}
}
int* escape() {
S s = S(0);
return s.get; // escapes a pointer to stack variable `s`
}
```
Comment #6 by dkorpel — 2022-08-15T17:22:53Z
(In reply to Dennis from comment #5)
> It's saying `this` has longer lifetime than `this`. Since when does `x > x`
> evaluate to true?
Nevermind, it says `this` has longer lifetime than "address of variable `this`", but, it should be in test suite and the modification with `return scope` needs to error.
Comment #7 by robert.schadek — 2024-12-13T19:19:20Z