-
Notifications
You must be signed in to change notification settings - Fork 127
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
IL1012: Fatal error in IL Linker: IsMethodNeededByInstantiatedTypeDueToPreservedScope(...) throws InvalidOperationException() #3112
Comments
Do you have sample we could use to reproduce it? /cc @vitek-karas |
/cc @jtschuster |
Build in Release configuration to reproduce the error |
Thanks a lot for the repro. Some observations: This fails with 7.0 linker, but works with Release build of main (8.0 linker). linker/src/linker/Linker/Annotations.cs Line 506 in 9c993bf
with callstack:
|
@sbomer for the marking and delay marking logic from custom steps. The assert is happening because the custom step calls AddPreservedMethod twice for the exact same thing: But first time the type is not marked yet, while second time it already is - but it's pending preserved methods have not been marked yet (I think). I don't know if this is the root cause of the 7.0 failure though. |
There was no issue with linker on .NET 6 btw |
The 7.0 failure seems to be a different issue. Debug build of 7.0 fails on the same assert as 8.0, but the failure in Release happens much later on. Also on a completely different method. It fails when it's doing The problem is that |
In 8.0 this code looks somewhat different and there's only Definitely worth looking into even in 8.0 to make sure this is not a problem. |
In theory it might be possible to work around this by introducing fake references to specific things earlier on to change the order in which linker processes methods and thus avoiding the case described above. So far I wasn't able to figure out exactly what to do to make that happen though. |
From an initial look over the code I don't understand how |
These are my notes from the debugging session (already forgot the details 😉) First call ProcessMethod - {System.Boolean MvvmCross.DroidX.RecyclerView.MvxGuardedGridLayoutManager::SupportsPredictiveItemAnimations()} Leads to AnnotationStore.GetBaseMethods for that method Which goes into TypeMapInfo EnsureProcessed for {Xamarin.AndroidX.RecyclerView, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null} MapType - type = {AndroidX.RecyclerView.Widget.RecyclerView} Which will look for base method of {System.Boolean AndroidX.Core.View.INestedScrollingChild::get_HasNestedScrollingParent()} (one of the interfaces implemented by the above view) Which is And it ends up adding this pair to the map. Second call ProcessMethod - {System.Void Android.Views.View::.ctor(Android.Content.Context)} This will call the failure point: IsMethodNeededByTypeDueToPreservedScope for {System.Boolean AndroidX.Core.View.INestedScrollingChild::get_HasNestedScrollingParent()} This calls TypeMapInfo for assembly {Xamarin.AndroidX.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null} Which ends up processing type {AndroidX.Core.Widget.NestedScrollView} |
I've reproduced the issue, and the scenario looks like this: Types; Assembly A1 has B. In the trimmer: Later, B.M() is passed to IsMethodNeededByInstantiatedTypeDueToPreservedScope()
There is a psuedo-circular assembly reference with the way we build out TypeMapInfo In main the same exact situation doesn't cause issues, and #3094 fixes this repro for .Net 7, but I don't think a similar situation is guaranteed to never happen. Since base methods can provide interface members, the list of base methods of a type is dependent on which assemblies have been processed by TypeMapInfo at the time GetBaseMethods is called. |
So if I read this right, we can't know the answer to I think the next thing to figure out is if we can fix this by accepting the fact that we don't know everything at that point - cache the list of bases (to avoid the exception), do the work anyway... is there a case where we would get something wrong if we did that? Can we have a more conservative behavior in such case (like marking more if we don't know - we do this in some other places as well)? |
Since we keep a list of the types with interfaces and process them until we reach a steady state, we should be okay doing that. However, it looks like we don't take into account situations where a base type provides the interface method, so we'll need to add some code to handle that case in Another thing we could try is to build the entire TypeMapInfo at the start of the linker. That would avoid this problem entirely but might have a significant speed perf impact. |
I'm also experiencing this issue, in relation with changes to a net6.0-android library building on 7.0.100 SDK. I'm getting this issue now because I'm adding some internal methods/properties to an android bindings assembly. |
…e provides iface method (dotnet#3120) Add test case for dotnet#3112 with pseudo-circular reference with ifaces Commit migrated from dotnet@2172c79
…hen base provides iface method (dotnet/linker#3120) Add test case for dotnet/linker#3112 with pseudo-circular reference with ifaces Commit migrated from dotnet/linker@2172c79
…state changes (#3094) * Check for marking virtual method due to base only when state changes (#3073) Instead of checking every virtual method to see if it should be kept due to a base method every iteration of the MarkStep pipeline, check each method only when its relevant state has changed. Co-authored-by: Sven Boemer <[email protected]> * Don't mark override of abstract base if the override's declaring type is not marked (#3098) * Don't mark an override every time the base is abstract, only if the declaring type is also marked Adds a condition to ShouldMarkOverrideForBase to exit early if the declaring type of the method is not marked. * Add test case for #3112 with pseudo-circular reference with ifaces * Link issue to TODO * Adds a test for recursive generics on interfaces This is a copy of the test added in #3156 Co-authored-by: Sven Boemer <[email protected]> Co-authored-by: vitek-karas <[email protected]>
Any update on this?
|
The bug should be fixed in 7.0.300 which should ship in roughly a month. You can grab a nightly build here https://github.com/dotnet/installer#table. It would be very helpful if you could try the nightly and let us know if it fixes the problem for your specific application. |
Hi @vitek-karas! |
@vitek-karas any down-sides of using this in production? 😅 |
It's not an official release, so the biggest downside is that it's unsupported and it's not officially signed. So I can't recommend it, but if it works for you... |
Any news when the fix will be officially released? |
The fix is in 7.0.304 which you can download from https://dotnet.microsoft.com/en-us/download/dotnet/7.0. |
Trying to build Android .NET 7 project on the VS 17.4
ILLink : error IL1012: IL Trimmer has encountered an unexpected error. Please report the issue at https://github.com/dotnet/linker/issues [C:\agent_work\22\s\***\Android-NET_7.csproj]
Fatal error in IL Linker
Unhandled exception. System.InvalidOperationException: Collection was modified; enumeration operation may not execute.
at Mono.Linker.Steps.MarkStep.IsMethodNeededByInstantiatedTypeDueToPreservedScope(MethodDefinition method)
at Mono.Linker.Steps.MarkStep.GetRequiredMethodsForInstantiatedType(TypeDefinition type)+MoveNext()
at Mono.Linker.Steps.MarkStep.MarkRequirementsForInstantiatedTypes(TypeDefinition type)
at Mono.Linker.Steps.MarkStep.ProcessMethod(MethodDefinition method, DependencyInfo& reason, MessageOrigin& origin)
at Mono.Linker.Steps.MarkStep.ProcessQueue()
at Mono.Linker.Steps.MarkStep.ProcessPrimaryQueue()
at Mono.Linker.Steps.MarkStep.Process()
at Mono.Linker.Steps.MarkStep.Process(LinkContext context)
at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step)
at Mono.Linker.Pipeline.Process(LinkContext context)
at Mono.Linker.Driver.Run(ILogger customLogger)
at Mono.Linker.Driver.Main(String[] args)
The text was updated successfully, but these errors were encountered: