Skip to content

Commit 3719b4c

Browse files
authored
Merge pull request #3262 from dkorpel/spec-scope-param
Update Ref Return Scope Parameters to new design
2 parents 421c6d7 + f611fdb commit 3719b4c

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
@@ -1940,78 +1940,91 @@ class C
19401940

19411941
$(H3 $(LNAME2 ref-return-scope-parameters, Ref Return Scope Parameters))
19421942

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

19451951
---
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
19591954

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

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

1966+
$(P Example of combinations of `return scope`, `return ref`, and `scope` semantics:)
19681967
---
19691968
@safe:
19701969

1970+
int* globalPtr;
1971+
19711972
struct S
19721973
{
1973-
this(return scope ref int* p) { ptr = p; }
1974-
19751974
int val;
19761975
int* ptr;
1977-
}
19781976

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

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
19841980

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

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+
}
19952004
}
19962005

1997-
ref int* test3(S s)
2006+
int* retRefA(return ref scope S s)
19982007
{
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`
20002010
}
20012011

2002-
ref int test4(S s)
2012+
ref int retRefB(return ref scope S s)
20032013
{
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;
20052016
}
20062017

2007-
S test5(ref scope int* p)
2018+
int* retScopeA(ref return scope S s)
20082019
{
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
20102022
}
20112023

2012-
S test6(ref return scope int* p)
2024+
ref int retScopeB(ref return scope S s)
20132025
{
2014-
return S(p);
2026+
return s.val; // disallowed, escaping a reference to `s`
2027+
return *s.ptr; // allowed, returning a `return scope` pointer
20152028
}
20162029
---
20172030

0 commit comments

Comments
 (0)