Skip to content

Fix config binding generator CS0103 for required/init property with matching ctor param#130483

Draft
svick wants to merge 2 commits into
dotnet:mainfrom
svick:config-binding-sg-required-property
Draft

Fix config binding generator CS0103 for required/init property with matching ctor param#130483
svick wants to merge 2 commits into
dotnet:mainfrom
svick:config-binding-sg-required-property

Conversation

@svick

@svick svick commented Jul 10, 2026

Copy link
Copy Markdown
Member

Summary

The Configuration Binding source generator produced non-compiling code (CS0103) for a required/init property that is bound through a matching constructor parameter whose name differs from the property (for example only in casing: parameter name vs. property Name).

Fixes #128390.

Root cause

In the generated Initialize method, a required/init property that also has a matching constructor parameter is deliberately re-assigned in the object initializer so any custom init/set accessor logic runs after the constructor (the behavior covered by CanBindOnParametersAndProperties_PropertiesAreSetAfterTheConstructor).

The emitter used the property name as the value expression:

return new GreetSettings(name)
{
    Name = Name, // CS0103: no local named `Name`
};

but the bound value lives in the local named after the constructor parameter (name). When the two names matched exactly (e.g. positional records, or the existing ClassWithMatchingParametersAndProperties) the code happened to compile; when they differed it did not.

Note

This pull request was authored with the assistance of GitHub Copilot.

svick and others added 2 commits July 10, 2026 14:47
…atching ctor param

The generated Initialize method re-assigns required/init properties that also
flow through a matching constructor parameter, so custom init/set accessors run
after the constructor. It used the property name as the value expression
(`Name = Name`), but the bound value lives in the local named after the
constructor parameter. When the parameter name differed from the property (e.g.
only in casing, `name` vs `Name`), no such local existed and the generated code
failed to compile with CS0103.

Use the matching constructor parameter's local name as the assigned value when
present, falling back to the property name otherwise. Output is unchanged when
the parameter and property names match exactly (e.g. positional records), so no
baselines change.

Fixes dotnet#128390

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: e830d4aa-6a35-4105-9979-86d92e5255d2
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-extensions-configuration
See info in area-owners.md if you want to be subscribed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a Configuration Binding source-generator compile failure when an init/required property is bound via a matching constructor parameter whose name differs from the property name (e.g., name vs Name). The change updates emitted object-initializer assignments to use the constructor-parameter local when applicable, and adds regression coverage in both generator compilation tests and binder parity tests.

Changes:

  • Update generator emission for Initialize methods to assign init-only properties from the matching constructor-parameter local (MatchingCtorParam.Name) when present.
  • Refactor generator test helper to assert successful compilation without allocating/returning an assembly image.
  • Add regression tests covering differently-cased ctor parameter/property names for both source-generation compilation and runtime/sourcegen binder behavior parity.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.Helpers.cs Replaces CreateAssemblyImage with a compilation assertion helper used by generator tests.
src/libraries/Microsoft.Extensions.Configuration.Binder/tests/SourceGenerationTests/GeneratorTests.cs Adds generator compilation regression theory for required/init property + matching ctor parameter (case-different and exact-match).
src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.TestClasses.cs Adds a new test type with differently-cased ctor parameter names to validate parameter/property binding behavior.
src/libraries/Microsoft.Extensions.Configuration.Binder/tests/Common/ConfigurationBinderTests.cs Adds a parity test ensuring properties are set after the constructor even when ctor parameter casing differs.
src/libraries/Microsoft.Extensions.Configuration.Binder/gen/Emitter/CoreBindingHelpers.cs Fixes emitted object-initializer assignments to use the ctor-parameter local when a property matches a constructor parameter.

@tarekgh tarekgh left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Configuration Binding Generator produces non-compiling code for required property in child classes

3 participants