csharplang icon indicating copy to clipboard operation
csharplang copied to clipboard

`is` expression evaluating `const` expression should be considered constant

Open 333fred opened this issue 2 years ago • 5 comments

Discussed in https://github.com/dotnet/csharplang/discussions/6925

Originally posted by Rekkonnect January 28, 2023

Summary

Despite being provided a constant expression, using an is pattern is not considered constant. This can be safely adjusted. As an added bonus, a warning is generated by code flow analysis saying that the expression always evaluates to true or false.

Motivation

Conditional compilation symbols, reliance on runtime constants deriving from conditional statements

Description

You cannot assign an is expression on constant LHS value to a constant field. For example,

public const int A = 4;
public const bool B = A is 4; // illegal, despite the result being available for constant evaluation
public const bool C = A is not 3 and < 1 or 5; // illegal too

In the example above, A is 4 is A == 4, but is not treated as such. A == 4 passes, A is 4 does not. My personal preference is using is wherever available, especially on enum constants, which also allows for extensibility of the pattern.

Since patterns on the RHS of the pattern matching expression are always constant (as of now), the only limitation is the LHS also being a constant expression.

Example

Consider the following repro for determining where to publish a NuGet package.

Design meetings

  • https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-10-09.md#is-expression-evaluating-const-expression-should-be-considered-constant
  • https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-11-27.md#making-patterns-constant-expressions

333fred avatar Jan 28 '23 16:01 333fred

If code determinism (aka. "constexpr") is implemented, we would get this for free.

list of possible relevant discussions/issues:

Unknown6656 avatar Feb 11 '23 10:02 Unknown6656

But C++ is a compiled ahead language, C# goes through the JIT which should do const folding on public const bool C = A is not 3 and < 1 or 5;

Should trust JIT compiler on client machine to convert everything undetermined to determined, because it can generate cache and analyse hot path for code

Xyncgas avatar Jun 12 '23 01:06 Xyncgas

A is not 3 and < 1 or 5 is an expression that can be evaluated during compile time, since A is constant and the RHS are all constant expressions, thus making it eligible for a constant expression. Roslyn has some form of constexpr evaluation because of the way constant expressions are evaluated and assigned to the constant fields and locals, including string literals and arithmetic expressions.

The above comment mentioning determinism does not actually interfere with this proposal, aside from being able to "get it for free" if something similar to constexpr is brought into C#.

Constants should never be evaluated during runtime in the JIT, they are fixed values that the program is shipped with, without preserving the expression leading to the result. That's the intent of a constant.

Rekkonnect avatar Jun 13 '23 07:06 Rekkonnect

This was discussed in LDM on https://github.com/dotnet/csharplang/blob/main/meetings/2023/LDM-2023-10-09.md#is-expression-evaluating-const-expression-should-be-considered-constant. It was approved for any time, meaning that it is open for community contribution. The first thing this needs is an approved specification: someone will need to go through the constant expressions part of the specification (https://github.com/dotnet/csharpstandard/blob/draft-v8/standard/expressions.md#1223-constant-expressions) and specify how exactly each type of pattern will work in a constant context (if it will even work at all). Once this is done, the LDM can look at the proposed specification and potentially approve it.

333fred avatar Oct 09 '23 22:10 333fred

I'd like to take up on that

Rekkonnect avatar Oct 09 '23 22:10 Rekkonnect