Clarify errors around void expressions in switch expressions / Disallow them in switch exp. instead of propagating void
#67.889 aperta il 20 apr 2023
Metriche repository
- Star
- (20.414 star)
- Metriche merge PR
- (Merge medio 6g 17h) (256 PR mergiate in 30 g)
Descrizione
Void expressions make no sense and do not seem to be usable at all - at least until dotnet/csharplang#2632 gets accepted and implemented. It looks like void expression type is propagated until it can't be anymore.
This propagation is probably why 1 switch { int => Console.WriteLine() } evaluated in any REPL that uses MS.CA.Scripting causes:
System.InvalidProgramException: Common Language Runtime detected an invalid program.
at void Submission#1.<<Initialize>>d__0.MoveNext()
at void System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start<TStateMachine>(ref TStateMachine stateMachine)
at Task<object> Submission#1.<Initialize>()
at Task<object> Submission#1.<Factory>(object[] submissionArray)
at async Task<TResult> Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync<TResult>(ImmutableArray<Func<object[], Task>> precedingExecutors, Func<object[], Task> currentExecutor, StrongBox<Exception> exceptionHolderOpt, Func<Exception, bool> catchExceptionOpt, CancellationToken cancellationToken)
Versions Used
- Compiler version: '4.5.0-1.22524.5 (03cf426e)'. Language version: preview.
- Sharplab
main (25 Jan 2023): Compiler version: '4.6.0-ci (<developer build>)'. Language version: preview. - Compiler version: '4.5.0-6.23127.3 (e2bc27d2)'. Language version: 11.0.
Steps to Reproduce
Try to compile:
void AsStatement() => 1 switch { int => Console.WriteLine() };
void Discard() => _ = 1 switch { int => Console.WriteLine() };
void Var() { var v = 1 switch { int => Console.WriteLine() }; }
void Argument() => Console.WriteLine(1 switch { int => Console.WriteLine() });
void Assignment() { int i = 1 switch { int => Console.WriteLine() }; }
int Return() => 1 switch { int => Console.WriteLine() };
(sharplab)
Expected Behavior
AsStatement: you can't use a switch expression as a statement - this should have higher priority than anything that happens in the expression.Discard,Var:Console.WriteLine()produces an error clearly indicating that this expression is the root cause of the problem, like "Expected an non-void expression".Argument:Console.WriteLine()produces "CS0029: Cannot implicitly convert type 'void' to 'bool'", since the required target type(s) is known and it was decided to useboolin this instance of the error.AssignmentandReturn:Console.WriteLine()produces "CS0029: Cannot implicitly convert type 'void' to 'int'", since it's known that the switch must have expression typeint.
Implicit conversion of void (which means "no type") to a non-void type (CS0029) sounds as if it couldn't materialize a type - kind of nonsense, so maybe this should be replaced with a clearer error? However, int i = Console.WriteLine(); results in the same error.
Actual Behavior
- :heavy_check_mark:
AsStatement:CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statementon the switch, - :x:
Discard:CS8209: A value of type 'void' may not be assignedon_, - :x:
Var:CS0815: Cannot assign void to an implicitly-typed variableonident = expr, - :x:
Argument:CS1503: Argument 1: cannot convert from 'void' to 'bool'on the switch, - :grey_question:
AssignmentandReturn:CS0029: Cannot implicitly convert type 'void' to 'int'- :heavy_check_mark: on
Console.WriteLine()
- :heavy_check_mark: on