You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This works as expected, therefore, the value of AnotherConstString will be set to "FooBar" by the compiler. The IL does not contain anything like AConstString + "Bar". Instead, any use of the constant values above will be inlined to its constant value.
This already works as of today. The difference here is that AnotherConstString is clearly a constant value that can be determined at compile time. So what ends up in the IL is a reference to the static field AnotherConstString while CreateAnotherString will be invoked by the static constructor during runtime.
So, if the compiler knew that CreateAnotherString has no side effects and its return value is entirely based on its parameters and the parameters are compile time constants, the compiler itself could evaluate the function.
The function is required to be a pure function. There already is a proposal for pure functions, since they may have additional benefits.
This could also affect cases like these:
publicstaticvoidBaz(intfoo){if(foo<0)thrownew ArgumentException($"{nameof(foo)} must be greater than or equal to zero.");}
Currently, what ends up in the IL will be something like this (translated back to C#):
string.Format("{0} must be greater than or equal to zero.","foo")
If string.Format is a pure function, all parameters are compile time constants, so the compiler could actually invoke string.Format and emit the result instead:
"foo must be greater than or equal to zero."
Of course, if a function is pure, it can remain in the compiled assembly, in case someone invokes it with non-constant parameters.
Evaluating constructors at compile time? (Could it be used for constant immutable structs?)
If a user-defined struct is constant and its overloaded operators can be evaluated by the compiler, something like const Vector2 upLeft = Vector2.Up + Vector2.Left would be a constant expression. This is actually the same thing as in the code of SomeClass above, just using Vector2 instead of string.
Common functions of the framework may be marked as "pure" or "constexpr" (e. g. string.Format, Convert.*, string.Join) without losing compatibility.
Regarding strings: "FooBar" is a compile time constant, so "FooBar".Length or "FooBar".get_Length() may return constant values. Imagine using it in a scenario like str.Remove(str.Length - "RemoveMe".Length), while the code remains maintainable because "RemoveMe".Length is more self-explanatory than just 8. If str is a constant and Remove is a pure function, the entire expression may be computed by the compiler.
This feature would be pretty similar to other languages supporting CTFE, like D or C++11 with constexpr.
Also, CTFE doesn't have to be implemented in the compiler that compiles to IL. It may be also implemented in the JIT or other AOT compilers.
The text was updated successfully, but these errors were encountered:
In the case of static readonly field, what is the point of optimizing the IL? Under normal circumstances (JIT compilation), it will behave as a constant during JIT anyway (i.e. the CLR executes the field initializers and only then JIT compiles the method, knowing the field can't change).
In the case of interpolated strings, string.Format() is not a pure function (it depends on the current culture), so this also wouldn't help (see #9212).
The constant.Length optimization sounds like something the JIT compiler should be able to do (but as far as I can tell, doesn't currently do).
Let's take this code:
This works as expected, therefore, the value of
AnotherConstString
will be set to"FooBar"
by the compiler. The IL does not contain anything likeAConstString + "Bar"
. Instead, any use of the constant values above will be inlined to its constant value.Now take a look at this code:
This already works as of today. The difference here is that
AnotherConstString
is clearly a constant value that can be determined at compile time. So what ends up in the IL is a reference to the static fieldAnotherConstString
whileCreateAnotherString
will be invoked by the static constructor during runtime.The code:
Compiles to this IL (with optimizations enabled):
So, if the compiler knew that
CreateAnotherString
has no side effects and its return value is entirely based on its parameters and the parameters are compile time constants, the compiler itself could evaluate the function.The function is required to be a pure function. There already is a proposal for pure functions, since they may have additional benefits.
This could also affect cases like these:
Currently, what ends up in the IL will be something like this (translated back to C#):
If
string.Format
is a pure function, all parameters are compile time constants, so the compiler could actually invoke string.Format and emit the result instead:Of course, if a function is pure, it can remain in the compiled assembly, in case someone invokes it with non-constant parameters.
Other thoughts:
const Vector2 upLeft = Vector2.Up + Vector2.Left
would be a constant expression. This is actually the same thing as in the code ofSomeClass
above, just using Vector2 instead of string.string.Format
,Convert.*
,string.Join
) without losing compatibility."FooBar"
is a compile time constant, so"FooBar".Length
or"FooBar".get_Length()
may return constant values. Imagine using it in a scenario likestr.Remove(str.Length - "RemoveMe".Length)
, while the code remains maintainable because"RemoveMe".Length
is more self-explanatory than just8
. Ifstr
is a constant andRemove
is a pure function, the entire expression may be computed by the compiler.This feature would be pretty similar to other languages supporting CTFE, like D or C++11 with constexpr.
Also, CTFE doesn't have to be implemented in the compiler that compiles to IL. It may be also implemented in the JIT or other AOT compilers.
The text was updated successfully, but these errors were encountered: