-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Introduces a peverify-compat feature flag #21269
Conversation
- Made readonly fields homeless outside the constructor when flag is set.
@VSadov, so the default will be faster unverifiable code, but there will be an option to enable the slower verifiable code, correct? Is this a case where we could get peverify updated to have knowledge about 'readonly' structs/fields? |
@tannergooding - peverify as a tool is a bit of deadend at the moment. The most likely vehicle for smarter rules is this, once it is more mature: https://github.com/dotnet/corert/tree/master/src/ILVerify |
test windows_release_vs-integration_prtest please These still fail once in a while in our branch. Likely fixed in master. |
@dotnet/roslyn-compiler - please review |
As @VSadov noted, the problem is that peverify is not evolving at the moment. The code we generate is still type safe and can be verified as such according to verification rules we've sketched out. Need a new tool to catch up with our code :) |
@jaredpar, so this is essentially a safety fallback for users who still rely on |
@@ -163,6 +163,8 @@ internal override CommonAnonymousTypeManager CommonAnonymousTypeManager | |||
/// </summary> | |||
internal bool FeatureStrictEnabled => Feature("strict") != null; | |||
|
|||
internal bool FeaturePEVerifyCompatEnabled => Feature("peverify-compat") != null; |
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.
Please add xml doc as above. #Resolved
CompileAndVerify(comp, verify: false, expectedOutput: @" | ||
3 | ||
42 | ||
2 |
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.
The output is different from above. That seems surprising. #WontFix
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 understand printing 2 here, but why 3 when peverify-compat is off? #WontFix
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.
Oh, I get it now. Passes a references to f
instead of evaluating it. #WontFix
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'm also concerned about this case. Is there a way to describe the cases which have observable changes and exclude them from peverify-compat? #WontFix
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.
The output is different because the flag currently deoptimizes overal treatment of readonly fields as lvalues in readonly context. Thus it affects scenarios where removing aliasing is observable. Generally those are scenarios involving readonly ref
This makes me think that perhaps we should not deoptimize those.
It could be hard, however, to distinguish situations where new features are involved since that could be very indirect.
#WontFix
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.
Basically, in the simplest case, - if you pass a readonly field to an in
parameter do you want:
1 - never pass it by reference (defeats the purpose of the in
, definitely no )
2 - always pass it by reference (triggers peverify complains)
3 - change the behavior based on the compat flag (some contorted code may see the difference)
We have #3
right now.
#WontFix
I wouldn't use the word safety here because of the nature of the problem. Nothing is unsafe here, peverify is just not keeping up with the language. I prefer thinking of it as a release valve for customers who are impacted by this change. Our expectation is that this customer doesn't exist but given this is going into a point release of the language want to have a backup plan. #WontFix |
@@ -137,6 +137,11 @@ private bool IsDebugPlus() | |||
return _module.Compilation.Options.DebugPlusMode; | |||
} | |||
|
|||
private bool IsPEVerifyCompatible() |
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.
Name sits wrong with me. Think it would read better as matching the option name. Say: EnablePEVerifyCompat
#Resolved
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.
IL_003c: ldflda ""MyManagedStruct.Nested.Nested1 MyManagedStruct.Nested.n"" | ||
IL_0032: ldfld ""MyManagedStruct cls1.y"" | ||
IL_0037: ldfld ""MyManagedStruct.Nested MyManagedStruct.n"" | ||
IL_003c: ldfld ""MyManagedStruct.Nested.Nested1 MyManagedStruct.Nested.n"" | ||
IL_0041: ldfld ""int MyManagedStruct.Nested.Nested1.num"" | ||
IL_0046: call ""void System.Console.WriteLine(int)"" | ||
IL_004b: ret | ||
} | ||
"); | ||
} | ||
|
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.
Let's add a test trait for PEVerifyCompat mode and mark the new tests as such. That will make it easy to remove the feature later on if we make that decision. #Resolved
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.
compiling with WithPEVerifyCompatFeature is a fairly robust indication, but can add a trait too.
In reply to: 131440583 [](ancestors = 131440583)
From discussion with Vlad, it is surprising that an "optimization" or "de-optimization" would have observable effects. The new language semantics need to be documented.
From further discussion, this observable change is an acceptable break (very corner case). #Resolved |
Discussed further. - The goal of the flag is a last resort way to suppress peverify errors. It would not be generally used or recommended as a long term solution. In reply to: 320316384 [](ancestors = 320316384) |
any more suggestion on this one? |
@dotnet/roslyn-compiler - PING |
@VSadov When this flag is documented, consider adding a recommendation similar to the following:
|
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.
LGTM
In some scenarios we have a choice of emitting faster code that is typesafe, but not formally verifiable vs. less efficient but verifiable code.
The most common occurrence is around accessing readonly fields of structs. If the intent is only to read, then we could just get a field reference and read to it.
However verification rules do not make distinction when reference is used only to read and require that intermediate copy of the field value be made.
The flag allows suppressing peverify violations, where possible, typically at the cost of introducing intermediate copying.