-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ECMA augments regarding instance and type construction. #110343
base: main
Are you sure you want to change the base?
Conversation
Multiple initializations of instances and types might violate runtime invariants, we should forbid it then as discussed in dotnet#109679. Users are not expected to have been relying on the behaviour being legal, especially since multiple type initializations are already resulting in invalid behaviour due to JIT optimizations.
Tagging subscribers to this area: @dotnet/area-meta |
Is there any reason to go this far? Wouldn't it be more sensible to say that it's just unsupported for all the types in the BCL & special types like delegates, enums (not that these can even have ctors), etc. (+ probably also anything else that doesn't explicitly document it as fine, but this library documentation part about other libs in this bracket doesn't seem like a concern for ECMA-335, other than at most as a comment to point out what should be common sense) - but that doesn't mean it should necessarily be invalid in every single case as a blanket rule (not that I wouldn't find such code not suspiscious) (like how we might say it's unsupported to take a |
ECMA spec is concerned about verifiable code only. It touches on valid unverifiable code here and there, but it is very far from having a full precise definition of valid unverifiable code. In general, it leaves the behavior of valid unverifiable code as undefined. I see things like calling constructor multiple times as a potentially valid unverifiable code. |
|
||
The following is added to the section "II.10.5.3 Type initializer": | ||
|
||
> Type initializers shall not be called explicitly from user code. Users intending to guarantee the type initializer has been executed shall use the `System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor` method. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Type initializers shall not be called explicitly from user code
This contradicts "A type initializer shall be executed exactly once for any given type, unless explicitly
called by user code." in the next chapter.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is changed with the next paragraph.
|
||
Section "II.10.5.3.1 Type initialization guarantees" is changed so that the guarantee number 3 now states the following: | ||
|
||
> A type initializer shall be executed exactly once for any given type, unless the previous attempt resulted in a `System.TypeInitializationException` being thrown at the location that triggered it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
unless the previous attempt resulted in a
System.TypeInitializationException
being thrown at the location that triggered it.
I am not sure what this is trying to say.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If a .cctor
throws an exception, the type is not marked as initialized so the .cctor
will be called again by the runtime until it succeeds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's not correct. If the .cctor
throws exception, the runtime won't try to run the .cctor
again. The failure is cached.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not know that, I feel like older versions of legacy Mono might've been non compliant with this cause I recall it being rerun in Unity.
|
||
The following is added to the section "II.10.5.1 Instance constructor": | ||
|
||
> Instance constructors shall not be executed multiple times for a single object instance. Explicit calls to constructors on object instances from user code are only permitted when calling instance constructors of the base type inside of instance constructors of the derived type. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not correct. Try this:
class A
{
A() : this(1)
{
}
A(int x)
{
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, you may want to update the wording in the call
instruction verification rules that have the same mistake: "The call instruction can also be used to call an object’s base class constructor, or to initialize a value type location by calling an appropriate constructor, both of which are treated as special cases by verification.".
It may be sufficient to just fix the call
verification rules to be more precise instead of duplicating it here.
If this is the direction we go, I'd prefer if we explicitly mention something along the lines of the above somewhere at least. I think it would be good to better document stuff around valid unverifiable code. |
Multiple initializations of instances and types might violate runtime invariants, we should forbid them then as discussed in #109679.
Users are not expected to have been relying on the behaviour being legal, especially since multiple type initializations are already resulting in invalid behaviour due to JIT optimizations.
cc @jkotas @tannergooding @EgorBo as discussed.