Jump to page: 1 2
Thread overview
[Issue 17284] opDispatch allows bypassing @safe on unions
[Issue 17284] std.experimental.typecons.Final allows bypassing @safe on unions
Mar 29, 2017
ZombineDev
[Issue 17284] ref returning function template allows bypassing @safe on unions
Mar 29, 2017
ZombineDev
Mar 29, 2017
ZombineDev
[Issue 17284] Template function attribute inference wrongly infers @safe for accessing overlapping pointer fields in unions
Mar 29, 2017
ZombineDev
Jan 20, 2018
Carsten Blüggel
Mar 04, 2018
Walter Bright
March 29, 2017
https://issues.dlang.org/show_bug.cgi?id=17284

hsteoh@quickfur.ath.cx changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |safe
           Severity|enhancement                 |normal

--
March 29, 2017
https://issues.dlang.org/show_bug.cgi?id=17284

ZombineDev <petar.p.kirov@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |petar.p.kirov@gmail.com
          Component|phobos                      |dmd
           Hardware|x86_64                      |All
            Summary|std.experimental.typecons.F |opDispatch allows bypassing
                   |inal allows bypassing @safe |@safe on unions
                   |on unions                   |
                 OS|Linux                       |All
           Severity|normal                      |major

--- Comment #1 from ZombineDev <petar.p.kirov@gmail.com> ---
The issue has little to do with std.experimental.typecons.Final. Final just
uses std.typecons.Proxy. I added an assert(0) on line 5585 in std.typecons from
dmd 2.073.2 and got this:
$ ./main
core.exception.AssertError@/home/zlx/dlang/dmd-2.073.2/linux/bin64/../../src/phobos/std/typecons.d(5585):
Assertion failure
----------------
??:? _d_assert [0x4296e4]
??:? pure nothrow ref @property @nogc return @safe int
std.experimental.typecons.Final!(main.U).Final.__mixin8.opDispatch!("i").opDispatch!(std.experimental.typecons.Final!(main.U).Final).opDispatch()
[0x428684]
??:? _Dmain [0x42845b]
??:? _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFZv [0x429c9f]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int
function(char[][])*).tryExec(scope void delegate()) [0x429bc7]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int
function(char[][])*).runAll() [0x429c44]
??:? void rt.dmain2._d_run_main(int, char**, extern (C) int
function(char[][])*).tryExec(scope void delegate()) [0x429bc7]
??:? _d_run_main [0x429b33]
??:? main [0x42871f]
??:? __libc_start_main [0x4b801f44]
(dmd-2.073.2)/mnt/d/tmp_code/final_safe

This issue can easily be reproduced with the following code:
class C { }
union U {
    C c;
    int i;
}

struct S(T)
{
    private T value__;

    @property auto ref opDispatch(string name)()
    {
        return mixin("value__." ~ name);
    }
}

void main() @safe {
    S!U u;
    u.c = new C; // compiles (!!!)
    u.i++;       // uh-oh
}

Therefore I'm changing the component to dmd.

--
March 29, 2017
https://issues.dlang.org/show_bug.cgi?id=17284

ZombineDev <petar.p.kirov@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|opDispatch allows bypassing |ref returning function
                   |@safe on unions             |template allows bypassing
                   |                            |@safe on unions

--- Comment #2 from ZombineDev <petar.p.kirov@gmail.com> ---
I reduced it a bit further:

Case 1:

```
class C { }
union U {
    C c;
    int i;
}

ref C getC1(ref U u) { return u.c; }
ref C getC2(T)(ref T u) { return u.c; }

void main() @safe {
    U u;
    u.getC2() = new C; // compiles (!!!)
}
```

Case 2:

```
class C { }
union U {
    C c;
    int i;
}

ref C getC1(ref U u) { return u.c; }
ref C getC2(T)(ref T u) { return u.c; }

void main() @safe {
    U u;
    u.getC1() = new C; // (Line 12) Doesn't compile
}
```

main.d(12): Error: @safe function 'D main' cannot call @system function
'main.getC1'

Case 3:

```
class C { }
union U {
    C c;
    int i;
}

@safe:

ref C getC1(ref U u) { return u.c; }     // (Line 9)
ref C getC2(T)(ref T u) { return u.c; }

void main() @safe {
    U u;
    u.getC1() = new C;
}
```
main.d(9): Error: field U.c cannot access pointers in @safe code that overlap
other fields

Case 4:

```
class C { }
union U {
    C c;
    int i;
}

@safe:

ref C getC1(ref U u) { return u.c; }      // (Line 9)
ref C getC2(T)(ref T u) { return u.c; }   // (Line 10)

void main() @safe {
    U u;
    u.getC2() = new C;                    // (Line 14)
}
```

