Skip to content

Commit fc302bb

Browse files
committed
Update Ref Return Scope Parameters to new design
1 parent f6e630a commit fc302bb

File tree

1 file changed

+57
-44
lines changed

1 file changed

+57
-44
lines changed

spec/function.dd

Lines changed: 57 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -1937,78 +1937,91 @@ class C
19371937

19381938
$(H3 $(LNAME2 ref-return-scope-parameters, Ref Return Scope Parameters))
19391939

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:)
19411947

19421948
---
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
19561951

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`
19611956

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+
---
19641962

1963+
$(P Example of combinations of `return scope`, `return ref`, and `scope` semantics:)
19651964
---
19661965
@safe:
19671966

1967+
int* globalPtr;
1968+
19681969
struct S
19691970
{
1970-
this(return scope ref int* p) { ptr = p; }
1971-
19721971
int val;
19731972
int* ptr;
1974-
}
19751973

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; }
19781975

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
19811977

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+
}
19871983

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+
}
19922001
}
19932002

1994-
ref int* test3(S s)
2003+
int* retRefA(return ref scope S s)
19952004
{
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`
19972007
}
19982008

1999-
ref int test4(S s)
2009+
ref int retRefB(return ref scope S s)
20002010
{
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;
20022013
}
20032014

2004-
S test5(ref scope int* p)
2015+
int* retScopeA(ref return scope S s)
20052016
{
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
20072019
}
20082020

2009-
S test6(ref return scope int* p)
2021+
ref int retScopeB(ref return scope S s)
20102022
{
2011-
return S(p);
2023+
return s.val; // disallowed, escaping a reference to `s`
2024+
return *s.ptr; // allowed, returning a `return scope` pointer
20122025
}
20132026
---
20142027

0 commit comments

Comments
 (0)