cat > main.d << EOF
void main() @safe
{
struct ThrowingElement
{
int i;
~this()
{
assert(1);
}
}
ThrowingElement[int] aa;
aa[0] = ThrowingElement(0);
}
EOF
(resubmission of the example of #18592 as I do believe that the compiler should
Comment #1 by greensunny12 — 2018-03-27T21:02:44Z
Argh I accidentally hit submit.
The reason for the resubmission is that the following code compiles fine already:
cat > main.d << EOF
void main() @safe
{
struct Foo
{
int i;
~this() // <- no need to annotate with @safe explicitly here
{
assert(1);
}
void m(){} // <- no need to annotate with @safe explicitly here
}
Foo foo;
foo.m();
}
EOF
So DMD already does transitively apply @safe, but apparently if it generated for associative arrays this generation doesn't work in all cases.
Comment #2 by ag0aep6g — 2018-03-27T21:22:16Z
(In reply to Seb from comment #1)
> So DMD already does transitively apply @safe, but apparently if it generated
> for associative arrays this generation doesn't work in all cases.
It's not the associative array. It's just that the generated opAssign isn't @safe (for no reason):
----
void main() @safe
{
struct ThrowingElement
{
~this() {}
}
ThrowingElement aa;
/* Accepted. The destructor is apparently inferred as @safe. */
aa = aa;
/* Error: @safe function D main cannot call @system generated
function onlineapp.main.ThrowingElement.opAssign */
}
----
Comment #3 by razvan.nitu1305 — 2018-03-29T14:52:12Z
(In reply to ag0aep6g from comment #2)
> (In reply to Seb from comment #1)
> > So DMD already does transitively apply @safe, but apparently if it generated
> > for associative arrays this generation doesn't work in all cases.
>
> It's not the associative array. It's just that the generated opAssign isn't
> @safe (for no reason):
>
> ----
> void main() @safe
> {
> struct ThrowingElement
> {
> ~this() {}
> }
>
> ThrowingElement aa;
> /* Accepted. The destructor is apparently inferred as @safe. */
> aa = aa;
> /* Error: @safe function D main cannot call @system generated
> function onlineapp.main.ThrowingElement.opAssign */
> }
> ----
That's because the generated opAssign is not @safe. Look at [1] : it injects a pointer which is void initialized, after that the function is inferred to be @system. I tried replacing the void initializer with null, or with a new ExpInitializer(loc, new ThisExp(loc)). That solves the current test case, but ends up failing other tests (for reasons unknown)
[1] https://github.com/dlang/dmd/blob/master/src/dmd/clone.d#L273
Comment #4 by greensunny12 — 2018-04-02T22:44:46Z
@RazvanN how about setting the opAssign to @trusted instead when we now that the dtor is @safe?
The problem is that sd.dtor.isSafe() returns 0 :/
Maybe we need to go through semantic first before looking at this?
Also there seems to be an existing check for this already - it just doesn't get triggered
```
stc = mergeFuncAttrs(stc, sd.dtor);
if (stc & STC.safe)
```
Well at least the high-level isSafe traits infers the safety correctly:
https://run.dlang.io/is/6ePqDY
Comment #5 by razvan.nitu1305 — 2018-08-23T16:56:57Z