Skip to content

[SourceGen] Don't emit INPC handlers for static type references in C# XAML expressions - #35922

Merged
jfversluis merged 1 commit into
net11.0from
sde/fix-35900-static-type-handlers
Jun 18, 2026
Merged

[SourceGen] Don't emit INPC handlers for static type references in C# XAML expressions#35922
jfversluis merged 1 commit into
net11.0from
sde/fix-35900-static-type-handlers

Conversation

@StephaneDelcroix

Copy link
Copy Markdown
Contributor

Note

Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!

Description of Change

Fixes #35900.

The XAML C# expression source generator was emitting INPC subscription handlers for every MemberAccess chain in an expression, including chains rooted at a static type reachable via global using such as Colors.Goldenrod, DateTime.Now, or Math.Max(...).

The existing filter in ExpressionAnalyzer.Analyze correctly dropped the top-level handler when the root identifier (Colors, DateTime, Math) was not a member of the x:DataType, but it always kept the nested handlers for the same chain. That produced invalid getter lambdas like:

new(static __source => __source.Colors, "Goldenrod")
new(static __source => __source.DateTime, "Now")
new(static __source => __source.Math,     "Max")

…which then failed compilation with CS1061: 'MainViewModel' does not contain a definition for 'Colors' (and similar for DateTime/Math). This is step 4 of the XamlCSharpExpressions name-resolution spec: an identifier that doesn't resolve as a BindingContext member, code-behind member, or lambda parameter must fall through to a static type reference — it must never produce an INPC subscription against a non-existent member of the DataType.

The fix tightens the handler filter so a nested handler is kept only when the root identifier of its parent expression (after the __source. prefix) is an actual member of the DataType. The getter-body rewriter (TransformRootIdentifiers) already handled the static-type case correctly, so the lambda body — e.g. __source => (__source.IsVip ? Colors.Goldenrod : Colors.Gray, true) — compiles unchanged once the handler array is clean.

Issues Fixed

Fixes #35900

Tests

Added a parameterized test in CSharpExpressionDiagnosticsTests that exercises all four scenarios from the issue report:

  • TextColor="{IsVip ? Colors.Goldenrod : Colors.Gray}"
  • Text="{$'Now: {DateTime.Now:t}'}"
  • Text="{$'Max = {Math.Max(Price, Quantity):F2}'}"
  • Text="{$'{Name} - {DateTime.Now:d}'}"

The test asserts the generated .xsg.cs contains no __source.Colors/__source.DateTime/__source.Math handler subscriptions and that the resulting compilation has no errors. All 205 existing SourceGen.UnitTests continue to pass.

… XAML expressions

Fixes #35900

The XAML C# expression source generator was extracting binding handlers
for every MemberAccess chain in an expression, including chains rooted
at static type names like 'Colors.Goldenrod', 'DateTime.Now' or
'Math.Max(...)'. Top-level handlers were filtered out when the root
identifier wasn't a member of the x:DataType, but nested handlers in
the chain were always kept. That produced invalid getter lambdas such
as 'static __source => __source.Colors' which broke compilation with
'CS1061: <DataType> does not contain a definition for Colors'.

Per the XamlCSharpExpressions spec step 4 (Static Invocation), an
identifier that doesn't resolve as a BindingContext member, code-behind
member, or local lambda parameter must fall through to a static type
reference - it must not subscribe to a non-existent property on the
DataType.

The fix tightens the handler filter in ExpressionAnalyzer.Analyze so a
nested handler is kept only when the root identifier of its parent
expression (after the source parameter prefix) is an actual member of
the DataType.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 35922

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 35922"

@github-actions github-actions Bot added the area-xaml XAML, CSS, Triggers, Behaviors label Jun 15, 2026
@kubaflo

kubaflo commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

NEEDS_DISCUSSION (confidence: high) — multi-model review (2 LGTM, 2 ND); code unanimously judged correct, 0 actionable findings.

The source-gen fix is correct and minimal: it tightens the handler filter so a nested member-access handler is kept only when its chain-root identifier is a real property/field of the x:DataType. This drops both handlers of static-type chains (e.g. Colors.Goldenrod → the invalid static __source => __source.Colors getter that caused CS1061) while preserving genuine nested chains like User.Address.City. The new gate is consistent with the body rewriter TransformRootIdentifiers, and the test lives in SourceGen.UnitTests with assertNoCompilationErrors.

The only reason this isn't a clean LGTM: a required CI leg (RunOniOS_MauiReleaseTrimFull_CoreCLR ARM64) is failing while maui-pr is pending. It looks flaky/unrelated to a source-gen filter change — please confirm a green re-run before merge.

Multi-model review (gpt-5.5 · opus-4.8 · opus-4.6 · gemini-3.1-pro). Comments only — not a formal approval.

