Thread overview
[Issue 23124] [dip1000] scope inference leads to implementatio-defined semantics for @trusted and @system.
[Issue 23124] [dip1000] scope and return should not be inferred for @trusted function
Aug 26, 2022
Walter Bright
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

--