@@ -2015,6 +2015,48 @@ S test6(ref return scope int* p)
2015
2015
}
2016
2016
---
2017
2017
2018
+ $(H3 $(LNAME2 pure-scope-inference, Inferred `scope` parameters in `pure` functions))
2019
+
2020
+ When a parameter is not marked or inferred `scope`, it may still be `@safe` to assign it a `scope` pointer in a function call.
2021
+ The following conditions need to be met:
2022
+
2023
+ $(UL
2024
+ $(LI The function is $(RELATIVE_LINK2 pure-functions, `pure`), hence the argument cannot be assigned to a global variable)
2025
+ $(LI The function is $(RELATIVE_LINK2 nothrow-functions, `nothrow`), hence the argument cannot be assigned to a thrown `Exception` object)
2026
+ $(LI None of the other parameters have mutable indirections, hence the argument cannot be assigned to a longer-lived variable)
2027
+ )
2028
+
2029
+ Then, the parameter is still treated as `scope` or `return scope` depending on the return type of the function:
2030
+ $(UL
2031
+ $(LI If the function returns by `ref` or has a return type that contains pointers, the argument could be returned, so it is treated as `return scope`)
2032
+ $(LI Otherwise, the argument cannot escape the function, so it is treated as `scope`)
2033
+ )
2034
+
2035
+ ---
2036
+ @safe:
2037
+
2038
+ int dereference(int* x) pure nothrow;
2039
+ int* identity(int* x) pure nothrow;
2040
+ int* identityThrow(int* x) pure;
2041
+ void assignToRef(int* x, ref int* escapeHatch) pure nothrow;
2042
+ void assignToPtr(int* x, int** escapeHatch) pure nothrow;
2043
+ void cannotAssignTo(int* x, const ref int* noEscapeHatch) pure nothrow;
2044
+
2045
+ int* globalPtr;
2046
+
2047
+ int* test(scope int* ptr)
2048
+ {
2049
+ int result = dereference(ptr); // allowed, treated as `scope`
2050
+ int* ptr2 = identity(ptr); // allowed, treated as `return scope`
2051
+ int* ptr3 = identityThrow(ptr); // not allowed, can throw an `Exception`
2052
+ assignToRef(ptr, globalPtr); // not allowed, mutable second parameter
2053
+ assignToPtr(ptr, &globalPtr); // not allowed, mutable second parameter
2054
+ cannotAssignTo(ptr, globalPtr); // allowed
2055
+
2056
+ return ptr2; // not allowed, ptr2 is inferred `scope` now
2057
+ }
2058
+ ---
2059
+
2018
2060
$(H3 $(LNAME2 udas-parameters, User-Defined Attributes for Parameters))
2019
2061
2020
2062
See also: $(GLINK2_ALTTEXT attribute, UserDefinedAttribute, User-Defined Attributes)
0 commit comments