Thread overview
[Issue 23124] [dip1000] scope and return should not be inferred for @trusted function
Aug 26, 2022
Walter Bright
[Issue 23124] [dip1000] scope inference leads to implementatio-defined semantics for @trusted and @system.
Sep 17, 2022
Ate Eskola
Sep 17, 2022
Ate Eskola
Sep 17, 2022
Ate Eskola
Dec 17, 2022
Iain Buclaw
August 26, 2022
https://issues.dlang.org/show_bug.cgi?id=23124

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |bugzilla@digitalmars.com
         Resolution|---                         |INVALID

--- Comment #1 from Walter Bright <bugzilla@digitalmars.com> ---
The error is:

test.d(17): Error: scope variable `myVar` assigned to `outer` with longer
lifetime

which is a correct error message. `outer` lives longer than the scope of `inner`, so it is an error to set `outer` to pointing at `inner`.

If you need it to compile, remove `@safe` from main().

It's a feature of D to do scope inference. Whether the use of a scope pointer is checked or not is dependent on whether the function using the scope pointer is @safe or not.

This is working as designed.

--
September 17, 2022
https://issues.dlang.org/show_bug.cgi?id=23124

Ate Eskola <Ajieskola@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|INVALID                     |---
            Summary|[dip1000] scope and return  |[dip1000] scope inference
                   |should not be inferred for  |leads to
                   |@trusted function           |implementatio-defined
                   |                            |semantics for @trusted and
                   |                            |@system.

--- Comment #2 from Ate Eskola <Ajieskola@gmail.com> ---
I did change my mind in the topic a bit. I said previously, that no `scope` inference should be done for a `@trusted` or `@system` function. Now I think that it's okay, good even, to infer, but if the inference changes the attributes it should be an error.

Why? Consider a hypothetical future spec-compliant D compiler. The language spec does not say where the inference must stop, so our future compiler infers `scope` only if the argument is directly returned. If it encounters any other expression than a plain symbol name, it stops inference there.

Now we have a function
------
import std.random : dice;
auto either(int* a, int* b) @trusted { return dice(1,1) ? a : b; }
------

What happens? DMD infers arguments a and b as `scope`, BUT our future compiler does not. What is a perfectly safe function with DMDFE just became a terrible footgun in another spec-abiding compiler!

So, if we don't want to disable inference in these cases, there are two options:

1: If inference detects need for adding `scope` or `return` to a `@system` or `@trusted` function, it must error.

2: The spec must unambiguously specify where `scope` and `return scope` should be inferred and where it should not.

I think the first option is simpler, but I'm happy with either one.

--
September 17, 2022
https://issues.dlang.org/show_bug.cgi?id=23124

--- Comment #3 from Ate Eskola <Ajieskola@gmail.com> ---
Example in my last comment was wrong. Posting a corrected one:

----------------
struct MyType
{ private int* wontEverPointToLocal;
  int* mayPointToLocalIfScope;
  // Safe in the future compiler because
  // not callable with scope MyType.
  // Dangerous in DMD because it infers
  // scope for this reference.
  @trusted fun(bool cond){return cond? wontEverPointToLocal:
mayPointToLocalIfScope;}
}
----------------

--
September 17, 2022
https://issues.dlang.org/show_bug.cgi?id=23124

--- Comment #4 from Ate Eskola <Ajieskola@gmail.com> ---
(In reply to Ate Eskola from comment #3)
> Example in my last comment was wrong. Posting a corrected one:
> 
> ----------------
> struct MyType
> { private int* wontEverPointToLocal;
>   int* mayPointToLocalIfScope;
>   // Safe in the future compiler because
>   // not callable with scope MyType.
>   // Dangerous in DMD because it infers
>   // scope for this reference.
>   @trusted fun(bool cond){return cond? wontEverPointToLocal:
> mayPointToLocalIfScope;}
> }
> ----------------

Nope, still not right. My brains are porridge. Third try:

---------------------
struct MyType
{ int* ptr;
  // Safe in DMD because return scope is inferred.
  // Dangerous in our future compiler because
  // may return an unscoped pointer to local data,
  // when MyType is scope.
  @trusted scope getPtr(bool cond){return cond? ptr: null;}
}
---------------------

--
December 17, 2022
https://issues.dlang.org/show_bug.cgi?id=23124

Iain Buclaw <ibuclaw@gdcproject.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Priority|P1                          |P3

--
December 13
https://issues.dlang.org/show_bug.cgi?id=23124

--- Comment #5 from dlangBugzillaToGithub <robert.schadek@posteo.de> ---
THIS ISSUE HAS BEEN MOVED TO GITHUB

https://github.com/dlang/dmd/issues/20107

DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB

--