Skip to content

Routing source generation for Native AOT not working well with generic constraints and nullable reference types #51866

Closed
@joaofbantunes

Description

@joaofbantunes

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

Building an API using .NET 8's Native AOT, I've encountered an issue when using generic constraints and nullable reference types, along with the services being injected. Here's a practical example.

Given the following interfaces:

public interface IInputConstraint<TOutput>;

public interface IGenericService<TInput, TOutput> where TInput : IInputConstraint<TOutput>
{
    TOutput Get(TInput input);
}

With some concrete implementations:

public record SomeInput(int Value) : IInputConstraint<string?>;

public class ConcreteService : IGenericService<SomeInput, string?>
{
    public string? Get(SomeInput input) => input.Value % 2 == 0 ? input.Value.ToString() : null;
}

Then registering and using this:

builder.Services.AddSingleton<IGenericService<SomeInput, string?>, ConcreteService>();

// ...

app.MapGet("/", (IGenericService<SomeInput, string?> service) 
    => "Maybe? " + service.Get(new SomeInput(Random.Shared.Next())));

When building the API, an error occurs, indicating that in the GeneratedRouteBuilderExtensions.g.cs file, SomeInput cannot be used as a type parameter because nullability doesn't match the generic constraint.

Looking at the GeneratedRouteBuilderExtensions.g.cs file, we can see that its missing the question mark to denote the string nullability:

var jsonBodyOrServiceTypeTuples = new (bool, Type)[] {
    (false, typeof(global::IGenericService<global::SomeInput, global::System.String>)),
};

Expected Behavior

The generated source code matches the original code, and the application works normally.

Steps To Reproduce

I created a simple example here: https://github.com/joaofbantunes/NativeAotVsNullableReferenceTypes

Exceptions (if any)

Not really exception, but compiler error:

GeneratedRouteBuilderExtensions.g.cs(75,60): Error CS8631 : The type 'SomeInput' cannot be used as type parameter 'TInput' in the generic type or method 'IGenericService<TInput, TOutput>'. Nullability of type argument 'SomeInput' doesn't match constraint type 'IInputConstraint<string>'.

.NET Version

8.0.100-rc.2.23502.2

Anything else?

Runtime Environment:
OS Name: Mac OS X
OS Version: 14.0
OS Platform: Darwin
RID: osx-arm64
Base Path: /usr/local/share/dotnet/sdk/8.0.100-rc.2.23502.2/

.NET workloads installed:
There are no installed workloads to display.

Host:
Version: 8.0.0-rc.2.23479.6
Architecture: arm64
Commit: 0b25e38ad3

.NET SDKs installed:
6.0.408 [/usr/local/share/dotnet/sdk]
7.0.302 [/usr/local/share/dotnet/sdk]
8.0.100-rc.2.23502.2 [/usr/local/share/dotnet/sdk]

.NET runtimes installed:
Microsoft.AspNetCore.App 6.0.16 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 7.0.5 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.0-rc.2.23480.2 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 6.0.16 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 7.0.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.0-rc.2.23479.6 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]

Other architectures found:
None

Environment variables:
Not set

global.json file:
Not found

Learn more:
https://aka.ms/dotnet/info

Download .NET:
https://aka.ms/dotnet/download

Metadata

Metadata

Assignees

Labels

NativeAOTarea-minimalIncludes minimal APIs, endpoint filters, parameter binding, request delegate generator etcfeature-rdg

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions