Support DynamicDependencyAttribute#1215
Conversation
a636b5b to
cd07ed1
Compare
| } | ||
| } | ||
|
|
||
| public static IEnumerable<MethodDefinition> GetConstructorsOnType (TypeDefinition type, Func<MethodDefinition, bool> filter, BindingFlags? bindingFlags = null) |
There was a problem hiding this comment.
These are local helpers, right? Why are they public?
There was a problem hiding this comment.
They are also used from ReflectionMethodBodyScanner - so maybe "internal" would be better.
There was a problem hiding this comment.
DynamicallyAccessedMembersBinder is already internal because our copy of DynamicallyAccessedMemberTypes is internal, so I think they are effectively internal already. Generally I prefer to use class-based accessibility modifiers for consistency with the rest of the codebase, especially since we have the ref assembly to control externally-visible public surface.
| #endif | ||
| } | ||
|
|
||
| var dynamicDependencies = Context.Annotations.GetLinkerAttributes<DynamicDependency> (member); |
There was a problem hiding this comment.
I don't think you should use GetLinkerAttributes here, you already iterate all attributes above so this is doing the same loop and also building cache for member which might not be reached at all.
There was a problem hiding this comment.
I originally optimized this a little more, but removed it based on this discussion: #1215 (comment). If you think it is worth it, I could add back the check for this callsite, and only call GetLinkerAttributes if the previous loop found any DynamicDependencyAttributes.
| type = assembly.FindTypeByDocumentationSignature (typeName); | ||
| if (type == null) { | ||
| _context.LogMessage (MessageContainer.CreateWarningMessage ($"Unresolved type '{typeName}' in DynamicDependencyAttribute on '{context}'", 2032)); | ||
| return; | ||
| } | ||
| } else if (dynamicDependency.Type is TypeReference typeReference) { | ||
| type = typeReference.Resolve (); | ||
| if (type == null) { | ||
| _context.LogMessage (MessageContainer.CreateWarningMessage ($"Unresolved type '{typeReference}' in DynamicDependencyAtribute on '{context}'", 2032)); | ||
| return; | ||
| } | ||
| } else { | ||
| type = context.DeclaringType.Resolve (); | ||
| if (type == null) { | ||
| _context.LogMessage (MessageContainer.CreateWarningMessage ($"Unresolved type '{context.DeclaringType}' in DynamicDependencyAttribute on '{context}'", 2032)); | ||
| return; | ||
| } |
There was a problem hiding this comment.
I'm tempted for this logic to respect --skip-unresolved
There was a problem hiding this comment.
That is good point. Curious: do normal apps run linker with --skip-unresolved or is that more of a corner case option?
There was a problem hiding this comment.
It's not a default option it's more about avoiding the aggressive context loading again
There was a problem hiding this comment.
We do pass it when running the linker from the SDK. As I understand it, that option enables the linker to continue from resolution failures (see #260) instead of crashing. I don't think we need to respect it here since these warnings won't fail the build. I think that if --skip-unresolved is false, the call to Resolve() would cause an AssemblyResolutionException before we get a chance to log this warning.
b8886a1 to
4668aae
Compare
6382f4c to
cd21177
Compare
|
Let's land #1223 before this PR |
5ce7a13 to
bff9585
Compare
Instead of type itself for DynamicallyAccessedMemberTypes.All
- Use IMemberDefinition as key - Remove optimization for DynamicDependencyAttribute case - Add optimization to check for presence of attributes in the cache - Add checking of member types for the attributes
Co-authored-by: Vitek Karas <vitek.karas@microsoft.com>
- Remove assert - Move helpers to signature parser - Consolidate warning messages
We will keep supporting it for now, and remove support for it once runtime has been converted to DynamicDependency
bff9585 to
1136f0a
Compare
|
@marek-safar I've addressed your feedback. PTAL |
marek-safar
left a comment
There was a problem hiding this comment.
Few minor issues, otherwise LGTM
| if (!(args[2].Value is string assemblyName)) | ||
| return null; | ||
|
|
||
| var dynamicDependency = memberSignature == null ? new DynamicDependency (memberTypes!.Value, typeName, assemblyName) : new DynamicDependency (memberSignature, typeName, assemblyName); |
There was a problem hiding this comment.
| var dynamicDependency = memberSignature == null ? new DynamicDependency (memberTypes!.Value, typeName, assemblyName) : new DynamicDependency (memberSignature, typeName, assemblyName); | |
| return new DynamicDependency (memberSignature ?? memberTypes!.Value, typeName, assemblyName) { | |
| OriginalAttribute = ca | |
| }; |
There was a problem hiding this comment.
That doesn't type-check because memberTypes!.Value isn't a string.
There was a problem hiding this comment.
It needs to call a different ctor for string vs DynamicallyAccessedMemberTypes. memberSignature ?? memberTypes!.Value doesn't have a well-defined type - it produces error CS0019: Operator '??' cannot be applied to operands of type 'string' and 'DynamicallyAccessedMemberTypes'.
- Remove left-over dead code, imports - Fix typos - Don't respect Condition on DynamicDependencyAttribute
* Add DynamicDependencyAttribute * Add tests for DynamicDependencyAttribute * Test PreserveDependency on illink, disable on mono * Add more tests for DynamicDependency * Fix whitespace and failing test * Fix mono build with LangVersion latest * Use null sentinel Instead of type itself for DynamicallyAccessedMemberTypes.All * Changes to attribute caching - Use IMemberDefinition as key - Remove optimization for DynamicDependencyAttribute case - Add optimization to check for presence of attributes in the cache - Add checking of member types for the attributes * Use Attribute type in cache, and move helpers to DynamicDependency * Remove DynamicDependencyAttribute implementation * Don't disable flow analysis for Dynamic/PreserveDependency * Add tests for DynamicallyAccessedMemberTypes * Update docs/error-codes.md Co-authored-by: Vitek Karas <vitek.karas@microsoft.com> * PR feedback - Remove assert - Move helpers to signature parser - Consolidate warning messages * Fix up tests * Make PreserveDependency deprecated We will keep supporting it for now, and remove support for it once runtime has been converted to DynamicDependency * PR feedback - Remove left-over dead code, imports - Fix typos - Don't respect Condition on DynamicDependencyAttribute * Use new logging helpers * More PR feedback * Use Resolve () instead * Update one more logging callsite Co-authored-by: Vitek Karas <vitek.karas@microsoft.com> Commit migrated from dotnet/linker@6ec3d0f
This adds support for DynamicDependencyAttribute, which uses the doc comment signature parser from #1197.
The behavior of the lookup step is pretty much kept the same - it will resolve assemblies from attributes, without recursively processing attributes from those assemblies. I originally started to do the recursive processing, but we agreed not to change it here since it is related to the broader work to enable adding new assemblies to the context in MarkStep, and there were concerns about the performance of loading extra unnecessary assemblies into the context.