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