Thread overview
[Issue 18792] Incorrect scope analysis with -dip1000 for small-sized-optimized string
Apr 23, 2018
Per Nordlöw
Apr 24, 2018
Per Nordlöw
Mar 04, 2020
Walter Bright
Mar 04, 2020
Per Nordlöw
Mar 04, 2020
Per Nordlöw
Mar 04, 2020
Walter Bright
Jun 10
Dennis
April 23, 2018
https://issues.dlang.org/show_bug.cgi?id=18792

Per Nordlöw <per.nordlow@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |safe

--
April 24, 2018
https://issues.dlang.org/show_bug.cgi?id=18792

Per Nordlöw <per.nordlow@gmail.com> changed:

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

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

Walter Bright <bugzilla@digitalmars.com> changed:

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

--- Comment #1 from Walter Bright <bugzilla@digitalmars.com> ---
Please reduce to a much smaller case of what the problem is.

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

--- Comment #2 from Per Nordlöw <per.nordlow@gmail.com> ---
I managed to reduce the code snippet to


struct SSOString
{
pure nothrow @nogc:

    inout(char)[] opSlice() inout return scope @trusted // TODO @safe for
-dip1000?
    {
        return small.data[0 .. small.length]; // scoped. TODO use .ptr when
proved stable
    }

    struct Small
    {
        ubyte length; // TODO only first 4 bits are needed to represent a
length between 0-15, use other 4 bits
        char[15] data;
    }

    struct Raw                  // same memory layout as `char[]`
    {
        size_t length;          // can be bit-fiddled without GC allocation
        char* ptr;
    }

    union
    {
        Raw raw; // PROBLEM this declaration prevents DIP-1000 scope analysis
from kicking in in `opSlice`
        Small small;
    }
}

@safe pure nothrow @nogc unittest
{
    char[] shouldFail1() @safe pure nothrow @nogc
    {
        SSOString x;
        return x[];             // TODO should fail with -dip1000
    }
}


When compiled with -dip100 the function `shouldFail1` should fail to compile but it does still compile. When I remove the line

    Raw raw;

scope analysis suddenly starts working which correctly triggers the error

foo.d(33,17): Error: returning `x.opSlice()` escapes a reference to local
variable `x`
        return x[];             // TODO should fail with -dip1000


Small enough, Walter?

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

--- Comment #3 from Per Nordlöw <per.nordlow@gmail.com> ---
(In reply to Per Nordlöw from comment #2)
> Small enough, Walter?

Forgot to remove obselete comments. Here's a new version with irrelevant comments removed.


struct SSOString
{
pure nothrow @nogc:

    inout(char)[] opSlice() inout return scope @trusted
    {
        return small.data[0 .. small.length];
    }

    struct Small
    {
        ubyte length;
        char[15] data;
    }

    struct Raw
    {
        size_t length;
        char* ptr;
    }

    union
    {
        Raw raw; // PROBLEM this declaration prevents DIP-1000 scope analysis
from kicking in in `opSlice`
        Small small;
    }
}

@safe pure nothrow @nogc unittest
{
    char[] shouldFail1() @safe pure nothrow @nogc
    {
        SSOString x;
        return x[];             // TODO should fail with -dip1000
    }
}

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

--- Comment #4 from Walter Bright <bugzilla@digitalmars.com> ---
much better, thank you

--
June 10
https://issues.dlang.org/show_bug.cgi?id=18792

Dennis <dkorpel@live.nl> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |dkorpel@live.nl
         Resolution|---                         |DUPLICATE
           Severity|enhancement                 |normal

--- Comment #5 from Dennis <dkorpel@live.nl> ---
I know this issue was first, but 21868 already got a pull.

It is the same problem: `return scope` without `ref return` applies return the values (e.g. SSOString.raw.ptr), not the address of SSOString itself (e.g. SSOString.small.data.ptr), but the compiler doesn't check for return-scope or return-ref, just return. The declaration of `Raw raw` is needed because otherwise SSOString has no pointers, so return scope is stripped away, so the compiler can't mistake the return attribute anymore and raises the correct error.

*** This issue has been marked as a duplicate of issue 21868 ***

--