[Issue 19183] DIP1000 defeated if auto used instead of scope in variable declaration with template this member function
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Thu Aug 23 11:29:39 UTC 2018
https://issues.dlang.org/show_bug.cgi?id=19183
--- Comment #15 from ag0aep6g <ag0aep6g at gmail.com> ---
(In reply to Atila Neves from comment #13)
> > Apparently, DMD goes with infinite
>
> Only if it's a template this function.
No. My statement was about the lifetime of `malloc(...)`, which is called in
the constructor. The constructor doesn't have a template this parameter.
Your code has a template this parameter on the method `ptr`. But before `ptr`
comes into play, the lifetime of the field has already been set to infinite.
If we initialize the field to something with restricted lifetime, then leaking
`s.ptr` gets rejected as it should be:
----
const(int)* gInts;
void main() @safe
{
int x;
auto s = MyStruct(&x);
gInts = s.ptr; /* Error: scope variable s assigned to gInts with longer
lifetime */
}
struct MyStruct
{
int* ints;
scope ptr(this This)() { return ints; }
}
----
The problem is that `ints` starts out with infinite lifetime when it's
initialized with a `malloc` call. `ptr` just passes the wrong lifetime on.
Also, if anything, it's the inference of the `return` attribute that's the
problem. The template this parameter merely triggers that. Empty template
parentheses or an `auto` return type have the same effect.
> As mentioned before, writing out the
> explicit instantitations for mutable, const and immutable doesn't compile.
[...]
> dmd is already doing the right thing with `scope ptr() { return ints; }`,
> `scope ptr() const { return ints; }` and `scope ptr() immutable { return
> ints; }` even if it's `auto s = MyStruct(10)` instead of `scope s =
> MyStruct(10)`.
As mentioned before, I can't reproduce this. Please post complete code.
With those definitions for `ptr` I get this code:
----
@safe:
const(int)* gInts;
void main() {
auto s = MyStruct(10);
gInts = s.ptr;
}
struct MyStruct
{
import core.stdc.stdlib;
int* ints;
this(int size) @trusted { ints = cast(int*) malloc(size); }
~this() { () @trusted { free(ints); }(); }
scope ptr() { return ints; }
scope ptr() const { return ints; }
scope ptr() immutable { return ints; }
}
----
And that compiles just fine. Because the `return` attribute is still inferred.
> It's only if `ptr` is a template this function this bug manifests. There's
> also a bug with `inout`, but that's another issue:
>
> https://issues.dlang.org/show_bug.cgi?id=17927
Yes, that's another issue. The method there doesn't have the `return`
attribute.
Maybe your point is that the `return` attribute shouldn't be inferred? Then
`ptr` wouldn't compile, but you could still make essentially the same mistake
by accessing `s.ints` directly.
> I didn't bother to respond to the rest of your analysis. The crux of the
> problem here is the interaction of a template function with DIP1000 and
> inferred lifetimes, and how it differs from the non-template functions.
My point is that changing the lifetime of `malloc(...)` could maybe fix this
issue and prevent the very similar mistake of copying `s.ints`, while still
allowing the `return` attribute to be inferred.
--
More information about the Digitalmars-d-bugs
mailing list