Skip to content

Commit 7c61da7

Browse files
dkorpelmaxhaton
andcommitted
Update spec/attribute.dd
Co-authored-by: Max Haughton <maxhaton@gmail.com>
1 parent acedd8f commit 7c61da7

File tree

1 file changed

+79
-10
lines changed

1 file changed

+79
-10
lines changed

spec/attribute.dd

Lines changed: 79 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -645,32 +645,52 @@ auto i = 6.8; // declare i as a double
645645
$(H2 $(LNAME2 scope, $(D scope) Attribute))
646646

647647
$(P
648-
The $(D scope) attribute is used for parameters or local variables with a type that contains low-level pointers.
649-
It signifies that the variable's pointer values will not escape the function
650-
(in case of a $(DDSUBLINK spec/function, scope-parameters, scope parameters)) or
651-
$(DDSUBLINK spec/statement, scope-statement, scope statement) that the variable is declared in,
652-
for example by returning it or assigning it to a variable outside of its scope.
648+
The `scope` attribute signifies a variable's pointer values will not escape the scope that the variable is declared in.
653649
)
654650

655651
$(P
656-
When applied to a global variable or a variable with a type that has no pointers, `scope` does nothing and is ignored.
652+
If the variable has a type that does not contain any indirections, the `scope` attribute is ignored.
653+
)
654+
655+
$(P
656+
When applied to a global variable, `scope` is also ignored, since there is no scope larger than global scope that pointers could escape to.
657657
)
658658

659659
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
660660
---
661-
scope int* x; // does nothing
661+
scope int* x; // scope ignored, global variable
662662

663663
void main()
664664
{
665-
scope float y; // does nothing
666-
scope int[2] z; // does nothing (static array is value type)
665+
static int* x; // scope ignored, global variable
666+
scope float y; // scope ignored, no indirections
667+
scope int[2] z; // scope ignored, static array is value type
667668
scope int[] w; // scope dynamic array
668669
}
669670
---
670671
)
671672

672673
$(P
673-
The $(D scope) attribute is part of the variable declaration, not of the type, and it only applies to the first level of indirection.
674+
When applied to a local variable with a type that has indirections,
675+
its value may not be assigned to a variable with longer lifetime:
676+
677+
$(UL
678+
$(LI Variables outside the $(DDSUBLINK spec/statement, scope-statement, scope statement) that the variable is declared in)
679+
$(LI Variables declared before the `scope` variable$(COMMA) since local variables are destructed in the reverse order that they are declared in.)
680+
$(LI `__gshared` or `static` variables)
681+
)
682+
683+
Other operations implicitly assigning them to variables with longer lifetime are also disallowed:
684+
685+
$(UL
686+
$(LI Returning a `scope` variable from a function)
687+
$(LI Assigning a `scope` variable to a non-scope parameter by calling a function)
688+
$(LI Putting a `scope` variable in an array literal)
689+
)
690+
)
691+
692+
$(P
693+
The `scope` attribute is part of the variable declaration, not of the type, and it only applies to the first level of indirection.
674694
For example, it is impossible to declare a variable as a dynamic array of scope pointers, because `scope` only applies to the `.ptr`
675695
of the array itself, not its elements. `scope` affects various types as follows:
676696

@@ -711,6 +731,55 @@ string escape(scope S s, scope S* sPtr, string[2] sarray, scope string[] darray)
711731
}
712732
---
713733

734+
$(P
735+
A "`scope` value" is the value of a `scope` variable, or any generated value that is (or could be) allocated on the stack:
736+
$(UL
737+
$(LI The address of a function local variable / parameter)
738+
$(LI A struct member accessed through the implicit `this` parameter)
739+
$(LI The return value of a $(DDSUBLINK spec/function, ref-functions, Ref Function))
740+
$(LI The variadic parameter from $(DDSUBLINK spec/function, typesafe_variadic_functions, Typesafe Variadic Functions))
741+
)
742+
743+
When a local variable is assigned a `scope` value, it is inferred `scope`, even when the variable has an explicit type and does not use the `auto` keyword.
744+
)
745+
746+
---
747+
int* escape(ref int x, int y, scope int* z)
748+
{
749+
scope int* w;
750+
751+
auto xPtr = &x; // inferred `scope int*`
752+
int* yPtr = &y; // also inferred `scope int*`
753+
int* zCopy = z; // inferred `scope int*`
754+
int* wCopy = w; // inferred `scope int*`
755+
756+
return yPtr; // error
757+
}
758+
759+
void variadic(int[] a...)
760+
{
761+
int[] x = a; // inferred `scope int[]`
762+
}
763+
764+
struct S
765+
{
766+
int x;
767+
768+
// this method may be called on a stack-allocated instance of S
769+
void f()
770+
{
771+
int* p = &x; // inferred `scope int* p`
772+
int* q = &this.x; // equivalent
773+
}
774+
}
775+
---
776+
777+
$(P
778+
$(DDSUBLINK spec/function, scope-parameters, scope parameters) are treated the same as scope local variables,
779+
except that returning them is allowed when the function has $(DDSUBLINK spec/function, function-attribute-inference, Function Attribute Inference).
780+
In that case, they are inferred as $(DDSUBLINK spec/function, return-scope-parameters, return scope parameters).
781+
)
782+
714783
$(H3 $(LNAME2 scope-class-var, $(D scope) variables with `class` type))
715784
$(P
716785
When used on variables with a `class` type, `scope` signifies the RAII

0 commit comments

Comments
 (0)