diff --git a/standard/classes.md b/standard/classes.md index 25ae0934d..bf78a4a21 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -5988,6 +5988,8 @@ A method ([§15.6](classes.md#156-methods)), anonymous function ([§12.22](expre It is a compile-time error for the parameter list of an async function to specify any `in`, `out`, or `ref` parameters, or any parameter of a `ref struct` type. +It is a compile-time error for an unsafe context to contain an `await` expression or a `yield return` statement. + The *return_type* of an async method shall be either `void`, a ***task type***, or an ***asynchronous iterator type*** ([§15.15](classes.md#1515-synchronous-and-asynchronous-iterators)). For an async method that produces a result value, a task type or an asynchronous iterator type ([§15.15.3](classes.md#15153-enumerable-interfaces)) shall be generic. For an async method that does not produce a result value, a task type shall not be generic. Such types are referred to in this specification as `«TaskType»` and `«TaskType»`, respectively. The Standard library type `System.Threading.Tasks.Task` and types constructed from `System.Threading.Tasks.Task` and `System.Threading.Tasks.ValueTask` are task types, as well as a class, struct or interface type that is associated with a ***task builder type*** via the attribute `System.Runtime.CompilerServices.AsyncMethodBuilderAttribute`. Such types are referred to in this specification as `«TaskBuilderType»` and `«TaskBuilderType»`. A task type can have at most one type parameter and cannot be nested in a generic type. An async method returning a task type is said to be ***task-returning***. @@ -6167,7 +6169,7 @@ An async function ([§15.14](classes.md#1514-async-functions)) or local function An iterator block may occur as a *method_body*, *operator_body* or *accessor_body*, whereas events, instance constructors, static constructors and finalizer shall not be implemented as synchronous or asynchronous iterators. -When a function is implemented using an iterator block, it is a compile-time error for the parameter list of the function to specify any `in`, `out`, or `ref` parameters, or a parameter of a `ref struct` type. +When a function is implemented using an iterator block, it is a compile-time error for the parameter list of the function to specify any `in`, `out`, or `ref` parameters, or a parameter of a `ref struct` type, or a pointer type. An asynchronous iterator shall support cancellation of the asynchronous operation. This is described in [§23.5.9](attributes.md#2359-the-enumeratorcancellation-attribute). diff --git a/standard/statements.md b/standard/statements.md index 0c6d084d7..71c7ce92b 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -162,10 +162,11 @@ The statement list of a block is reachable if the block itself is reachable. The end point of a block is reachable if the block is empty or if the end point of the statement list is reachable. -A *block* that contains one or more `yield` statements ([§13.15](statements.md#1315-the-yield-statement)) is called an iterator block. Iterator blocks are used to implement function members as iterators ([§15.15](classes.md#1515-synchronous-and-asynchronous-iterators)). Some additional restrictions apply to iterator blocks: +A *block* that contains one or more `yield` statements ([§13.15](statements.md#1315-the-yield-statement)) is called an iterator block, even if those `yield` statements are contained only indirectly in nested blocks (excluding nested lambdas and local functions). Iterator blocks are used to implement function members as iterators ([§15.15](classes.md#1515-synchronous-and-asynchronous-iterators)). -- It is a compile-time error for a `return` statement to appear in an iterator block (but `yield return` statements are permitted). -- It is a compile-time error for an iterator block to contain an unsafe context ([§24.2](unsafe-code.md#242-unsafe-contexts)). An iterator block always defines a safe context, even when its declaration is nested in an unsafe context. +It is a compile-time error for a `return` statement to appear in an iterator block (but `yield return` statements are permitted). + +The iterator block used to implement an iterator ([§15.14](classes.md#1514-iterators)) always defines a safe context, even when the iterator declaration is nested in an unsafe context. ### 13.3.2 Statement lists @@ -477,7 +478,7 @@ The initializing *variable_reference* shall have type *type* and meet the same r If *ref_kind* is `ref readonly`, the *identifier*s being declared are references to variables that are treated as read-only. Otherwise, if *ref_kind* is `ref`, the *identifier*s being declared are references to variables that shall be writable. -It is a compile-time error to declare a ref local variable, or a variable of a `ref struct` type, within a method declared with the *method_modifier* `async`, or within an iterator ([§15.15](classes.md#1515-synchronous-and-asynchronous-iterators)). +It is a compile-time error to declare and use (even implicitly in compiler-synthesized code) a ref local variable, or a variable of a `ref struct` type across `await` expressions or `yield return` statements. More precisely, the error is driven by the following mechanism: after an `await` expression or a `yield return` statement, all ref local variables and variables of a `ref struct` type in scope are considered definitely unassigned. For a discussion of `scoped`, see [§9.7.3](variables.md#973-the-scoped-modifier). diff --git a/standard/unsafe-code.md b/standard/unsafe-code.md index ec1327b38..eef677fef 100644 --- a/standard/unsafe-code.md +++ b/standard/unsafe-code.md @@ -767,6 +767,8 @@ An implicit conversion exists from a *unary_expression* whose target is a method - The selected method `M` shall be compatible (as defined above) with the function pointer type `F`. Otherwise, a compile-time error occurs. - The result of the conversion is a function pointer of type `F`. +In an iterator, it is a compile-time error to take the address of a local or a parameter. + ### 24.6.6 Pointer increment and decrement In an unsafe context, the `++` and `--` operators ([§12.8.16](expressions.md#12816-postfix-increment-and-decrement-operators) and [§12.9.7](expressions.md#1297-prefix-increment-and-decrement-operators)) can be applied to pointer variables of all types It is a compile-time error for these operators to be applied to variables of type *funcptr_type* or *voidptr_type*. Thus, for every data pointer type `T*`, the following operators are implicitly defined: