Thread overview
[Issue 22528] Template breaks return annotation for class reference returned by struct method
[Issue 22528] [dip1000] scope inference turns return-ref into return-scope
Nov 24, 2021
Dennis
Nov 24, 2021
Dennis
Nov 26, 2021
Dennis
Nov 27, 2021
Walter Bright
November 20, 2021
https://issues.dlang.org/show_bug.cgi?id=22528

thomas.bockman@gmail.com changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |accepts-invalid

--
November 24, 2021
https://issues.dlang.org/show_bug.cgi?id=22528

Dennis <dkorpel@live.nl> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |dkorpel@live.nl
           Hardware|x86_64                      |All
            Summary|Template breaks return      |[dip1000] scope inference
                   |annotation for class        |turns return-ref into
                   |reference returned by       |return-scope
                   |struct method               |
                 OS|Linux                       |All

--- Comment #1 from Dennis <dkorpel@live.nl> ---
What's happening is that `borrowA` gets `scope` inferred because it's a
template.
You can add this line to borrowA to break scope inference and make it behave
like borrowB:
```
inout D temp = this._target;
```

Here's a more reduced test case:
```
@safe:

struct S {
    int* ptr;

    auto borrowA() return {
        return ptr;
    }

    int* borrowB() return /*scope inferred*/ {
        return ptr;
    }
}

void main() {
    static int* global;
    S s;
    global = s.borrowA;
    global = s.borrowB;
}
```

--
November 24, 2021
https://issues.dlang.org/show_bug.cgi?id=22528

Dennis <dkorpel@live.nl> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
         Resolution|---                         |DUPLICATE

--- Comment #2 from Dennis <dkorpel@live.nl> ---


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

--
November 26, 2021
https://issues.dlang.org/show_bug.cgi?id=22528

--- Comment #3 from thomas.bockman@gmail.com ---
(In reply to Dennis from comment #1)
> What's happening is that `borrowA` gets `scope` inferred because it's a template.

I don't get it. `return` restricts how the return value may be used by the caller, and `scope` restricts how the `this` reference may be used by the callee.

Why does an inferred restriction in once place effectively remove my explicit restriction from another?

> You can add this line to borrowA to break scope inference and make it behave
> like borrowB:
> ```
> inout D temp = this._target;
> ```

Thanks for the workaround; I'll try that out.

It does look fragile though, as it's basically tricking the compiler. At any time the compiler could be upgraded to be smart enough to recognize that this line is, in context, a no-op and can be ignored for analysis purposes.

--
November 26, 2021
https://issues.dlang.org/show_bug.cgi?id=22528

--- Comment #4 from Dennis <dkorpel@live.nl> ---
(In reply to thomas.bockman from comment #3)
> Why does an inferred restriction in once place effectively remove my explicit restriction from another?

Because the implementation is bad, it currently has flags STC.scope_ and STC.return_ and infers the meaning of STC.return from context. Walter is working on using STC.returnScope instead, see issue 22541 and https://github.com/dlang/dmd/pull/13357

> At any
> time the compiler could be upgraded to be smart enough to recognize that
> this line is, in context, a no-op and can be ignored for analysis purposes.

Yes, it relies on issue 20674. I do think this issue will be solved before
that, but you could also add a unittest with `assert(!__traits(compiles, ()
@safe {...}));` to test that escaping a reference isn't allowed, so you'll be
aware when the workaround breaks.

--
November 27, 2021
https://issues.dlang.org/show_bug.cgi?id=22528

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://issues.dlang.org/sh
                   |                            |ow_bug.cgi?id=20881

--