main.d(9): Error: field U.c cannot access pointers in @safe code that overlap
other fields
                                          main.d(10): Error: field U.c cannot
access pointers in @safe code that overlap other fields

    main.d(14): Error: template instance main.getC2!(U) error instantiating

--
March 29, 2017
https://issues.dlang.org/show_bug.cgi?id=17284

--- Comment #3 from ZombineDev <petar.p.kirov@gmail.com> ---
So it seems that the bug has to do with the @safe-ty inference on template functions, since the code does not compile if the function template is explicitly marked with @safe.

--
March 29, 2017
https://issues.dlang.org/show_bug.cgi?id=17284

--- Comment #4 from hsteoh@quickfur.ath.cx ---
Interesting.  So it would appear that the problem is caused by attribute inference wrongly inferring @safe for a template function that returns an overlapping pointer field.

I.e.:

----
class C { }
union U { C c; int i; }
ref C func(T)(ref T t) { return t.c; }

pragma(msg, typeof(func!U));
----

Compiler output:
----
pure nothrow @nogc ref @safe C(return ref U t)
----

The correct inferred type should be:
----
pure nothrow @nogc ref @system C(return ref U t)
----

--
March 29, 2017
https://issues.dlang.org/show_bug.cgi?id=17284

hsteoh@quickfur.ath.cx changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Summary|ref returning function      |Template function attribute
                   |template allows bypassing   |inference wrongly infers
                   |@safe on unions             |@safe for accessing
                   |                            |overlapping pointer fields
                   |                            |in unions

--
March 29, 2017
https://issues.dlang.org/show_bug.cgi?id=17284

--- Comment #5 from hsteoh@quickfur.ath.cx ---
Oh my, it gets worse: ref has nothing to do with it at all!  Look at this blatant violation of @safe:

------
class C { }
union U { C c; int i; }

void func(T)(T t)
{
        t.c = new C;
        t.i++;       // !!!
}

pragma(msg, typeof(func!U));
------

Compiler output:
------
pure nothrow @safe void(U t)
------

Looks like attribute inference is a free license to violate @safety. :-D  Or, more precisely, attribute inference completely forgets to check for overlapping pointers.

--
March 29, 2017
https://issues.dlang.org/show_bug.cgi?id=17284

--- Comment #6 from ZombineDev <petar.p.kirov@gmail.com> ---
> Looks like attribute inference is a free license to violate @safety. :-D

Yeah with templates one enters 'god mode' in :D

Though the situation isn't very clear-cut. Take this code for example:

```
struct S { int* ptr; }
void func1()() { S s; s.ptr++; }
pragma (msg, "typeof(&func1!()): ", typeof(&func1!()));

class C { }
union U { C c; int i; }
void func2()() { U u; u.c = null; }
pragma (msg, "typeof(&func2!()): ", typeof(&func2!()));

int[] func3()() { int[5] sa; return sa; }
pragma (msg, "typeof(&func3!()): ", typeof(&func3!()));

int[] func4a(int[] a) @safe { return a; }
int[] func4b()() { int[5] sa; return func4a(sa); }
pragma (msg, "typeof(&func4b!()): ", typeof(&func4b!()));

void main() {}
```

$ dmd safe_infer_test1.d
typeof(&func1!()): void function() pure nothrow @nogc @system
typeof(&func2!()): void function() pure nothrow @nogc @safe
typeof(&func3!()): safe_infer_test1.d(10): Error: escaping reference to local
variable sa
int[] function() pure nothrow @nogc @safe
typeof(&func4b!()): int[] function() @safe

So, depending on the code in question, sometimes inferences works correctly, and sometimes not.

Also note that the attribute inference of func4b!() changes depending on if you compile with -dip1000 or not:

$ dmd -dip1000 safe_infer_test1.d
typeof(&func1!()): void function() pure nothrow @nogc @system
typeof(&func2!()): void function() pure nothrow @nogc @safe
typeof(&func3!()): safe_infer_test1.d(10): Error: escaping reference to local
variable sa
int[] function() pure nothrow @nogc @safe
typeof(&func4b!()): int[] function() @system

--
January 20, 2018
https://issues.dlang.org/show_bug.cgi?id=17284

Carsten Blüggel <chilli@posteo.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |chilli@posteo.net

--
March 04, 2018
https://issues.dlang.org/show_bug.cgi?id=17284

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bugzilla@digitalmars.com

--- Comment #7 from Walter Bright <bugzilla@digitalmars.com> ---
https://github.com/dlang/dmd/pull/7982

--
« First   ‹ Prev
1 2