Why does C# switch expression over ushort? cause massive compiler errors?

110 Views Asked by At

I have the following code which fails to compile. It isn't the usual compiler error, this is something I have never seen before:

Failing code:

static class Domains
{
    static DomainRole GetRole(ushort? role)
    {
        return role switch
        {
            >= 0 and <= 5 => (DomainRole)role,
            _             => DomainRole.Unknown
        };
    }
}

enum DomainRole
{
    Unknown                 = -1,
    StandaloneWorkstation   = 0,
    MemberWorkstation       = 1,
    StandaloneServer        = 2,
    MemberServer            = 3,
    BackupDomainController  = 4,
    PrimaryDomainController = 5
}

If I cast to int?, it works:

        return (int?)role switch
        {
            >= 0 and <= 5 => (DomainRole)role,
            _             => DomainRole.Unknown
        };

Ditto with switch statements:

        switch (role)
        {
            case >= 0 and <= 5:
                return (DomainRole)role;
            default:
                return DomainRole.Unknown;
        }

if statements also works:

        if (role is >= 0 and <= 5)
        {
            return (DomainRole)role;
        }

        return DomainRole.Unknown;

But not with ushort?. Why is this? Took me long enough to figure out.

Below is the compiler failures:

  Microsoft.CSharp.Core.targets(75, 5): Process terminated. System.ArgumentException: Value does not fall within the expected range.
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.ValueSetFactory.NumericValueSet`2.Microsoft.CodeAnalysis.CSharp.IValueSet.get_Sample()
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.SampleValueString(IValueSet remainingValues, TypeSymbol type, Boolean requireExactType, Boolean& unnamedEnumValue)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.<SamplePatternForTemp>g__tryHandleNumericLimits|2_5(Boolean& unnamedEnumValue, <>c__DisplayClass2_0& )
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.SamplePatternForTemp(BoundDagTemp input, Dictionary`2 constraintMap, Dictionary`2 evaluationMap, Boolean requireExactType, Boolean& unnamedEnumValue)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.<SamplePatternForTemp>g__tryHandleUnboxNullableValueType|2_3(Boolean& unnamedEnumValue, <>c__DisplayClass2_0& )
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.SamplePatternForTemp(BoundDagTemp input, Dictionary`2 constraintMap, Dictionary`2 evaluationMap, Boolean requireExactType, Boolean& unnamedEnumValue)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.SamplePatternForPathToDagNode(BoundDagTemp rootIdentifier, ImmutableArray`1 nodes, BoundDecisionDagNode targetNode, Boolean nullPaths, Boolean& requiresFalseWhenClause, Boolean& unnamedEnumValue)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.SwitchExpressionBinder.CheckSwitchExpressionExhaustive(SwitchExpressionSyntax node, BoundExpression boundInputExpression, ImmutableArray`1 switchArms, BoundDecisionDag& decisionDag, LabelSymbol& defaultLabel, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.SwitchExpressionBinder.BindSwitchExpressionCore(SwitchExpressionSyntax node, Binder originalBinder, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindExpressionInternal(ExpressionSyntax node, BindingDiagnosticBag diagnostics, Boolean invoked, Boolean indexed)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindExpression(ExpressionSyntax node, BindingDiagnosticBag diagnostics, Boolean invoked, Boolean indexed)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindReturn(ReturnStatementSyntax syntax, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindStatement(StatementSyntax node, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindBlockParts(BlockSyntax node, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindBlock(BlockSyntax node, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindStatement(StatementSyntax node, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindMethodBody(CSharpSyntaxNode declaration, BlockSyntax blockBody, ArrowExpressionClauseSyntax expressionBody, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindMethodBody(CSharpSyntaxNode syntax, BindingDiagnosticBag diagnostics, Boolean includesFieldInitializers)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.MethodCompiler.BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics, VariableState nullableInitialState, Boolean reportNullableDiagnostics, Boolean includesFieldInitializers, ImportChain& importChain, Boolean& originalBodyNested, InitialState& forSemanticModel)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileMethod(MethodSymbol methodSymbol, Int32 methodOrdinal, ProcessedFieldInitializers& processedInitializers, SynthesizedSubmissionFields previousSubmissionFields, TypeCompilationState compilationState)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamedType(NamedTypeSymbol containingType)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.MethodCompiler.<>c__DisplayClass25_0.<CompileNamedTypeAsync>b__0()
  Microsoft.CSharp.Core.targets(75, 5):    at System.Environment.FailFast(System.String, System.Exception)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.FailFast.OnFatalException(System.Exception)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.FatalError.Report(System.Exception, System.Action`1<System.Exception>)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.FatalError.ReportAndPropagateUnlessCanceled(System.Exception)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.MethodCompiler+<>c__DisplayClass25_0.<CompileNamedTypeAsync>b__0()
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.ValueSetFactory+NumericValueSet`2[[System.UInt16, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[Microsoft.CodeAnalysis.CSharp.ValueSetFactory+UShortTC, Microsoft.CodeAnalysis.CSharp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]].Microsoft.CodeAnalysis.CSharp.IValueSet.get_Sample()
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.SampleValueString(Microsoft.CodeAnalysis.CSharp.IValueSet, Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol, Boolean, Boolean ByRef)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.<SamplePatternForTemp>g__tryHandleNumericLimits|2_5(Boolean ByRef, <>c__DisplayClass2_0 ByRef)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.SamplePatternForTemp(Microsoft.CodeAnalysis.CSharp.BoundDagTemp, System.Collections.Generic.Dictionary`2<Microsoft.CodeAnalysis.CSharp.BoundDagTemp,Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder`1<System.ValueTuple`2<Microsoft.CodeAnalysis.CSharp.BoundDagTest,Boolean>>>, System.Collections.Generic.Dictionary`2<Microsoft.CodeAnalysis.CSharp.BoundDagTemp,Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder`1<Microsoft.CodeAnalysis.CSharp.BoundDagEvaluation>>, Boolean, Boolean ByRef)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.<SamplePatternForTemp>g__tryHandleUnboxNullableValueType|2_3(Boolean ByRef, <>c__DisplayClass2_0 ByRef)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.SamplePatternForTemp(Microsoft.CodeAnalysis.CSharp.BoundDagTemp, System.Collections.Generic.Dictionary`2<Microsoft.CodeAnalysis.CSharp.BoundDagTemp,Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder`1<System.ValueTuple`2<Microsoft.CodeAnalysis.CSharp.BoundDagTest,Boolean>>>, System.Collections.Generic.Dictionary`2<Microsoft.CodeAnalysis.CSharp.BoundDagTemp,Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder`1<Microsoft.CodeAnalysis.CSharp.BoundDagEvaluation>>, Boolean, Boolean ByRef)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.SamplePatternForPathToDagNode(Microsoft.CodeAnalysis.CSharp.BoundDagTemp, System.Collections.Immutable.ImmutableArray`1<Microsoft.CodeAnalysis.CSharp.BoundDecisionDagNode>, Microsoft.CodeAnalysis.CSharp.BoundDecisionDagNode, Boolean, Boolean ByRef, Boolean ByRef)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.SwitchExpressionBinder.CheckSwitchExpressionExhaustive(Microsoft.CodeAnalysis.CSharp.Syntax.SwitchExpressionSyntax, Microsoft.CodeAnalysis.CSharp.BoundExpression, System.Collections.Immutable.ImmutableArray`1<Microsoft.CodeAnalysis.CSharp.BoundSwitchExpressionArm>, Microsoft.CodeAnalysis.CSharp.BoundDecisionDag ByRef, Microsoft.CodeAnalysis.CSharp.Symbols.LabelSymbol ByRef, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.SwitchExpressionBinder.BindSwitchExpressionCore(Microsoft.CodeAnalysis.CSharp.Syntax.SwitchExpressionSyntax, Microsoft.CodeAnalysis.CSharp.Binder, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindExpressionInternal(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag, Boolean, Boolean)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindExpression(Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag, Boolean, Boolean)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindReturn(Microsoft.CodeAnalysis.CSharp.Syntax.ReturnStatementSyntax, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindStatement(Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindBlockParts(Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindBlock(Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindStatement(Microsoft.CodeAnalysis.CSharp.Syntax.StatementSyntax, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindMethodBody(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax, Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindMethodBody(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag, Boolean)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.MethodCompiler.BindMethodBody(Microsoft.CodeAnalysis.CSharp.Symbols.MethodSymbol, Microsoft.CodeAnalysis.CSharp.TypeCompilationState, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag, VariableState, Boolean, Boolean, Microsoft.CodeAnalysis.CSharp.ImportChain ByRef, Boolean ByRef, InitialState ByRef)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileMethod(Microsoft.CodeAnalysis.CSharp.Symbols.MethodSymbol, Int32, ProcessedFieldInitializers ByRef, Microsoft.CodeAnalysis.CSharp.SynthesizedSubmissionFields, Microsoft.CodeAnalysis.CSharp.TypeCompilationState)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamedType(Microsoft.CodeAnalysis.CSharp.Symbols.NamedTypeSymbol)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.MethodCompiler+<>c__DisplayClass25_0.<CompileNamedTypeAsync>b__0()
  Microsoft.CSharp.Core.targets(75, 5):    at Roslyn.Utilities.UICultureUtilities+<>c__DisplayClass5_0.<WithCurrentUICulture>b__0()
  Microsoft.CSharp.Core.targets(75, 5):    at System.Threading.Tasks.Task.InnerInvoke()
  Microsoft.CSharp.Core.targets(75, 5):    at System.Threading.Tasks.Task+<>c.<.cctor>b__272_0(System.Object)
  Microsoft.CSharp.Core.targets(75, 5):    at System.Threading.ExecutionContext.RunFromThreadPoolDispatchLoop(System.Threading.Thread, System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
  Microsoft.CSharp.Core.targets(75, 5):    at System.Threading.Tasks.Task.ExecuteWithThreadLocal(System.Threading.Tasks.Task ByRef, System.Threading.Thread)
  Microsoft.CSharp.Core.targets(75, 5):    at System.Threading.Tasks.Task.ExecuteEntryUnsafe(System.Threading.Thread)
  Microsoft.CSharp.Core.targets(75, 5):    at System.Threading.ThreadPoolWorkQueue.Dispatch()
  Microsoft.CSharp.Core.targets(75, 5):    at System.Threading.PortableThreadPool+WorkerThread.WorkerThreadStart()
  Microsoft.CSharp.Core.targets(75, 5):    at System.Threading.Thread.StartCallback()
  Microsoft.CSharp.Core.targets(75, 5): System.ArgumentException: Value does not fall within the expected range.
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.ValueSetFactory.NumericValueSet`2.Microsoft.CodeAnalysis.CSharp.IValueSet.get_Sample()
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.SampleValueString(IValueSet remainingValues, TypeSymbol type, Boolean requireExactType, Boolean& unnamedEnumValue)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.<SamplePatternForTemp>g__tryHandleNumericLimits|2_5(Boolean& unnamedEnumValue, <>c__DisplayClass2_0& )
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.SamplePatternForTemp(BoundDagTemp input, Dictionary`2 constraintMap, Dictionary`2 evaluationMap, Boolean requireExactType, Boolean& unnamedEnumValue)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.<SamplePatternForTemp>g__tryHandleUnboxNullableValueType|2_3(Boolean& unnamedEnumValue, <>c__DisplayClass2_0& )
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.SamplePatternForTemp(BoundDagTemp input, Dictionary`2 constraintMap, Dictionary`2 evaluationMap, Boolean requireExactType, Boolean& unnamedEnumValue)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.PatternExplainer.SamplePatternForPathToDagNode(BoundDagTemp rootIdentifier, ImmutableArray`1 nodes, BoundDecisionDagNode targetNode, Boolean nullPaths, Boolean& requiresFalseWhenClause, Boolean& unnamedEnumValue)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.SwitchExpressionBinder.CheckSwitchExpressionExhaustive(SwitchExpressionSyntax node, BoundExpression boundInputExpression, ImmutableArray`1 switchArms, BoundDecisionDag& decisionDag, LabelSymbol& defaultLabel, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.SwitchExpressionBinder.BindSwitchExpressionCore(SwitchExpressionSyntax node, Binder originalBinder, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindExpressionInternal(ExpressionSyntax node, BindingDiagnosticBag diagnostics, Boolean invoked, Boolean indexed)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindExpression(ExpressionSyntax node, BindingDiagnosticBag diagnostics, Boolean invoked, Boolean indexed)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindReturn(ReturnStatementSyntax syntax, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindStatement(StatementSyntax node, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindBlockParts(BlockSyntax node, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindBlock(BlockSyntax node, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindStatement(StatementSyntax node, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindMethodBody(CSharpSyntaxNode declaration, BlockSyntax blockBody, ArrowExpressionClauseSyntax expressionBody, BindingDiagnosticBag diagnostics)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.Binder.BindMethodBody(CSharpSyntaxNode syntax, BindingDiagnosticBag diagnostics, Boolean includesFieldInitializers)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.MethodCompiler.BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics, VariableState nullableInitialState, Boolean reportNullableDiagnostics, Boolean includesFieldInitializers, ImportChain& importChain, Boolean& originalBodyNested, InitialState& forSemanticModel)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileMethod(MethodSymbol methodSymbol, Int32 methodOrdinal, ProcessedFieldInitializers& processedInitializers, SynthesizedSubmissionFields previousSubmissionFields, TypeCompilationState compilationState)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.MethodCompiler.CompileNamedType(NamedTypeSymbol containingType)
  Microsoft.CSharp.Core.targets(75, 5):    at Microsoft.CodeAnalysis.CSharp.MethodCompiler.<>c__DisplayClass25_0.<CompileNamedTypeAsync>b__0()
0

There are 0 best solutions below