Can't build for release due to modreq from `in`
- 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