Skip to content

ConfigurationBinder source generator generates code with the wrong nullable annotations #94105

@eerhardt

Description

@eerhardt

Description

When attempting to use the ConfigurationBinder source generator in dotnet/extensions (see dotnet/extensions#4625), I'm getting a nullable warning that is causing the generated code to not compile (I would need to disable nullable validation for the whole project if I wanted to ignore the nullable warning, which isn't acceptable).

I'm not sure what the general pattern is here that causes this issue, so I logged the issue for the scenario specifically. I think it might need to include nested generics where one of the nested generic types is nullable.

Reproduction Steps

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net8.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
    <EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
    <NoWarn>$(NoWarn);SYSLIB1100;SYSLIB1101</NoWarn>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0-rtm.23511.16" />
    <PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="8.0.0-rc.2.23510.2" />
  </ItemGroup>

</Project>
// needed to work around https://github.com/dotnet/runtime/issues/94065
global using Polly;
global using Polly.Hedging;
global using Polly.RateLimiting;
global using Polly.Timeout;

using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Http.Resilience;

var c = new ConfigurationBuilder().Build();
c.Get<HttpStandardHedgingResilienceOptions>();

Expected behavior

Should be without warnings

Actual behavior

Get a nullable warning from generated code:

CS8619	Nullability of reference types in value of type 'Func<HedgingActionGeneratorArguments<HttpResponseMessage>, Func<ValueTask<Outcome<HttpResponseMessage>>>?>' doesn't match target type 'Func<HedgingActionGeneratorArguments<HttpResponseMessage>, Func<ValueTask<Outcome<HttpResponseMessage>>>>'.	ConsoleApp101	C:\Users\eerhardt\source\repos\ConsoleApp101\ConsoleApp101\Microsoft.Extensions.Configuration.Binder.SourceGeneration\Microsoft.Extensions.Configuration.Binder.SourceGeneration.ConfigurationBindingGenerator\BindingExtensions.g.cs	1418		

The generated code looks like:

            if (AsConfigWithChildren(configuration.GetSection("ActionGenerator")) is IConfigurationSection section256)
            {
                Func<HedgingActionGeneratorArguments<HttpResponseMessage>, Func<ValueTask<Outcome<HttpResponseMessage>>>>? temp258 = instance.ActionGenerator;
                if (temp258 is not null)
                {

That middle line is the issue, it is of type:

Func<HedgingActionGeneratorArguments<HttpResponseMessage>, Func<ValueTask<Outcome<HttpResponseMessage>>>>
but the type of instance.ActionGenerator is:
Func<HedgingActionGeneratorArguments<TResult>, Func<ValueTask<Outcome<TResult>>>?>

Note the ? inside the last > brace.

Regression?

No response

Known Workarounds

No response

Configuration

No response

Other information

cc @tarekgh @ericstj

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions