Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow unsafe blocks in iterators #73046

Merged
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Clarify comment
  • Loading branch information
jjonescz committed Apr 30, 2024
commit 974722ebfc91f75bc1a19e52f84a5a200215f662
5 changes: 3 additions & 2 deletions src/Compilers/CSharp/Portable/Binder/Binder_Flags.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,9 @@ internal Binder WithAdditionalFlagsAndContainingMemberOrLambda(BinderFlags flags
internal Binder SetOrClearUnsafeRegionIfNecessary(SyntaxTokenList modifiers, bool isIteratorBody = false)
{
// In C# 13 and above, iterator bodies define a safe context even when nested in an unsafe context.
Copy link
Member

@cston cston Apr 30, 2024

Choose a reason for hiding this comment

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

In C# 13 and above,

Aren't iterator bodies defined in a safe context, regardless of language version? #Resolved

Copy link
Member Author

@jjonescz jjonescz Apr 30, 2024

Choose a reason for hiding this comment

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

Directly in iterators it might appear so because using any unsafe constructs is an error anyway, but if we use local functions for example, it can be seen that in C# 12 iterators do not define safe context, for example:

unsafe class C // unsafe context
{
    System.Collections.Generic.IEnumerable<int> M() // iterator
    {
        yield return local();
        int local() => sizeof(nint); // allowed, we are in unsafe context
    }
}

This is a pre-existing spec violation.

// In C# 12 and below, we keep the behavior that nested iterator bodies (e.g., local functions)
// inherit the safe/unsafe context from their containing scope to avoid a breaking change.
// In C# 12 and below, we keep the (spec violating) behavior that iterator bodies inherit the safe/unsafe context
// from their containing scope. Since there are errors for unsafe constructs directly in iterators,
// this inherited unsafe context can be observed only in nested non-iterator local functions.
var withoutUnsafe = isIteratorBody && this.Compilation.IsFeatureEnabled(MessageID.IDS_FeatureRefUnsafeInIteratorAsync);

if (this.Flags.Includes(BinderFlags.UnsafeRegion))
Expand Down