-
Notifications
You must be signed in to change notification settings - Fork 128
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
Unnecessary warnings for DiagnosticSourceEventSource #2136
Comments
The warnings are being produced because we keep all members of
|
@LakshanF for context - another issue with EventSource marking. This might be fixed once we switch from using But honestly that's just luck. (That said, why does this class use so many nested types? It seems it would be cleaner to just make them into standalone classes... ) What I'm most worried about going forward is the fact that we will have to have |
@sbomer - shouldn't the warnings be suppressed by the UnconditionalSuppressMessage and RequiresUnreferencedCode attributes? |
Some people write code that way - all contained inside the class that uses it. It's a style/preference thing, I think. |
The warnings are generated because the linker thinks that the RUC annotated methods are being accessed via reflection (due to the The fact that the EventSource will never call any of these methods (actually any methods at all) via reflection is something linker currently doesn't track, so it has to assume the worst (which is that they will be called). |
I think there's another interesting question here which is why we didn't see these warnings in the runtime repo build. Not in the per-assembly runs (that's something we're working on currently and it's not supposed to work yet), but in the analysis run. That should have seen enough to raise these warnings... |
Do we need the properties? Prior to the change to All to accommodate NestedTypes, we had only methods (and nested types) looking at the history. |
Interesting - the scope stack is different when we get to
The issue seems to be that the Did we write down anywhere how |
That might solve another mystery for me. I tried paring down the repro to just using HttpClient client = new();
Console.WriteLine(client.GetStringAsync("http://www.msn.com").Result); That app produces no warnings. |
This is tricky :-( We should definitely fix linker to be deterministic and order independent, but how is an interesting question. That means it would be better to raise the warning on the annotated type (in this case But that brings another problem which is that there's no good way to suppress the warning if necessary (like in this case). Putting the suppression on the type will work, but it will also suppress all such warnings in all methods of that type, it doesn't mean "just the type declaration". This leads me to another possibility - currently we issue the same warning Note that for #1764 we will introduce a new warning (for example So in short, the idea is to:
The thinking behind this could also be that by deriving from class Base<T> where T : new () {}
class Derived<T> : Base<T> {} // This warns since T does not have new() constraint - the derived type is blamed, since Base clearly stated its requirements. Alternative: typeof(foo).GetMethod("RUCMethod"); // This should definitely warn on this line
typeof(foo).GetMethods(); // This could now warn on the foo.RUCMethod instead which is weird
foo a; a.GetType(); // This would warn on foo.RUCMethod; |
Actually one last alternative - have a special warning code just for this (type hierarchy marking induced warnings). That would make the suppression exact and would allow us to provide the best warning message. And having yet another warning code doesn't sound that bad. |
This sounds like a pretty clean solution! |
Based on suggestion from @sbomer - one other solution:
So the behavior would be something like: [DynamicallyAccessedMembers(PublicMethods | PublicFields)]
class Base {}
class Derived : Base
{
// IL2300: Type `Derived` or one of its base types is annotated with `DynamicallyAccessedMembers` attribute which
// instructs the trimmer to keep member `DangerousMethod()`. This member is potentially incompatible with trimming
// and is annotated with `RequiresUnreferencedCode`: Dangerous.
[RequiresUnreferencedCode("Dangerous")]
public void DangerousMethod() {}
// IL3201: Type `Derived` or one of its base types is annotated with `DynamicallyAccessedMembers` attribute which
// instructs the trimmer to keep member `AnnotatedTypeField` as it might be accessed via reflection. The member is
// itself annotated with `DynamicallyAccessedMembers` attribute and the trimmer can't guarantee all the requirements
// when the member is accessed via reflection.
[DynamicallyAccessedMembers(PublicProperties)]
public Type AnnotatedTypeField;
} This looks pretty good from a UX perspective. It also makes suppressing these straightforward and very precise - just add the correct |
In case it wasn't clear - I like this last solution the best - raise the warning on the RUC method itself with new warning code. |
Why should the second scenario warn (on class Derived {
void M() {
var f = this.GetType().GetField("AnnotatedTypeField"); // fine due to the annotation
f.SetValue(null, typeof(Foo)); // dynamic assignment violates the annotation
f.GetValue(null).GetMethod("SomeMethod"); // should already warn because we don't know the type
}
} edit: I guess the concern is something like this: void M() {
var m = this.GetType().GetMethod("MethodWithDAMTParameter");
m.Invoke(null, new object[] {typeof(Foo)}); // violates the annotation
} but I think we can hit that today without type hierarchy marking. To fix that, I think dynamically invoking a method should produce a warning for pretty much the same reason that MakeGenericType does - we can't validate annotations dynamically. I see that we can get there for the field example too, if instead of |
Never mind - sounds like the plan is to warn on the initial |
How do we want this to work for derived types which are annotated? class Base {
[RUC]
public static void RUC() {}
}
[DAMT.PublicMethods]
class AnnotatedDerived : Base { } Here if the warning originates on |
dotnet publish
the following application:Expected results
There shouldn't be any ILLink warnings, since I am not using code that is unsafe.
Actual results
Notes
The APIs that are getting warned about all either have
RequiresUnreferencedCodeAttribute
orUnconditionalSuppressMessage
, so I don't understand why the linker is warning here. All those methods are internal implementation details ofDiagnosticSourceEventSource
. See the code here:https://github.com/dotnet/runtime/blob/2be4fdc81f7f190ac35646ccc18799deb05da7dd/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/DiagnosticSourceEventSource.cs#L650-L661
As far as I can tell, DiagnosticSource is referenced by System.Net.Http, which is referenced by XmlDownloadManager. However, when I used
HttpClient
by itself in an app, I couldn't get the warnings to show up.cc @vitek-karas @sbomer @marek-safar
The text was updated successfully, but these errors were encountered: