-
Notifications
You must be signed in to change notification settings - Fork 128
Fix warnings for DAM.All #2191
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
Fix warnings for DAM.All #2191
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -127,7 +127,17 @@ public void ApplyDynamicallyAccessedMembersToType (ref ReflectionPatternContext | |
| // Handle cases where a type has no members but annotations are to be applied to derived type members | ||
| reflectionPatternContext.RecordHandledPattern (); | ||
|
|
||
| MarkTypeForDynamicallyAccessedMembers (ref reflectionPatternContext, type, annotation, DependencyKind.DynamicallyAccessedMemberOnType); | ||
| // The annotations this type inherited from its base types should not produce | ||
| // warnings on the base members, since those are covered by warnings in the base type. | ||
| // For now, annotations that are inherited from base types but also declared explicitly on this type | ||
| // still warn about base members since the cache doesn't track enough information to tell the difference. | ||
| var declaredAnnotation = _context.Annotations.FlowAnnotations.GetTypeAnnotation (type); | ||
| var inheritedOnlyAnnotation = annotation & ~declaredAnnotation; | ||
|
|
||
| // Warn about all members accessed by the annotation on this type (including members of base types/interfaces) | ||
| MarkTypeForDynamicallyAccessedMembers (ref reflectionPatternContext, type, declaredAnnotation, DependencyKind.DynamicallyAccessedMemberOnType, declaredOnly: false); | ||
| // Warn about members accessed by inherited annotations (not including members of base types/interfaces) | ||
| MarkTypeForDynamicallyAccessedMembers (ref reflectionPatternContext, type, inheritedOnlyAnnotation, DependencyKind.DynamicallyAccessedMemberOnType, declaredOnly: true); | ||
| } | ||
|
|
||
| ValueNode GetValueNodeForCustomAttributeArgument (CustomAttributeArgument argument) | ||
|
|
@@ -2285,9 +2295,9 @@ void RequireDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionC | |
|
|
||
| static bool HasBindingFlag (BindingFlags? bindingFlags, BindingFlags? search) => bindingFlags != null && (bindingFlags & search) == search; | ||
|
|
||
| void MarkTypeForDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionContext, TypeDefinition typeDefinition, DynamicallyAccessedMemberTypes requiredMemberTypes, DependencyKind dependencyKind) | ||
| void MarkTypeForDynamicallyAccessedMembers (ref ReflectionPatternContext reflectionContext, TypeDefinition typeDefinition, DynamicallyAccessedMemberTypes requiredMemberTypes, DependencyKind dependencyKind, bool declaredOnly = false) | ||
| { | ||
| foreach (var member in typeDefinition.GetDynamicallyAccessedMembers (_context, requiredMemberTypes)) { | ||
| foreach (var member in typeDefinition.GetDynamicallyAccessedMembers (_context, requiredMemberTypes, declaredOnly)) { | ||
| switch (member) { | ||
| case MethodDefinition method: | ||
| MarkMethod (ref reflectionContext, method, dependencyKind); | ||
|
|
@@ -2296,8 +2306,7 @@ void MarkTypeForDynamicallyAccessedMembers (ref ReflectionPatternContext reflect | |
| MarkField (ref reflectionContext, field, dependencyKind); | ||
| break; | ||
| case TypeDefinition nestedType: | ||
| DependencyInfo nestedDependencyInfo = new DependencyInfo (dependencyKind, reflectionContext.Source); | ||
| reflectionContext.RecordRecognizedPattern (nestedType, () => _markStep.MarkEntireType (nestedType, includeBaseAndInterfaceTypes: true, nestedDependencyInfo)); | ||
| MarkType (ref reflectionContext, nestedType, dependencyKind); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I must admit I'm a bit nervous about potential endless recursion. After all that's why If I remember correctly the counter example for class MyAttribute : Attribute
{
MyAttribute([DAM(All)] Type type) {}
}
[MyAttribute(typeof(TestType))]
class TestType
{
}This would be endless since I think this new code will work, since So I guess there's no problem in the end, I hope...
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add a test case along these lines. The base type one would look like: class Base<[DAM(All)] T> {}
class TestType : Base<TestType> {}Similarly for interfaces. Another one is attributes on members: We already have an issue with this on properties and other members - see #2196 (I just created this). The All is basically just another case of the same problem for these members.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, the first example is already covered by this test: https://github.com/mono/linker/blob/e21bb44ca909d33c18acf3ed0b68f94a413351a5/test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs#L96-L100. I added the second testcase you suggested - I think generic type parameters shouldn't be an issue since the DAM binder only gives back members and doesn't look at the instantiated base generic type at all (instead it relies on normal MarkType logic to mark generic arguments). Good find about attributes on properties/events.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That was the point - I don't think But I'm fine if we try to cover this later on.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, it looks like it was at least given some thought but it's good to have more tests as we add more ways to get to MarkType. I did add the generic tests you suggested above so I think that is covered. |
||
| break; | ||
| case PropertyDefinition property: | ||
| MarkProperty (ref reflectionContext, property, dependencyKind); | ||
|
|
@@ -2308,10 +2317,6 @@ void MarkTypeForDynamicallyAccessedMembers (ref ReflectionPatternContext reflect | |
| case InterfaceImplementation interfaceImplementation: | ||
| MarkInterfaceImplementation (ref reflectionContext, interfaceImplementation, dependencyKind); | ||
| break; | ||
| case null: | ||
sbomer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| DependencyInfo dependencyInfo = new DependencyInfo (dependencyKind, reflectionContext.Source); | ||
| reflectionContext.RecordRecognizedPattern (typeDefinition, () => _markStep.MarkEntireType (typeDefinition, includeBaseAndInterfaceTypes: true, dependencyInfo)); | ||
| break; | ||
| } | ||
| } | ||
| } | ||
|
|
||
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 think this is fine - the only case where I can think of this making sense is if the derived type adds more annotations (base has all methods and derived type has both methods and fields) - but that is SO unlikely and rare - I don't care :-).