@jfversluis
jfversluis merged commit d086178 into net11.0 Jun 18, 2026
35 of 41 checks passed
@jfversluis
jfversluis deleted the sde/fix-35900-static-type-handlers branch June 18, 2026 08:07
@github-actions github-actions Bot added this to the .NET 11.0-preview6 milestone Jun 18, 2026
davidortinau added a commit to dotnet/core that referenced this pull request Jul 10, 2026
Incorporates jfversluis review feedback on #10467:
- Android MediaPicker result recovery APIs (dotnet/maui#35455)
- HybridWebView Android message-source filtering (dotnet/maui#35717)
- XAML C# expression source generator CS1061 fix (dotnet/maui#35922)
- Testable permissions via IPermissions/Permissions.Current (dotnet/maui#35987)
- XA0149 warning for legacy __AndroidEnvironment__ resources (dotnet/android#11700)
- Skip library proguard.txt with disallowed R8 global options (dotnet/android#11709)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
davidortinau added a commit to dotnet/core that referenced this pull request Jul 10, 2026
* [release-notes] .NET MAUI in .NET 11 Preview 6

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Draft .NET MAUI and friends notes for .NET 11 Preview 6

Combined highlights for .NET MAUI, .NET for Android, and .NET for iOS,
Mac Catalyst, macOS, and tvOS: CollectionView2 on Windows, handler-based
Shell on Android, Compatibility package removal, AOT-safe HybridWebView,
Geolocation minimum-distance filter, a reliability wave, the
AndroidMessageHandler HTTP-contract work, and the Apple platform toolchain
and NSUrlSessionHandler updates.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Add Preview 6 items from MAUI maintainer review

Incorporates jfversluis review feedback on #10467:
- Android MediaPicker result recovery APIs (dotnet/maui#35455)
- HybridWebView Android message-source filtering (dotnet/maui#35717)
- XAML C# expression source generator CS1061 fix (dotnet/maui#35922)
- Testable permissions via IPermissions/Permissions.Current (dotnet/maui#35987)
- XA0149 warning for legacy __AndroidEnvironment__ resources (dotnet/android#11700)
- Skip library proguard.txt with disallowed R8 global options (dotnet/android#11709)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: David Ortinau <david.ortinau@microsoft.com>
rbhanda added a commit to dotnet/core that referenced this pull request Jul 14, 2026
* [release-notes] .NET 11 Preview 6 base metadata

changes.json, features.json, build-metadata.json, and README for the
.NET 11 Preview 6 milestone (VMR base v11.0.0-preview.5.26302.115 ->
head release/11.0.1xx-preview6).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* [release-notes] C# in .NET 11 Preview 6 (#10460)

* [release-notes] C# in .NET 11 Preview 6

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update release-notes/11.0/preview/preview6/csharp.md

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Bill Wagner <wiwagn@microsoft.com>

* [release-notes] MSBuild in .NET 11 Preview 6 (#10463)

* [release-notes] MSBuild in .NET 11 Preview 6

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add bug-fix note for architecture-agnostic Runtime=NET task host handshake (dotnet/msbuild#13890)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Remove HTML comments from Preview 6 MSBuild release notes

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Chet Husk <chusk3@gmail.com>

* [release-notes] NuGet in .NET 11 Preview 6 (#10464)

* [release-notes] NuGet in .NET 11 Preview 6

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix STJ feature-flag env var value and remove VS reference

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Chet Husk <chusk3@gmail.com>

* [release-notes] .NET SDK in .NET 11 Preview 6 (#10459)

* [release-notes] .NET SDK in .NET 11 Preview 6

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Clarify NativeAOT CLI updates in preview6/sdk.md

Updated the NativeAOT CLI section to clarify the unification of managed and NativeAOT parsers, and removed filtered content related to internal changes.

* Add live running-tests display to dotnet test notes

Document the in-flight test progress panel (dotnet/sdk#54486) and fix
pre-existing trailing-space lint errors in the NativeAOT section.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Chet Husk <baronfel@users.noreply.github.com>
Co-authored-by: Chet Husk <chusk3@gmail.com>

* [release-notes] Windows Forms in .NET 11 Preview 6 (#10465)

* [release-notes] Windows Forms in .NET 11 Preview 6

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Revise Windows Forms release notes for Preview 6

Updated release notes for .NET 11 Preview 6 to include bug fixes and improvements for various Windows Forms components.

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Klaus Löffelmann <9663150+KlausLoeffelmann@users.noreply.github.com>

* [release-notes] .NET MAUI in .NET 11 Preview 6 (#10467)

* [release-notes] .NET MAUI in .NET 11 Preview 6

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Draft .NET MAUI and friends notes for .NET 11 Preview 6

Combined highlights for .NET MAUI, .NET for Android, and .NET for iOS,
Mac Catalyst, macOS, and tvOS: CollectionView2 on Windows, handler-based
Shell on Android, Compatibility package removal, AOT-safe HybridWebView,
Geolocation minimum-distance filter, a reliability wave, the
AndroidMessageHandler HTTP-contract work, and the Apple platform toolchain
and NSUrlSessionHandler updates.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

* Add Preview 6 items from MAUI maintainer review

Incorporates jfversluis review feedback on #10467:
- Android MediaPicker result recovery APIs (dotnet/maui#35455)
- HybridWebView Android message-source filtering (dotnet/maui#35717)
- XAML C# expression source generator CS1061 fix (dotnet/maui#35922)
- Testable permissions via IPermissions/Permissions.Current (dotnet/maui#35987)
- XA0149 warning for legacy __AndroidEnvironment__ resources (dotnet/android#11700)
- Skip library proguard.txt with disallowed R8 global options (dotnet/android#11709)

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: David Ortinau <david.ortinau@microsoft.com>

* [release-notes] EF Core in .NET 11 Preview 6 (#10462)

Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>

* [release-notes] F# in .NET 11 Preview 6 (#10461)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* [release-notes] Containers in .NET 11 Preview 6 (#10468)

* [release-notes] Containers in .NET 11 Preview 6

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Update release notes

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Logan Bussell <loganbussell@microsoft.com>

* [release-notes] .NET Libraries in .NET 11 Preview 6 (#10457)

* [release-notes] .NET Libraries in .NET 11 Preview 6

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Fix async DataAnnotations sample after testing on the Preview 6 SDK

AsyncValidationAttribute is overridden via the protected IsValidAsync
(and IsValid) members, not GetValidationResultAsync (which is the public
method the framework calls and is not virtual). Verified the corrected
sample compiles and runs against the Preview 6 build.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Verify Preview 6 library samples and fix inaccuracies

- Stream adapters: read from the read-only stream via StreamContent/PostAsync instead of copying HttpContent into it

- Cross-lane vectors: replace nonexistent Concat with ConcatLowerLower/LowerUpper/UpperLower/UpperUpper and drop preexisting Shuffle/ShuffleNative

- Async validation: swap the unique-username example for a VAT registry lookup, layer StringLength and RegularExpression sync rules with the async rule, and add a server-side validation note

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>

* [release-notes] ASP.NET Core in .NET 11 Preview 6 (#10456)

* [release-notes] WPF in .NET 11 Preview 6 (#10466)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Throw InvalidOperationException for sync validation of async validator

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* Apply late review suggestions from #10456 to the ASP.NET Core notes

- OpenAPI unions: correct the third-party generator claim (ApiExplorer does not
  detect unions via JsonTypeInfoKind.Union; Swashbuckle/NSwag don't yet
  recognize unions). Per @DeagleGross review on #10456.
- Blazor Virtualize: note that a user scroll during ScrollToIndexAsync wins.
  Per @ilonatommy review on #10456.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add P6 Blazor items to align with docs (dotnet/AspNetCore.Docs#37322)

- CSRF: note that Blazor Web App templates no longer call app.UseAntiforgery().
- Bug fixes/Blazor: Virtualize is now CSP-compliant (#66680); session cookie is
  issued before streaming SSR for [SupplyParameterFromSession]/TempData (#66832).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Document 'Configure Blazor client behavior from the server' as a P6 feature

WithBrowserOptions flows client-side Blazor.start configuration from the server
in C# (log level, Server reconnection, SSR DOM preservation, WASM environment),
serialized to the client across Server/WebAssembly/Auto render modes. Introduced
in Preview 4 (server-to-browser config via DOM comment) and reshaped in Preview 6
(dotnet/aspnetcore#67337, proposal #66393). Includes the reshape/rename migration
for earlier adopters. Sample build-verified on 11.0.100-preview.6.26359.118.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Correct Virtualize CSP note: data-blazor-virtualize-reserved-height

Reviewing dotnet/AspNetCore.Docs#37322 surfaced that the attribute is
data-blazor-virtualize-reserved-height (only the server-computed spacer height),
not the generic data-blazor-style. Verified in the P6 source (Virtualize.cs /
Virtualize.ts). @ilonatommy corrected the same wording on the docs PR.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* [release-notes] .NET Runtime in .NET 11 Preview 6 (#10458)

* [release-notes] .NET Runtime in .NET 11 Preview 6

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Enrich Preview 6 runtime notes with additional verified features

Fold verified .NET 11 Preview 6 runtime changes into runtime.md
(JIT improvements, in-process crash logging, NativeAOT interface
dispatch, SIMD lane APIs, and an expanded bug-fix list), and rebuild
the TOC to match the current sections.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: ade796bb-8052-4946-b204-a88518267e77

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Rich Lander <2608468+richlander@users.noreply.github.com>

* fix markdown lint in preview6 containers note

Co-authored-by: jongalloway <68539+jongalloway@users.noreply.github.com>

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Bill Wagner <wiwagn@microsoft.com>
Co-authored-by: Chet Husk <chusk3@gmail.com>
Co-authored-by: Chet Husk <baronfel@users.noreply.github.com>
Co-authored-by: Klaus Löffelmann <9663150+KlausLoeffelmann@users.noreply.github.com>
Co-authored-by: David Ortinau <david.ortinau@microsoft.com>
Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
Co-authored-by: Logan Bussell <loganbussell@microsoft.com>
Co-authored-by: Jeff Handley <jeffhandley@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Rich Lander <2608468+richlander@users.noreply.github.com>
Co-authored-by: Rahul Bhandari <rbhanda@microsoft.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: jongalloway <68539+jongalloway@users.noreply.github.com>
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 18, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-xaml XAML, CSS, Triggers, Behaviors

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants