[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
Wed Aug 22 19:39:13 UTC 2018


https://issues.dlang.org/show_bug.cgi?id=19183

--- Comment #12 from ag0aep6g <ag0aep6g at gmail.com> ---
(In reply to Atila Neves from comment #11)
> > You're still just copying an `int*` around, which isn't unsafe.
> 
> Of course it is, that's basically the whole point of Rust and DIP1000.

You're right. Of course DIP 1000 is about restricting how pointers can be
copied around. I was completely wrong here. Didn't really think in DIP 1000
terms. Sorry for the noise.


[...]
> From DIP1000:
> 
> "For all global and static variables, lifetime is infinite."
> "For values allocated on the garbage collected heap, lifetime is infinite
> whilst reachability is dependent on the references in the program bound to
> those values."
> 
> Algebra of lifetimes lists "*e", "new", "e[i]", "ArrayLiteral" and
> "ArrayLiteral[constant]" as the only expressions with infinite lifetime.
> 
> And again:
> 
> "A variable is inferred to be scope if it is initialized with a value that
> has a non-∞ lifetime."
> 
> 
> Therefore, since `auto s = MyStruct(10)` doesn't match any of the above
> conditions for an infinite lifetime, `auto` or `scope` should be the same
> thing.

DIP 1000 on `null`: "lifetime(null) is infinite". `null` is an instance of a
global, I guess.

On function calls, it says that the lifetime of the result is defined in the
"section dedicated to discussing functions". Unfortunately, that section
doesn't mention "lifetime" even once, and I find it rather hard to figure out
what the lifetime of a function call is supposed to be when the function body
isn't available for analysis.

So if we leave the pointer as `null`, it has infinite lifetime. And it's okay
to copy it around. This is what happens in all the posted snippets that don't
have a `malloc` call.

For `malloc(...)` it's not clear to me what the lifetime is supposed to be.
Apparently, DMD goes with infinite. The consequence is that the `free` call
always comes as a surprise to the compiler. I.e., calling `free` always breaks
the @trusted promise, and @safe becomes unreliable. The best we can do with
this is using an @trusted `free` anyway and containing the fallout.

What if `malloc(...)` had a zero lifetime instead? Then any access to a field
initialized from it would have to be @trusted, because its lifetime would
always be considered over. Since @safe code wouldn't be able to even look at
the field, @safe might stay reliable. I'm not sure if this could work out.

I suppose the goal is to somehow get access to the field with proper lifetime
(i.e. tied to the struct instance, if the destructor `free`s). With the current
implementation we might do it like this:

----
--- main.d
import the_ugly;
void* global;
void main() @safe
{
    auto s = S(1);
    int* local = s.p;
    static assert(!__traits(compiles, global = s.p));
}
--- the_ugly.d
struct S
{
    private int* p_;
    int* p() return @safe
    {
        return p_;
    }
    this(int n) @trusted
    {
        import core.stdc.stdlib: malloc;
        p_ = cast(int*) malloc(int.sizeof);
    }
    ~this() @trusted
    {
        import core.stdc.stdlib: free;
        free(p_);
    }
}
----

The problem is of course that the whole module the_ugly must be verified
manually. @safe and attribute inference cannot be relied upon. That's brittle.

Could a method like `p` be written if DMD chose a zero lifetime for
`malloc(...)` instead of an infinite one? If so, that might be nice. `p` would
probably have to be @trusted, but @safe and attribute inference could be relied
upon for other methods and `p_` wouldn't even have to be private.


> > I'm not sure if I understand that correctly, but this compiles just fine:
> 
> I'm arguing it shouldn't.

You said it "doesn't compile". Or more precisely: You described some code that
"doesn't compile" and I couldn't reproduce it from the description. If the code
you thought of is different from the snippet I pieced together, maybe show it
if it's interesting.

--


More information about the Digitalmars-d-bugs mailing list