Skip to content

[Version 13.0] Feature support for ref and unsafe in iterators and async - #1781

Draft
RexJaeschke wants to merge 3 commits into
draft-v13from
v13-ref-and-unsafe-in-iterators-and-async
Draft

[Version 13.0] Feature support for ref and unsafe in iterators and async#1781
RexJaeschke wants to merge 3 commits into
draft-v13from
v13-ref-and-unsafe-in-iterators-and-async

Conversation

@RexJaeschke

Copy link
Copy Markdown
Contributor

This is Rex's adaptation of the corresponding MS proposal.

@RexJaeschke RexJaeschke added this to the C# 13 milestone Aug 13, 2026
@RexJaeschke RexJaeschke added type: feature This issue describes a new feature Review: pending Proposal is available for review labels Aug 13, 2026
@RexJaeschke
RexJaeschke marked this pull request as draft August 13, 2026 10:48
Comment thread standard/statements.md
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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, that means it is permissible to read a ref local variable in unreachable code.

using System.Collections.Generic;

public class C {
    public IEnumerator<int> M() {
        int i = 0;
        ref int r = ref i;

        yield return r; // OK
        // r is definitely unassigned, because of the yield return above.

        // yield return r; // error

        yield break;
        // r is again definitely assigned, because this point is unreachable.

        yield return r; // OK
    }
}

Comment thread standard/statements.md
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.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not clear to me that this disallows the following:

using System.Threading.Tasks;

public class C {
    public static async Task M(Task<int> t) {
        int i = 0;
        ref int r = ref i;
        K1(ref r, await t); // error
    }
    
    private static void K1(ref int r, int i) {}
}

One could claim that ref r is evaluated before the await expression and r is still definitely assigned at that point. So this depends on the "compiler-synthesized code" for await expressions but I'm not sure that is specified rigorously enough to say whether the above is allowed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Review: pending Proposal is available for review type: feature This issue describes a new feature

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants