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

"Requires unsafe context" error in an unsafe iterator #76514

Open
xparadoxical opened this issue Dec 19, 2024 · 4 comments
Open

"Requires unsafe context" error in an unsafe iterator #76514

xparadoxical opened this issue Dec 19, 2024 · 4 comments
Labels
Area-Compilers Feature - Ref/Unsafe in Iterators/Async Resolution-By Design The behavior reported in the issue matches the current design untriaged Issues and PRs which have not yet been triaged by a lead

Comments

@xparadoxical
Copy link

Version Used:
Compiler version: '4.12.0-3.24572.7 (dfa7fc6)'. Language version: 13.0.
Steps to Reproduce:
unsafe IEnumerable<int> M() { int* i = null; yield return 1; }
(sharplab)

Diagnostic Id:

CS0214: Pointers and fixed size buffers may only be used in an unsafe context

Expected Behavior:
Compiles, since the entire method is unsafe so pointers should be allowed without an explicit unsafe block.
Actual Behavior:
Doesn't compile, you have to use unsafe { int* i = null; }.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Dec 19, 2024
@huoyaoyuan
Copy link
Member

huoyaoyuan commented Dec 19, 2024

It's intentional breaking change: https://github.com/dotnet/roslyn/blob/main/docs/compilers/CSharp/Compiler%20Breaking%20Changes%20-%20DotNet%209.md#iterators-introduce-safe-context-in-c-13-and-newer

According to the design note, unsafe on iterator method only introduces unsafe context on parameter and attribute declaration. The body is still safe context:

    [/* unsafe context */ A]
    unsafe IEnumerable<int> M3(
        /* unsafe context */ int*[] x)
    { // safe context
        yield return 1;
    }

@xparadoxical
Copy link
Author

xparadoxical commented Dec 19, 2024

If an iterator declaration is marked with the unsafe modifier, the signature is in an unsafe scope but the iterator block used to implement that iterator still defines a safe scope.

Well that's sad. I thought my example should be equivalent to IEnumerable<int> M() { unsafe { int* i = null; } yield return 1; }, in other words yield returns which can't be in unsafe context would implicitly divide the unsafe context into smaller unsafe blocks. This doesn't seem to have been considered, looking at the 8th bullet point of the "alternatives" section. Unsafe blocks add a level of indentation, which is why I always prefer to mark entire members as unsafe.

@jcouv
Copy link
Member

jcouv commented Dec 20, 2024

Thanks @huoyaoyuan for digging up the reference. This was indeed by design: "If an iterator declaration is marked with the unsafe modifier, the signature is in an unsafe scope but the iterator block used to implement that iterator still defines a safe scope."
But I don't recall the motivation for that choice. Tagging @jjonescz for comment. Thanks

@jcouv jcouv added Resolution-By Design The behavior reported in the issue matches the current design Feature - Ref/Unsafe in Iterators/Async labels Dec 20, 2024
@jjonescz
Copy link
Member

jjonescz commented Dec 23, 2024

But I don't recall the motivation for that choice.

The speclet has the motivation in https://github.com/dotnet/csharplang/blob/main/proposals/csharp-13.0/ref-unsafe-in-iterators-async.md#alternatives:

Image

I thought my example should be equivalent to IEnumerable<int> M() { unsafe { int* i = null; } yield return 1; }, in other words yield returns which can't be in unsafe context would implicitly divide the unsafe context into smaller unsafe blocks. This doesn't seem to have been considered, looking at the 8th bullet point of the "alternatives" section.

That indeed wasn't considered (fwiw it looks like an overly complicated language rule to me), but feel free to open a discussion for that in https://github.com/dotnet/csharplang.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers Feature - Ref/Unsafe in Iterators/Async Resolution-By Design The behavior reported in the issue matches the current design untriaged Issues and PRs which have not yet been triaged by a lead
Projects
None yet
Development

No branches or pull requests

4 participants