Can't build for release due to modreq from `in`

Open
#12,656 7 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
3/5
Estimated time
1-2 days
Newbie friendliness
68/100
Issue type
Bug
Clarity
Mostly clear
Activity status
Active
Tech stack
csharp

Research direction

Start with src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs, especially the CompareTypes logic at lines 84-105. Reproduce the failure with the two dotnet new projects and a Release build, then inspect how RequiredModifierType and the other mentioned Cecil type cases are handled. Done means the repro no longer produces IL1012 while abstract-method signature handling remains correct.

Written by the indexing model from the issue text.

Description

Area: App+Library Build need-attention
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.cs in 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 diag you 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.

Dominant language
C#
Stars
2.1k
Forks
580
Avg merge
2d 19m
Merged PRs (30d)
228

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from dotnet/android

All issues in dotnet/android

Similar issues

More C# issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.