dotnet / dotnet/csharpstandard

13.8.3 and 12.20 Converted constants in a switch statement

Open
#174 13 comments 0 reactions 0 assignees View on GitHub
type: bug
Dominant language
C#
Stars
815
Forks
99
Avg merge
1d 14h
Merged PRs (30d)
16

Description

See also https://github.com/dotnet/csharplang/issues/1282 where I first reported this, in order to avoid having compiler engineers "fix" the compiler.

There appears to be a bug in the [specification of the `switch` statement](https://github.com/dotnet/csharplang/blob/master/spec/statements.md#the-switch-statement) (13.8.3). This appear in the spec:

> The constant expression of each `case` label must denote a value that is implicitly convertible ([Implicit conversions](https://github.com/dotnet/csharplang/blob/master/spec/conversions.md#implicit-conversions)) to the governing type of the `switch` statement. A compile-time error occurs if two or more `case` labels in the same `switch` statement specify the same constant value.

This permits the following code, which the compiler rejects:

``` c#
{
const int N1 = 1;
const short N2 = 1;
int x = 1;
switch (x)
{
case N1:
case N2: // error CS0152: The switch statement contains multiple cases with the label value '1'
break;
}
}
```

This is permitted by the spec because `N1` and `N2` do not "specify the same constant value". They are not even of the same type.

The simple "fix" would be to require that the ***converted expressions*** do not specify the same constant value. However, that would expose a different problem. In the current spec, a null literal is not a constant value after it has been converted to a nullable type such as `int?`. As a result, the modified rule would permit multiple `null` cases (because they do not specify the same constant value after conversion, as they do not in fact specify a constant value at all after conversion).

I believe the way to fix these issues is to
1. Modify the quoted section to say something like "A compile-time error occurs if two or more `case` labels in the same `switch` statement specify the same constant value after the conversion."
2. In the section [Constant expressions](https://github.com/dotnet/csharplang/blob/master/spec/expressions.md#constant-expressions) (12.20), in the bullet list following the introductory sentence "The following conversions are permitted in constant expressions:", add a new bullet reading "Null literal conversions".

These proposed changes correspond to what the Roslyn compiler actually does.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.