Repository navigation
Can't build for release due to modreq from in #12656
Copy link
Copy link
Open
Labels
Area: App+Library BuildIssues when building Library projects or Application projects.Issues when building Library projects or Application projects.need-attentionA xamarin-android contributor needs to reviewA xamarin-android contributor needs to review
Milestone
Description
Android framework version
net10.0-android
Affected platform version
.NET 10.0.400 SDK
Description
The build fails, due to not handling all edge cases here: https://github.com/dotnet/android/blob/main/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs#L84-L105.
Might be worth also handling any other similar cases, like IsSentinel, IsOptionalModifier, IsRequiredModifier, IsFunctionPointer, IsPointer (there may be others too). I can also repro with pointers, and haven't tried any others.
Steps to Reproduce
I used AI to help me get this relatively minimal repro.
- Run
dotnet new android -n Proj1 - Run
dotnet new androidlib -n Proj2 - Add reference to Proj2 from Proj1
- Add this code to MainActivity.cs:
var renderer = new ConcreteRenderer();
var context = new Context();
renderer.Render(in context);- Edit
Class1.csin Proj2 to:
#nullable disable
namespace ReproLibrary;
public struct Context
{
public int Value;
}
public interface IRenderer
{
void Render(in Context context);
}
public abstract class Renderer : Java.Lang.Object, IRenderer
{
public abstract void Render(in Context context);
}
public sealed class ConcreteRenderer : Renderer, IRenderer
{
public override void Render(in Context context)
{
}
}- Build with
dotnet build -c Debug(succeeds) - Build with
dotnet build -c Release(fails) - If you build with
-v diagyou will see the error:
16:50:18.052 1:9>ILLink : error IL1012: IL Trimmer has encountered an unexpected error. Please report the issue at https://aka.ms/report-illink [C:\Users\Hamish\Projects\Tests\TestAndroidInMethod\Proj1\Proj1.csproj]
Fatal error in IL Linker (TaskId:81)
Unhandled exception. System.NotSupportedException: TypeDefinition cannot be resolved from 'Mono.Cecil.RequiredModifierType' type (TaskId:81)
at Mono.Linker.LinkContext.Resolve(TypeReference typeReference) (TaskId:81)
at MonoDroid.Tuner.FixAbstractMethodsStep.CompareTypes(TypeReference iType, TypeReference tType) (TaskId:81)
at MonoDroid.Tuner.FixAbstractMethodsStep.HaveSameSignature(TypeReference iface, MethodDefinition iMethod, MethodDefinition tMethod) (TaskId:81)
at MonoDroid.Tuner.FixAbstractMethodsStep.FixAbstractMethods(TypeDefinition type) (TaskId:81)
at MonoDroid.Tuner.FixAbstractMethodsStep.ProcessType(TypeDefinition type) (TaskId:81)
at MonoDroid.Tuner.FixAbstractMethodsStep.<Initialize>b__0_0(TypeDefinition type) (TaskId:81)
at Mono.Linker.Steps.MarkStep.MarkType(TypeReference reference, DependencyInfo reason, MessageOrigin origin) (TaskId:81)
at Mono.Linker.Steps.MarkStep.MarkMethod(MethodReference reference, DependencyInfo reason, MessageOrigin& origin) (TaskId:81)
at Mono.Linker.Steps.MarkStep.MarkInstruction(Instruction instruction, MethodDefinition method, Boolean& requiresReflectionMethodBodyScanner, MessageOrigin& origin) (TaskId:81)
at Mono.Linker.Steps.MarkStep.MarkAndCheckRequiresReflectionMethodBodyScanner(MethodIL methodIL, MessageOrigin origin) (TaskId:81)
at Mono.Linker.Steps.MarkStep.MarkMethodBody(MethodBody body, MessageOrigin origin) (TaskId:81)
at Mono.Linker.Steps.MarkStep.ProcessPendingBodies() (TaskId:81)
at Mono.Linker.Steps.MarkStep.ProcessPrimaryQueue() (TaskId:81)
at Mono.Linker.Steps.MarkStep.Process() (TaskId:81)
at Mono.Linker.Steps.MarkStep.Process(LinkContext context) (TaskId:81)
at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step) (TaskId:81)
at Mono.Linker.Pipeline.Process(LinkContext context) (TaskId:81)
at Mono.Linker.Driver.Run(ILogger customLogger) (TaskId:81)
at Mono.Linker.Driver.Main(String[] args) (TaskId:81)
Did you find any workaround?
Don't use in or ref readonly, pointers, etc., in any types that inherit from Object outside of the main app project.
Relevant log output
Additional Info
It also repros with
#nullable disable
namespace ReproLibrary;
public struct Context
{
public int Value;
}
public interface IRenderer
{
void Render(in Context context);
}
public class ConcreteRenderer : Java.Lang.Object, IRenderer
{
public virtual void Render(in Context context)
{
}
}I think, which is closer to my original setup.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Area: App+Library BuildIssues when building Library projects or Application projects.Issues when building Library projects or Application projects.need-attentionA xamarin-android contributor needs to reviewA xamarin-android contributor needs to review
Activity
jonathanpeppers commentedon Sep 3, 2026
FixAbstractMethodsStepis more about fixing interfaces that change across Android API levels. This happened toICursorat one point many years ago.You don't mention changing the API level between
Proj1andProj2, is there something missing in the repro? Or is the file you linked to incorrect?Ideally, if you could share that sample project that would be best, thanks!
dotnet-policy-service commentedon Sep 3, 2026
Hi @hamarb123. We have added the "need-info" label to this issue, which indicates that we have an open question for you before we can take further action. This issue will be closed automatically in 7 days if we do not hear back from you by then - please feel free to re-open it if you come back to this issue after that time.
hamarb123 commentedon Sep 3, 2026
No, I don't change anything - the step crashes as it doesn't handle the type system properly is the cause afaict (it assumes that the only non-TypeRef/Def/Spec types are generic parameters, arrays, byrefs, and misses other cases like pointers, modreqs, modopts, function pointers, etc., which all crash for
TypeCache.Resolve). Here's the repro in a zip:TestAndroidInMethod.zip (do
dotnet build -c Releasein Proj1 to repro)Afaik the interface doesn't have to be in the android project either - in my real solution, the interface is in a different project that just targets
net10.0, the issue is just that I implement it on a type that inherits fromJava.Lang.Object, and then this task throws an exception due to missing handling (of in this case modreq - it also repro's if you put in pointer for example).jonathanpeppers commentedon Sep 3, 2026
This appears to already be fixing in main/.NET 11. There is refactoring related to trimming that I believe fixed this.
If you get the latest .NET 11 release, is it solved for you there?
hamarb123 commentedon Sep 3, 2026
@jonathanpeppers it does appear to be fixed in .NET 11 SDK when targeting .NET 11, it doesn't fix with .NET 11 SDK targeting .NET 10. It would be nice if it could be fixed for .NET 10 also, in my case, the only problematic one I have in my code is the
modreqone forin.Thanks for letting me know that it will be fixed in the future on its own though :)
jonathanpeppers commentedon Sep 4, 2026
Unfortunately, it is not a small change that fixed it -- so we can't easily backport to 10.
.NET 11 RC 1 is coming soon, if they mark it production/"go live" would that be good enough?
hamarb123 commentedon Sep 4, 2026
A different fix could easily be implemented for .NET 10, where it just maps modreq to the element type & compares that. Would that not work?
If not, then I can wait for .NET 11, but I would have thought it'd be relatively to fix it for .NET 10 also.