Add option to disable interface sweeping#649
Conversation
|
It would be nice to add tests |
|
@mrvoorhe I added two tests, including one to validate the current ability to remove interfaceimpls on uninstantiated types. By the way - if this behavior is controversial, I'm happy to make a larger change that will preserve interfaceimpls in more cases - however I'd like to get this PR in as soon as possible since we are trying to enable it in coreclr/corefx. @marek-safar PTAL. |
57fe772 to
a157e28
Compare
|
I'm fine with it. I think someone is going to be a little confusing that uninstantiated types still get their interfaces swept at some point. But at the same time the optimizations made for uninstantiated types are in some ways their own separate feature. |
|
The mono job failure doesn't appear related to the change: |
marek-safar
left a comment
There was a problem hiding this comment.
Could you attach the actual case where you are hitting this? It might be actually bug and the option will not be needed. My thinking is if the interface is in assembly which is linked but the interface is also used in assembly which is copied the interface need to be marked fully.
|
@marek-safar here's an example from System.Collections. As I mentioned, corefx links individual assemblies, so the interface type doesn't get marked if it's from a referenced (not copied) assembly. The |
+1. I agree that this looks like a bug and the option should not be really needed if the bug is fixed. |
|
Would it be fine to sweep the implementation of an interface only if it's private? This seems to be removing them for public types implementing public interfaces that aren't used internally, which definitely sounds like a bug. For instance, in |
|
I generally like the suggestion to treat implementations of public interfaces as public surface area - that would be the right thing to do for corefx. If we treat the current behavior as a bug, we need to consider what the desired behavior is, since the feature was originally designed to remove interfaceimpls when the interface type is not used (which is the case in the corefx setup). I'm working on this in #657. |
No. We want public interfaces removed if they are not used. If you wanted all public interfaces in an assembly to survive you would pass the assembly to the linker with @sbomer I don't entirely follow what the issue is. The link you gave doesn't have any context so it's hard to know what should happen. Can you elaborate? or can you write a linker test case that produces invalid IL? |
|
@mrvoorhe my apologies - hopefully I can clear up the context: Corefx is using the linker (with
I think @lpereira's suggestion makes sense in that context (though in other circumstances like linking an app, we might still want to remove impls of public interfaces when they're not used). In any case, this PR solved the problem by turning off the optimization. As @marek-safar and @jkotas suggested, from the corefx point of view this is a bug, so we might instead want to fix the behavior of |
|
@sbomer Thanks for clarifying. I was starting to piece it together after I saw the other PR. |
When linking an individual corefx library, classes that implement an interface from another assembly may have .interfaceimpls swept for interface types that are not used (because they come from another assembly which is not rooted). This adds an option to disable interface sweeping, allowing us to keep all .interfaceimpls for instantiated types. Note that uninstantiated types may still have unused .interfaceimpls swept and the implementation override methods removed.
This adds testcases to check: - interfaceimpls are kept when interface sweeping is disabled - uninstantiated types still get interfaceimpls removed, even with interface sweeping disabled
9ba6fcb to
82c4ae2
Compare
|
@marek-safar I put the option to disable interface sweeping under a define like we discussed (there still needs to be a command-line option since we will flow the same build of the linker to both the SDK and coreclr/corefx), while we consider other approaches. @tlakollo is validating the diff with this change to ensure it will unblock corefx/coreclr's linker update. PTAL. |
| return false; | ||
|
|
||
| if (Annotations.IsMarked (resolvedInterfaceType) && !Annotations.IsMarked (iface)) | ||
| if (Annotations.IsMarked (resolvedInterfaceType)) |
There was a problem hiding this comment.
Where did !Annotations.IsMarked (iface)) check go?
There was a problem hiding this comment.
Annotations.IsMarked (iface) is already false by the time we get here due to the check above.
|
@marek-safar PTAL |
* Add option to disable interface sweeping When linking an individual corefx library, classes that implement an interface from another assembly may have .interfaceimpls swept for interface types that are not used (because they come from another assembly which is not rooted). This adds an option to disable interface sweeping, allowing us to keep all .interfaceimpls for instantiated types. Note that uninstantiated types may still have unused .interfaceimpls swept and the implementation override methods removed. * Add testcases for disabling interface sweeping This adds testcases to check: - interfaceimpls are kept when interface sweeping is disabled - uninstantiated types still get interfaceimpls removed, even with interface sweeping disabled * Update usage and fix style * Hide option under a define * Make unusedinterfaces option generally available * Fix semicolon, rename testcase Commit migrated from dotnet/linker@e092fdb
When linking an individual corefx library, classes that implement an
interface from another assembly may have .interfaceimpls swept for
interface types that are not used (because they come from another
assembly which is not rooted).
This adds an option to disable interface sweeping, allowing us to keep
all .interfaceimpls for instantiated types. Note that uninstantiated
types may still have unused .interfaceimpls swept and the
implementation override methods removed.