@@ -1940,78 +1940,91 @@ class C
1940
1940
1941
1941
$(H3 $(LNAME2 ref-return-scope-parameters, Ref Return Scope Parameters))
1942
1942
1943
- $(P Parameters marked as `ref return scope` come in two forms:)
1943
+ $(P It is not possible to have both `return ref` and `return scope` semantics
1944
+ for the same parameter.
1945
+ When a parameter is passed by `ref` and has both the `return` and `scope` storage classes,
1946
+ it gets $(LINK2 #return-scope-parameters, `return scope`) semantics if and only if the `return` and `scope`
1947
+ keywords appear adjacent to each other, in that order.
1948
+ In all other cases, the parameter has $(LINK2 #return-ref-parameters, `return ref`) semantics
1949
+ and regular $(LINK2 #scope-parameters, `scope`) semantics:)
1944
1950
1945
1951
---
1946
- U xerxes(ref return scope V v); // (1) ref and return scope
1947
- ref U sargon(ref return scope V v); // (2) return ref and scope
1948
- ---
1949
-
1950
- $(P The first form attaches the `return` to the `scope`, and has
1951
- $(LINK2 #return-scope-parameters, return scope parameter) semantics
1952
- for the value of the `ref` parameter.)
1953
-
1954
- $(P The second form attaches the `return` to the `ref`, and has
1955
- $(LINK2 #return-ref-parameters, return ref parameter) semantics
1956
- with additional
1957
- $(LINK2 https://dlang.org/spec/memory-safe-d.html#scope-return-params, scope parameter)
1958
- semantics.)
1952
+ U xerxes( ref return scope V v) // (1) ref and return scope
1953
+ U sargon(return ref scope V v) // (2) return ref and scope
1959
1954
1960
- $(P Although a struct constructor returns a reference to the instance
1961
- being constructed, it is treated as form (1).)
1962
-
1963
- $(P The lexical order of the attributes `ref`, `return`, and `scope` is not significant.)
1955
+ struct S
1956
+ {
1957
+ // note: in struct member functions, the implicit `this` parameter
1958
+ // is passed by `ref`
1964
1959
1965
- $(P It is not possible to have both `return ref` and `return scope` semantics
1966
- for the same parameter.)
1960
+ U xerxes() return scope; // return scope
1961
+ U sargon() scope return; // return ref, `return` comes after `scope`
1962
+ U xerxes() return const scope; // return ref, `return` and `scope` are not adjacent
1963
+ }
1964
+ ---
1967
1965
1966
+ $(P Example of combinations of `return scope`, `return ref`, and `scope` semantics:)
1968
1967
---
1969
1968
@safe:
1970
1969
1970
+ int* globalPtr;
1971
+
1971
1972
struct S
1972
1973
{
1973
- this(return scope ref int* p) { ptr = p; }
1974
-
1975
1974
int val;
1976
1975
int* ptr;
1977
- }
1978
1976
1979
- int* foo1(ref return scope S s);
1980
- int foo2(ref return scope S s);
1977
+ this(return scope ref int* p) { ptr = p; }
1981
1978
1982
- ref int* foo3(ref return scope S s);
1983
- ref int foo4(ref return scope S s);
1979
+ // note: `this` is passed by `ref` in structs
1984
1980
1985
- int* test1( scope S s)
1986
- {
1987
- return foo1(s); // Error: scope variable `s` may not be returned
1988
- return foo3(s); // Error: scope variable `s` may not be returned
1989
- }
1981
+ int* retRefA() scope return
1982
+ {
1983
+ globalPtr = this.ptr; // disallowed, `this` is `scope`
1984
+ return &this.val; // allowed, `return` means `return ref`
1985
+ }
1990
1986
1991
- int test2(S s)
1992
- {
1993
- return foo2(s);
1994
- return foo4(s);
1987
+ ref int retRefB() scope return
1988
+ {
1989
+ globalPtr = this.ptr; // disallowed, `this` is `scope`
1990
+ return this.val; // allowed, `return` means `return ref`
1991
+ }
1992
+
1993
+ int* retScopeA() return scope
1994
+ {
1995
+ return &this.val; // disallowed, escaping a reference to `this`
1996
+ return this.ptr; // allowed, returning a `return scope` pointer
1997
+ }
1998
+
1999
+ ref int retScopeB() return scope
2000
+ {
2001
+ return this.val; // disallowed, escaping a reference to `this`
2002
+ return *this.ptr; // allowed, returning a `return scope` pointer
2003
+ }
1995
2004
}
1996
2005
1997
- ref int* test3( S s)
2006
+ int* retRefA(return ref scope S s)
1998
2007
{
1999
- return foo3(s); // Error: returning `foo3(s)` escapes a reference to parameter `s`
2008
+ globalPtr = s.ptr; // disallowed, `s` is `scope`
2009
+ return &s.val; // allowed, returning a reference to `return ref s`
2000
2010
}
2001
2011
2002
- ref int test4( S s)
2012
+ ref int retRefB(return ref scope S s)
2003
2013
{
2004
- return foo4(s); // Error: returning `foo4(s)` escapes a reference to parameter `s`
2014
+ globalPtr = s.ptr; // disallowed, `s` is `scope`
2015
+ return s.val;
2005
2016
}
2006
2017
2007
- S test5 (ref scope int* p )
2018
+ int* retScopeA (ref return scope S s )
2008
2019
{
2009
- return S(p); // Error: scope variable `p` may not be returned
2020
+ return &s.val; // disallowed, escaping a reference to `s`
2021
+ return s.ptr; // allowed, returning a `return scope` pointer
2010
2022
}
2011
2023
2012
- S test6 (ref return scope int* p )
2024
+ ref int retScopeB (ref return scope S s )
2013
2025
{
2014
- return S(p);
2026
+ return s.val; // disallowed, escaping a reference to `s`
2027
+ return *s.ptr; // allowed, returning a `return scope` pointer
2015
2028
}
2016
2029
---
2017
2030
0 commit comments