Skip to content

Support DynamicDependencyAttribute#1215

Merged
sbomer merged 21 commits into
dotnet:masterfrom
sbomer:dynamicDependencyAttribute
Jun 5, 2020
Merged

Support DynamicDependencyAttribute#1215
sbomer merged 21 commits into
dotnet:masterfrom
sbomer:dynamicDependencyAttribute

Conversation

@sbomer
Copy link
Copy Markdown
Member

@sbomer sbomer commented May 26, 2020

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.

Comment thread docs/error-codes.md Outdated
Comment thread src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs Outdated
Comment thread src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs Outdated
Comment thread src/linker/Linker.Steps/MarkStep.cs Outdated
Comment thread src/linker/Linker.Steps/MarkStep.cs Outdated
Comment thread src/linker/Linker/LinkerAttributesInformation.cs Outdated
Comment thread src/linker/Linker/LinkerAttributesInformation.cs Outdated
Comment thread src/linker/Linker/LinkerAttributesInformation.cs Outdated
@sbomer sbomer force-pushed the dynamicDependencyAttribute branch from a636b5b to cd07ed1 Compare May 27, 2020 21:53
@sbomer sbomer marked this pull request as ready for review May 28, 2020 00:24
@sbomer sbomer requested a review from marek-safar as a code owner May 28, 2020 00:24
@sbomer sbomer requested a review from MichalStrehovsky May 28, 2020 00:24
Comment thread src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs
Comment thread src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs
Comment thread src/linker/Linker.Dataflow/DynamicallyAccessedMembersBinder.cs Outdated
}
}

public static IEnumerable<MethodDefinition> GetConstructorsOnType (TypeDefinition type, Func<MethodDefinition, bool> filter, BindingFlags? bindingFlags = null)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are local helpers, right? Why are they public?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are also used from ReflectionMethodBodyScanner - so maybe "internal" would be better.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/linker/Linker/DynamicDependency.cs Outdated
Comment thread src/linker/Linker/AssemblyUtilities.cs Outdated
Comment thread src/linker/Linker.Dataflow/ReflectionMethodBodyScanner.cs Outdated
Comment thread src/linker/Linker.Steps/MarkStep.cs Outdated
Comment on lines +608 to +620
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;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm tempted for this logic to respect --skip-unresolved

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is good point. Curious: do normal apps run linker with --skip-unresolved or is that more of a corner case option?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a default option it's more about avoiding the aggressive context loading again

Copy link
Copy Markdown
Member Author

@sbomer sbomer May 29, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread src/linker/Linker.Steps/MarkStep.cs Outdated
@marek-safar
Copy link
Copy Markdown
Contributor

Let's land #1223 before this PR

@sbomer sbomer force-pushed the dynamicDependencyAttribute branch 2 times, most recently from 5ce7a13 to bff9585 Compare June 2, 2020 16:31
@sbomer sbomer requested a review from marek-safar June 3, 2020 18:04
sbomer and others added 16 commits June 4, 2020 00:24
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
@sbomer sbomer force-pushed the dynamicDependencyAttribute branch from bff9585 to 1136f0a Compare June 4, 2020 00:41
@sbomer
Copy link
Copy Markdown
Member Author

sbomer commented Jun 4, 2020

@marek-safar I've addressed your feedback. PTAL

Copy link
Copy Markdown
Contributor

@marek-safar marek-safar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few minor issues, otherwise LGTM

Comment thread src/linker/Linker.Steps/MarkStep.cs Outdated
Comment thread src/linker/Linker/AssemblyUtilities.cs Outdated
Comment thread src/linker/Linker.Steps/MarkStep.cs Outdated
Comment thread src/linker/Linker/DynamicDependency.cs Outdated
if (!(args[2].Value is string assemblyName))
return null;

var dynamicDependency = memberSignature == null ? new DynamicDependency (memberTypes!.Value, typeName, assemblyName) : new DynamicDependency (memberSignature, typeName, assemblyName);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
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
};

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That doesn't type-check because memberTypes!.Value isn't a string.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What type check?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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'.

Comment thread src/linker/Linker/LinkerAttributesInformation.cs Outdated
Comment thread src/linker/Linker/LinkerAttributesInformation.cs Outdated
Comment thread src/linker/Linker/TypeDefinitionExtensions.cs Outdated
Comment thread src/linker/System.Diagnostics.CodeAnalysis/DynamicDependencyAttribute.cs Outdated
sbomer added 2 commits June 5, 2020 17:39
- Remove left-over dead code, imports
- Fix typos
- Don't respect Condition on DynamicDependencyAttribute
@sbomer sbomer requested a review from mateoatr June 5, 2020 18:39
@sbomer
Copy link
Copy Markdown
Member Author

sbomer commented Jun 5, 2020

@mateoatr could you review the last commit in particular? 82eca9c
I removed parameters to one of the ctors because I don't think we will have line numbers without a source file.

Comment thread src/linker/Linker.Steps/MarkStep.cs Outdated
Comment thread src/linker/Linker/DynamicDependency.cs Outdated
@sbomer sbomer merged commit 6ec3d0f into dotnet:master Jun 5, 2020
tkapin pushed a commit to tkapin/runtime that referenced this pull request Jan 31, 2023
* 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants