www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Return value storage classes - `scope` as well as `ref`

reply Nick Treleaven <nick geany.org> writes:
Recently we've discussed syntax solutions to `ref` not applying 
to a variable/parameter when those are of function pointer type:
https://issues.dlang.org/show_bug.cgi?id=2753

`ref` is a function attribute, so this problem is easier to 
solve. Also it is not allowed after the parameter list because 
conceptually it applies to the return value.

However, there is another case of missing syntax for an 
unimplemented feature. `scope` would be useful to apply to the 
return value of a function. Currently `scope` is disallowed on 
functions except for methods or delegates, where it applies to 
`this` or the context. There are cases where it would be useful 
to apply to the return value - e.g. for `List.front` here:
https://issues.dlang.org/show_bug.cgi?id=17934

```d
     Elem elem;
     {
         auto l = list();
         elem = l.front; // should error
         // destructor called
     }
```
And for `S.fp` here:
https://forum.dlang.org/post/mqyqlieghqwsinbqiqbp forum.dlang.org

```d
     int* p;
     {
         auto lf = S(5);
         p = lf.fp; // should error
         // destructor called
     }
```
Syntax solutions proposed to fix the `ref` problem are:
* Parenthesized type syntax - 
https://forum.dlang.org/post/fnfuczxfyjpyespactjt forum.dlang.org
* leading function pointer type syntax - 
https://forum.dlang.org/post/qngjoxgihmcsvoprnanb forum.dlang.org
* trailing return type syntax - 
https://forum.dlang.org/post/iveapbodjzgqfjkujsop forum.dlang.org

The first two have PRs. I think only the latter fixes the `scope` 
problem. A simpler fix would be this ordering:
```
Type ReturnStorage? Identifier Parameters
```
Where *ReturnStorage* is `ref` or `scope`.
```d
T scope ref func_name();
```

Using parentheses just for the storage class(es) would work too:
```d
(scope ref) T func_name();
```

Also, solving the problem generally could be useful in the future 
if we want any other storage classes to apply to the return value 
rather than the function or the parameter.
May 29 2023
next sibling parent reply Dukc <ajieskola gmail.com> writes:
On Monday, 29 May 2023 at 10:08:38 UTC, Nick Treleaven wrote:
 And for `S.fp` here:
 https://forum.dlang.org/post/mqyqlieghqwsinbqiqbp forum.dlang.org

 ```d
     int* p;
     {
         auto lf = S(5);
         p = lf.fp; // should error
         // destructor called
     }
 ```
No, this is working just as it should. `lf` is not `scope`, so a return value of a `return scope` function should be neither. Maybe you're confusing lifetime of struct itself with lifetime of what it's pointing to. `return scope` return value is `scope` only if the struct is `scope` - that is, potentially pointing to a local with one or more of it's fields. Whether the struct itself is in stack is irrelevant. On the other hand, `return` (without the trailing `scope`, `return ref` when applied to a parameter) means the return value is `scope` if the struct is in a stack. Maybe that's what you intended `S.fp` to be.
May 30 2023
next sibling parent Dukc <ajieskola gmail.com> writes:
On Tuesday, 30 May 2023 at 07:21:44 UTC, Dukc wrote:
 No, this is working just as it should. `lf` is not `scope`, so 
 a return value of a `return scope` function should be neither.
Oh sorry, didn't read your whole post. You weren't claiming there's a bug but suggesting a new design. That is, making `lf` be `scope` with this syntax. I still prefer the current solution, though. `scope` is an on/off attribute only from perspect of variables. Expression, though, have shortest possible lifetimes, meaning they figure out which local scope the result is guaranteed to last. `S(5)` is an expression, so the compiler needs to figure out it's shortest possible lifetime even if it isn't immediately assigned to a variable. What should it be? It isn't obvious. What does work, without language changes, is giving a sentinel pointer parameter to the constructor that is used to figure out the shortest possible lifetime. That is, the constructor is defined `this(int, return scope void* sentinel)` and is used `S(5, &localVariableIWontOutlive)`.
May 30 2023
prev sibling parent reply Nick Treleaven <nick geany.org> writes:
On Tuesday, 30 May 2023 at 07:21:44 UTC, Dukc wrote:
 On the other hand, `return` (without the trailing `scope`, 
 `return ref` when applied to a parameter) means the return 
 value is `scope` if the struct is in a stack. Maybe that's what 
 you intended  `S.fp` to be.
Yes, thanks I didn't know that. I'm not sure if that's documented anywhere in the spec. https://dlang.org/spec/function.html#return-scope-parameters This also resolves the bugzilla issue: https://issues.dlang.org/show_bug.cgi?id=17934#c12
May 31 2023
parent Nick Treleaven <nick geany.org> writes:
On Wednesday, 31 May 2023 at 10:29:06 UTC, Nick Treleaven wrote:
 I'm not sure if that's documented anywhere in the spec.
https://github.com/dlang/dlang.org/pull/3619
May 31 2023
prev sibling parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Monday, 29 May 2023 at 10:08:38 UTC, Nick Treleaven wrote:
 However, there is another case of missing syntax for an 
 unimplemented feature. `scope` would be useful to apply to the 
 return value of a function.
By “unimplemented feature” are you suggesting a new langue feature or is there something specified that is not implemented yet? If it’s already in the spec, please quote the relevant sections.
May 30 2023