dotnet / dotnet/android

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

Open
#12,656 7 comments 0 reactions 0 assignees View on GitHub
Area: App+Library Build need-attention
Dominant language
C#
Stars
2.1k
Forks
579
Avg merge
1d 19h
Merged PRs (30d)
252

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:
```csharp
var renderer = new ConcreteRenderer();
var context = new Context();
renderer.Render(in context);
```
- Edit `Class1.cs` in Proj2 to:
```csharp
#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.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

```shell

```

### Additional Info

It also repros with
```csharp
#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.

Contributor guide

No contributing guide indexed for this repository

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.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.