Skip to content

Commit acedd8f

Browse files
committed
Improve spec of scope attribute
1 parent 3719b4c commit acedd8f

File tree

1 file changed

+99
-10
lines changed

1 file changed

+99
-10
lines changed

spec/attribute.dd

Lines changed: 99 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -645,27 +645,117 @@ 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 local variables and implements the
649-
RAII (Resource Acquisition Is Initialization) protocol.
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.
653+
)
654+
655+
$(P
656+
When applied to a global variable or a variable with a type that has no pointers, `scope` does nothing and is ignored.
657+
)
658+
659+
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
660+
---
661+
scope int* x; // does nothing
662+
663+
void main()
664+
{
665+
scope float y; // does nothing
666+
scope int[2] z; // does nothing (static array is value type)
667+
scope int[] w; // scope dynamic array
668+
}
669+
---
670+
)
671+
672+
$(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+
For example, it is impossible to declare a variable as a dynamic array of scope pointers, because `scope` only applies to the `.ptr`
675+
of the array itself, not its elements. `scope` affects various types as follows:
676+
677+
$(TABLE_2COLS ,
678+
$(THEAD Type of local variable, What `scope` applies to)
679+
680+
$(TROW Any $(DDSUBLINK spec/type, basic-data-types, Basic Data Type), nothing)
681+
$(TROW $(DDSUBLINK spec/arrays, pointers, Pointer) `T*`, the pointer value)
682+
$(TROW $(DDSUBLINK spec/arrays, dynamic-arrays, Dynamic Array) `T[]`, the `.ptr` to the elements)
683+
$(TROW $(DDSUBLINK spec/arrays, static-arrays, Static Array) `T[n]`, each element `T`)
684+
$(TROW $(GLINK2 hash-map, Associative Array) `K[V]`, the pointer to the implementation defined structure)
685+
$(TROW `struct` or `union`, each of its member variables)
686+
$(TROW `function` pointer, the pointer value)
687+
$(TROW $(DDSUBLINK spec/function, closures, delegate), both the `.funcptr` and `.ptr` (closure context) pointer values)
688+
$(TROW `class` or `interface`, the class reference)
689+
$(TROW $(GLINK2 enum, enum), the base type)
690+
)
691+
692+
Example:
693+
)
694+
695+
---
696+
struct S
697+
{
698+
string str; // note: string = immutable(char)[]
699+
string* strPtr;
700+
}
701+
702+
string escape(scope S s, scope S* sPtr, string[2] sarray, scope string[] darray)
703+
{
704+
return s.str; // invalid, scope applies to struct members
705+
return *s.strPtr; // valid, scope struct member is dereferenced
706+
return sPtr.str; // valid, struct pointer is dereferenced
707+
return *sPtr.strPtr; // valid, two pointers are dereferenced
708+
return sarray[0]; // invalid, scope applies to static array elements
709+
return sarray[1]; // invalid, ditto
710+
return darray[0]; // valid, scope applies to array pointer, not elements
711+
}
712+
---
713+
714+
$(H3 $(LNAME2 scope-class-var, $(D scope) variables with `class` type))
715+
$(P
716+
When used on variables with a `class` type, `scope` signifies the RAII
717+
(Resource Acquisition Is Initialization) protocol.
650718
This means that the destructor for an object is automatically called when the
651719
reference to it goes out of scope. The destructor is called even
652720
if the scope is exited via a thrown exception, thus $(D scope)
653721
is used to guarantee cleanup.
654722
)
655723
$(P
656-
If there is more than one $(D scope) variable going out of scope
724+
When a class is constructed with `new` and assigned to a local `scope` variable,
725+
it may be allocated on the stack and permitted in a `@nogc` context.
726+
)
727+
$(P
728+
If there is more than one `scope` class variable going out of scope
657729
at the same point, then the destructors are called in the reverse
658730
order that the variables were constructed.
659731
)
660732
$(P
661-
$(D scope) cannot be applied to globals, statics, data members, ref
662-
or out parameters. Arrays of $(D scope)s are not allowed, and $(D scope)
663-
function return values are not allowed. Assignment to a $(D scope),
664-
other than initialization, is not allowed.
665-
$(D Rationale:) These restrictions may get relaxed in the future
666-
if a compelling reason to appears.
733+
If there is more than one `scope` class variable going out of scope
734+
at the same point, then the destructors are called in the reverse
735+
order that the variables were constructed.
736+
)
737+
$(P
738+
Assignment to a $(D scope) variable with class type,
739+
other than initialization, is not allowed, because that would complicate
740+
proper destruction of the variable.
667741
)
668742

743+
---
744+
class C {}
745+
746+
void main() @nogc
747+
{
748+
{
749+
scope c0 = new C(); // allocated on the stack
750+
scope c1 = new C();
751+
752+
c1 = c0; // not allowed
753+
754+
// destructor of `c1` and `c0` are called here in that order
755+
}
756+
}
757+
---
758+
669759
$(H2 $(LNAME2 abstract, $(D abstract) Attribute))
670760

671761
$(P
@@ -720,7 +810,6 @@ $(H2 $(LNAME2 mustuse-attribute, `@mustuse` Attribute))
720810
An expression is considered to be discarded if and only if either of the
721811
following is true:
722812
)
723-
724813
$(UL
725814
$(LI
726815
it is the top-level $(GLINK2 expression, Expression) in an $(GLINK2

0 commit comments

Comments
 (0)