[Issue 22027] New: inout shouldn't imply return
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Tue Jun 15 23:22:27 UTC 2021
https://issues.dlang.org/show_bug.cgi?id=22027
Issue ID: 22027
Summary: inout shouldn't imply return
Product: D
Version: D2
Hardware: All
OS: All
Status: NEW
Keywords: safe
Severity: enhancement
Priority: P1
Component: dmd
Assignee: nobody at puremagic.com
Reporter: dkorpel at live.nl
Currently `inout` parameters imply the `return` attribute. It's a special case,
adding complexity to the language and the compiler, and it doesn't make sense.
The rationale of it is:
> The idea is that the inout doesn't make sense if one is not returning
> something based on the parameter marked with inout.
https://github.com/dlang/dmd/pull/10390#issuecomment-528774351
However, as pointed out by Rainer Schuetze, it's possible to return something
else that has the same qualifier as the parameter but different lifetime.
```
struct Large { void[4000] data; }
struct SImpl
{
Large d;
}
struct S
{
SImpl* impl; // GC managed?
ref inout(Large) getLarge() inout { return impl.d; }
}
```
https://github.com/dlang/dmd/pull/10390#issuecomment-529177731
In fact, here are examples of valid uses of inout with every combination of
ref/return/scope, showing that it doesn't ever imply the need for `return`:
```
struct Node
{
int x;
Node* next;
inout(int*) next_v0() return inout {return &this.x;}
inout(int*) next_v1() return scope inout {return &this.next.x;}
inout(int*) next_v2() scope inout {return &this.next.next.x;}
inout(int*) next_v3() inout {return &this.next.x;}
ref inout(int) next_r0() return inout {return this.next.x;}
ref inout(int) next_r1() scope inout {return this.next.next.x;}
ref inout(int) next_r2() return scope inout {return this.next.next.x;}
ref inout(int) next_r3() inout {return this.next.x;}
}
inout(int*) next_v0(return inout Node this_) {return &this_.next.x;}
inout(int*) next_v1(return scope inout Node this_) {return &this_.next.x;}
inout(int*) next_v2( scope inout Node this_) {return &this_.next.next.x;}
inout(int*) next_v3( inout Node this_) {return &this_.next.x;}
ref inout(int) next_r0(return inout Node this_) {return this_.next.x;}
ref inout(int) next_r1(return scope inout Node this_) {return this_.next.x;}
ref inout(int) next_r2( scope inout Node this_) {return
this_.next.next.x;}
ref inout(int) next_r3( inout Node this_) {return this_.next.x;}
```
It's also worth noting that the current implementation has a bug that's
trivially fixed by removing the special case:
https://issues.dlang.org/show_bug.cgi?id=20149
```
@safe:
struct ScopeBuffer {
char[4] buf;
inout(char)[] getSlice() inout {return buf[];}
}
char[] fun() {
char[4] buf = "abcd";
ScopeBuffer sb = ScopeBuffer(buf);
return sb.getSlice; // dangling slice to stack memory is returned here
}
void main() {
auto s = fun();
}
```
--
More information about the Digitalmars-d-bugs
mailing list