dotnet / dotnet/csharpstandard
13.8.3 and 12.20 Converted constants in a switch statement
- 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
Assessment
This issue has not been assessed yet.