Skip to content

Track nullable state for extension properties#84311

Draft
jcouv wants to merge 9 commits into
dotnet:mainfrom
jcouv:fix-issue-81913-extension-property-nullability
Draft

Track nullable state for extension properties#84311
jcouv wants to merge 9 commits into
dotnet:mainfrom
jcouv:fix-issue-81913-extension-property-nullability

Conversation

@jcouv

@jcouv jcouv commented Jun 27, 2026

Copy link
Copy Markdown
Member

Fixes #81913
This was discussed with extensions working group (Aleksey and Mads)

Problem

C#'s nullable flow analysis (NullableWalker) did not track null-state for extension instance properties (the extension(Receiver) { public T P { get; set; } } feature). As a result:

#nullable enable
object o = new object();
o.P = null;
o.P.ToString();      // warns (correct)
o.P = new object();
o.P.ToString();      // BEFORE: warns (bug)  /  AFTER: no warning

static class E
{
    extension(object o)
    {
        public object? P { get => throw null!; set => throw null!; }
    }
}

Fix

Three changes in NullableWalker.cs:

  1. IsSlotMember — for an extension instance member, key against the extension parameter's (substituted) type via TryGetInstanceExtensionParameter instead of the marker ContainingType, so the write path can create a stable member slot.
  2. VisitPropertyAccess (extension branch) — add read-side slot consultation (MakeMemberSlot + GetState) mirroring the regular VisitMemberAccess path.
  3. InheritDefaultState — for extension block members, use the symbol directly instead of AsMemberOfType (which asserts the member is not an extension block member and would otherwise crash).

The read path keys on the reinferred updatedProperty while the write path keys on node.PropertySymbol; these resolve to the same slot because VariableIdentifier.Equals compares with TypeCompareKind.AllIgnoreOptions (ignores nullability). Generic extensions work because the binder substitutes type arguments at the concrete access site.

Extension indexers are intentionally unaffected — regular indexers aren't slot-tracked either (their identity includes argument values).

Microsoft Reviewers: Open in CodeFlow
@jcouv jcouv added Feature - Extension Everything The extension everything feature Area-Compilers labels Jun 30, 2026
@jcouv jcouv force-pushed the fix-issue-81913-extension-property-nullability branch from 92b9f11 to 9ae5a5c Compare June 30, 2026 21:36
@jcouv jcouv self-assigned this Jun 30, 2026
@jcouv jcouv changed the title Track nullable state for extension properties (#81913) Jun 30, 2026
@jcouv jcouv force-pushed the fix-issue-81913-extension-property-nullability branch from 9ae5a5c to 2fe7477 Compare June 30, 2026 21:44
@jcouv jcouv marked this pull request as ready for review June 30, 2026 23:22
@jcouv jcouv requested a review from a team as a code owner June 30, 2026 23:22
Copilot AI review requested due to automatic review settings June 30, 2026 23:22

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

This PR updates C# nullable flow analysis (NullableWalker) to track and consult null-state for extension instance properties, aligning their behavior with regular instance properties and addressing incorrect warnings/flow behavior in extension-property scenarios.

Changes:

  • Update member-slot identity and default-state inheritance logic for extension block members in NullableWalker.
  • Consult tracked member-slot state on reads of extension properties (mirroring normal member access).
  • Add/adjust compiler nullability regression tests for extension properties, including state reset and attribute/postcondition/pattern interactions.
Show a summary per file
File Description
src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs Tracks extension property members via receiver parameter type, avoids AsMemberOfType for extension members, and consults member-slot state on extension-property reads.
src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs Adds/updates nullability tests validating extension-property state tracking and adjusts expectations in several pattern/postcondition scenarios.
src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs Adds nullability tests around AllowNull/DisallowNull on extension property setters in object initializers and with expressions (source + metadata).

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 2
// (17,13): warning CS8602: Dereference of a possibly null reference.
// first.ToString(); // 1
Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "first").WithLocation(17, 13));
comp.VerifyEmitDiagnostics();
Comment thread src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests2.cs Outdated
@jcouv jcouv marked this pull request as draft July 1, 2026 00:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Area-Compilers Feature - Extension Everything The extension everything feature

2 participants