-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Config binder source-gen: .NET 7 app fails to compile with .NET 8 preview 4 package #86348
Comments
Tagging subscribers to this area: @dotnet/area-extensions-configuration Issue DetailsDescriptionI was testing out the new config source generator. In .NET Preview 3, I can add the NuGet package to a .NET 7 app, and the app can build and use the source generated code as expected. With the preview 4 version of the generator I get a compiler error:
Reproduction StepsProgram.cs var builder = WebApplication.CreateBuilder(args);
builder.Services.Configure<TestOptions>(builder.Configuration); csproj <Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<Nullable>enable</Nullable>
<!-- 👇 Note that this is required, otherwise it can't find Dictionary<> values-->
<!-- 👇 Should be fixed too 😉-->
<ImplicitUsings>enable</ImplicitUsings>
<LangVersion>latest</LangVersion>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="8.0.0-preview.4.*" />
</ItemGroup>
</Project> Building gives the following error:
The generated code looks like this (error location highlighted): // <auto-generated/>
#nullable enable
internal static class GeneratedConfigurationBinder
{
public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<T>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::Microsoft.Extensions.Configuration.IConfiguration configuration)
{
if (configuration is null)
{
throw new global::System.ArgumentNullException(nameof(configuration));
}
if (typeof(T) == typeof(global::TestOptions))
{
return services.Configure<global::TestOptions>(obj =>
{
if (!global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.HasValueOrChildren(configuration))
{
// 👇 Anonymous function converted to a void returning delegate cannot return a value
return default;
}
global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.BindCore(configuration, ref obj);
});
}
throw new global::System.NotSupportedException($"Unable to bind to type '{typeof(T)}': 'Generator parser did not detect the type as input'");
}
}
namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
using System;
using System.Globalization;
using Microsoft.Extensions.Configuration;
internal static class Helpers
{
public static void BindCore(IConfiguration configuration, ref TestOptions obj)
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
if (configuration["String"] is string stringValue1)
{
obj.String = stringValue1;
}
}
public static bool HasValueOrChildren(IConfiguration configuration)
{
if ((configuration as IConfigurationSection)?.Value is not null)
{
return true;
}
return HasChildren(configuration);
}
public static bool HasChildren(IConfiguration configuration)
{
foreach (IConfigurationSection section in configuration.GetChildren())
{
return true;
}
return false;
}
}
} Expected behaviorNo build errors. With preview 3 there are no build errors, because it's not returning a value. This is the generated code using the preview 3 package: // <auto-generated/>
#nullable enable
using System.Linq;
internal static class GeneratedConfigurationBinder
{
public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<T>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::Microsoft.Extensions.Configuration.IConfiguration configuration)
{
if (typeof(T) == typeof(TestOptions))
{
return services.Configure<TestOptions>(obj =>
{
BindCore(configuration, ref obj);
});
}
throw new global::System.NotSupportedException($"Unable to bind to type '{typeof(T)}': 'Generator parser did not detect the type as input'");
}
private static void BindCore(global::Microsoft.Extensions.Configuration.IConfiguration configuration, ref TestOptions obj)
{
if (obj is null)
{
throw new global::System.ArgumentNullException(nameof(obj));
}
if (configuration["String"] is string stringValue1)
{
obj.String = stringValue1;
}
}
public static bool HasChildren(global::Microsoft.Extensions.Configuration.IConfiguration configuration)
{
foreach (global::Microsoft.Extensions.Configuration.IConfigurationSection section in configuration.GetChildren())
{
return true;
}
return false;
}
}
``
### Actual behavior error CS8030: Anonymous function converted to a void returning delegate cannot return a value
.NET SDK: Runtime Environment: Host:
|
FYI I've just tested by upgrading the app to .NET 8, using the .NET 8 preview 4, and I get the same error
|
Thanks @andrewlock for the report. we'll look at that. |
@layomia I assume we have a test covering this case now. Right? |
Yes we have a regression test. Lines 6 to 27 in 8f2c610
|
In my experience with SrcGen tests, I highly recommend disabling Implicit usings in the test projects, you don't gain much and it produces errors which do not show up in the CI pipeline. |
FYI, I have just installed .NET preview 5, and the source generator still appears to be broken. For example: I've highlighted error locations. Program.cs var builder = WebApplication.CreateBuilder(args);
IConfigurationSection section = builder.Configuration.GetSection("AllOptions");
builder.Services.Configure<BindableOptions>(section);
builder.Services.Configure<UnbindableOptions>(section);
var settings = new BindableOptions();
section.Bind(settings);
builder.Services.AddSingleton(settings); Generated Code: // <auto-generated/>
#nullable enable
internal static class GeneratedConfigurationBinder
{
public static global::Microsoft.Extensions.DependencyInjection.IServiceCollection Configure<T>(this global::Microsoft.Extensions.DependencyInjection.IServiceCollection services, global::Microsoft.Extensions.Configuration.IConfiguration configuration)
{
if (configuration is null)
{
throw new global::System.ArgumentNullException(nameof(configuration));
}
if (typeof(T) == typeof(global::BindableOptions))
{
// 👇 Argument type 'lambda expression' is not assignable to parameter type 'Microsoft.Extensions.Configuration.IConfiguration'
return services.Configure<global::BindableOptions>(obj =>
{
if (!global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.HasValueOrChildren(configuration))
{
return;
}
// 👇 binderOptions variable does not exist
global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.BindCore(configuration, ref obj, binderOptions);
});
}
// 👇 Variable 'type' does not exist
throw new global::System.NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
}
public static void Bind(this global::Microsoft.Extensions.Configuration.IConfiguration configuration, global::BindableOptions obj) => global::Microsoft.Extensions.Configuration.Binder.SourceGeneration.Helpers.BindCore(configuration, ref obj, binderOptions: null);
} |
Thanks. I'm going to open a PR for #83600 shortly which will comprehensively fix these compilation issues. |
Fixed in #86348. |
Description
I was testing out the new config source generator. In .NET Preview 3, I can add the NuGet package to a .NET 7 app, and the app can build and use the source generated code as expected.
With the preview 4 version of the generator I get a compiler error:
Reproduction Steps
Program.cs
csproj
Building gives the following error:
The generated code looks like this (error location highlighted):
Expected behavior
No build errors. With preview 3 there are no build errors, because it's not returning a value. This is the generated code using the preview 3 package:
error CS8030: Anonymous function converted to a void returning delegate cannot return a value
.NET SDK:
Version: 7.0.202
Commit: 6c74320bc3
Runtime Environment:
OS Name: Windows
OS Version: 10.0.19044
OS Platform: Windows
RID: win10-x64
Base Path: C:\Program Files\dotnet\sdk\7.0.202\
Host:
Version: 7.0.5
Architecture: x64
Commit: 8042d61
The text was updated successfully, but these errors were encountered: