dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.98k stars 4.03k forks source link

TypeLoadException when declaring a task-like type as `ref struct` #64903

Open jhinder opened 1 year ago

jhinder commented 1 year ago

Version Used: VS 2022 17.4 Preview 4

Steps to Reproduce:

  1. Declare a task-like type as a ref struct: the task type itself is a ref struct, the builder needs to be one by extension too; the awaiter is a class as it must implement an interface.
  2. Write a simple await expression using that type.
  3. Run the application.

The sample code can be found in the Sharplab repro.

Expected Behavior: I'm not familiar with the internals of task-like types and async state machines in C#, so I don't know if it's even possible to emit valid async code in this scenario. The alternative would be to reject ref struct task-like types altogether.

Actual Behavior: TypeLoadException, probably because the state machine (regular struct) contains a field for the builder (ref struct)?

System.TypeLoadException: A ByRef-like type cannot be used as the type for an instance field in a non-ByRef-like type.
   at Playground.Program.M() in E:\Projects\compiler-playground\Program.cs:line 15
   at Playground.Program.<Main>d__0.MoveNext() in E:\Projects\compiler-playground\Program.cs:line 11

It's also not possible to assign such types to variables inside async methods: writing var task = M(); await task; in the Main method (something that would be perfectly legal for regular task types) leads to CS4012: "Parameters or locals of type 'RefStructTask' cannot be declared in async methods or async lambda expressions."

jcouv commented 1 year ago

Assigned to @cston to load-balance