The following code compile successfully with DIP1000 enabled: struct Foo() { int* bar; int* foo() @safe return { return bar; } } int* a; void main() @safe { Foo!() f; a = f.foo; } But if `Foo` is not a template it fails to compile, complaining that the return value of `foo` outlives `f`. I think there are two errors here: 1. `Foo` as a template and as a non-template struct behaves differently 2. I think the above code is actually valid because it's not provable that `foo` escapes a pointer to the internal state of `Foo`
> 2. I think the above code is actually valid because it's not provable that `foo` escapes a pointer to the internal state of `Foo` It's not valid because foo() is defined as returning a pointer that is equivalent to foo()'s `this` pointer. Then, `a = f.foo;` is treated as assigning the address of `f` to `a`, a global, which is an error. The compiler is behaving correctly for this point.
(In reply to Walter Bright from comment #1) > > 2. I think the above code is actually valid because it's not provable that `foo` escapes a pointer to the internal state of `Foo` > > It's not valid because foo() is defined as returning a pointer that is > equivalent to foo()'s `this` pointer. Then, `a = f.foo;` is treated as > assigning the address of `f` to `a`, a global, which is an error. The > compiler is behaving correctly for this point. So it doesn't matter if "foo" is returning something else, like a global variable?
> 1. `Foo` as a template and as a non-template struct behaves differently What's happening is that when `Foo` is a template, then inference happens with `foo()`, which infers that `this.bar` is being returned, not `this`. You can verify this by removing the function body for `foo()` so inference cannot happen, and then the error appears, because without inference the `return` applies to `this`, not `this.bar`. Not a bug.
> So it doesn't matter if "foo" is returning something else, like a global variable? If inference is not happening, then the compiler believes you when you say it is returning the `this` pointer. This is a feature, not a bug, as it enables you to attach the checking to the `this` pointer.
(In reply to Walter Bright from comment #3) > > 1. `Foo` as a template and as a non-template struct behaves differently > > What's happening is that when `Foo` is a template, then inference happens > with `foo()`, which infers that `this.bar` is being returned, not `this`. > You can verify this by removing the function body for `foo()` so inference > cannot happen, and then the error appears, because without inference the > `return` applies to `this`, not `this.bar`. > > Not a bug. Is it possible to somehow get the behavior I want? To make sure that some internal state of "f" cannot outlive "f" itself.
(In reply to Walter Bright from comment #3) > > 1. `Foo` as a template and as a non-template struct behaves differently > > What's happening is that when `Foo` is a template, then inference happens > with `foo()`, which infers that `this.bar` is being returned, not `this`. > You can verify this by removing the function body for `foo()` so inference > cannot happen, and then the error appears, because without inference the > `return` applies to `this`, not `this.bar`. > > Not a bug. But is it possible to get what I want somehow? To make sure no internal state of "f" outlives "f" itself.
That's what @live is for.