-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
Almost complete sync of logic for generating DAM/RUC reflection access warnings between ILLink and NativeAOT #84770
Conversation
…equire dataflow. That one is going to be hard.
Note that the current implementation of override detection only works on overrides of base methods. It does NOT work for overrides/implementations of interface methods.
Tagging subscribers to this area: @agocke, @MichalStrehovsky, @jkotas Issue DetailsThis enables the last of the disabled The implementation basically copies the logic from ILLink on how to produce warnings when method or field is marked due to reflection access. This also introduces a new cache into This had to be a new cache since it requires The new cache should end up being very small/cheap, since we only populate it for compiler generated code which is accessed via reflection (should be rare). There's one missing bit: ILLink has a detection to figure out if a method is an implementation of an interface method and will suppress warnings due to annotations on such method, since the annotation on the interface methods must match. This effectively avoid duplicate warning generation. The NativeAOT implementation doesn't do this for interfaces (only for overrides of base class mehods). This fixes final bits of #68786
|
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.
Left a question. I didn't review the algorithm in detail because it's rather complicated and I already lack quite some context. I still wish we just ignored the fact that compiler-generated things can be reflected on and left it as a wart.
|
||
Method = method; | ||
|
||
bool requiresDataflowProcessing = ReflectionMethodBodyScanner.RequiresReflectionMethodBodyScannerForMethodBody(flowAnnotations, 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.
Is there any reason to introduce a local here instead of setting RequiresDataflow directly? We could add an early out after processing an instruction as well.
public MethodDesc Method; | ||
public bool RequiresDataflow; |
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.
public MethodDesc Method; | |
public bool RequiresDataflow; | |
public readonly MethodDesc Method; | |
public readonly bool RequiresDataflow; |
if (_dataflowRequirementHashtable == null) | ||
throw new InvalidOperationException(); |
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 looks unnecessary. It's not a public API.
=> new DataflowRequirementValue(key, _flowAnnotations); | ||
} | ||
|
||
public void InitializeFlowAnnotations(FlowAnnotations flowAnnotations) |
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 wonder - could we avoid having this double initialization?
Can we for example move the logic that is getting added to CompilerGeneratedState
somewhere else? Can this just be part of the regular FlowAnnotations state? And if not, could this logic be moved to a CompilerGeneratedState
subclass (that is a nested type of FlowAnnotations
) and change FlowAnnotations
ctor to just new it up (instead of taking it as a parameter)?
I must admit I'm starting to agree that we should probably give up on at least some of this. For example I found out that ILLink doesn't warn in all cases of accessing compiler generated code, even when it technically should. I'm going to look into a couple more cases which popped up, just to make sure we're not missing something bigger first though. |
/azp run runtime-extra-platforms |
Azure Pipelines successfully started running 1 pipeline(s). |
This is ready for review. I updated the comment to match the implemented behavior. All the CI failures are unrelated. |
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.
Thank you!
This enables the last of the disabled
RequiresCapability
tests for NativeAOT.The implementation basically copies the logic from ILLink on how to produce warnings when method or field is marked due to reflection access.
We decided that producing warnings due to reflection access to compiler generated methods is more trouble than benefit and thus we won't do that anymore. See reasoning in #85042.
Otherwise the behavior in NativeAOT fully copies the one in ILLink (small exceptions due to better method overload resolution in NativeAOT).
High-level behavior changes in NativeAOT:
ldtoken
and similar). This allows for more precise handling of the cases above.Testing changes:
SkipKepItemsValidationAttribute
- this allows to enable one of the reflection tests for its diagnostics coverage, avoiding the necessity to fix everything around Kept behavior yet.This fixes final bits of #68786
Fixes #68688
This helps with #82447