Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 28, 2025

The nullability walker fails with an assertion error when analyzing collection expressions that use extension Add methods:

#nullable enable
object? oNull = null;
MyCollection c = [oNull, oNotNull];

static class E {
    public static void Add(this MyCollection c, object o) { }
}

Error: System.InvalidOperationException: Did not find Microsoft.CodeAnalysis.CSharp.BoundLocal 'oNull' in the map.

Root Cause

For extension methods, NullableWalker only visits Arguments[1] (the element argument), but never visits Arguments[0] (the receiver). When DebugVerifier walks all arguments, it asserts on the untracked receiver.

Changes

  • NullableWalker.cs: Mark receiver argument with unknown nullability for extension Add methods in collection expressions
  • ExtensionTests.cs: Add regression test

Relates to #68786

Original prompt

This section details on the original issue you should resolve

<issue_title>Assertion in nullability analysis of collection expression with extension Add method</issue_title>
<issue_description>The following code results in an assertion when calling VerifyEmitDiagnostics.
This should have been covered by PR #70192
Relates to nullability work for collection expressions: #68786

#nullable enable
using System.Collections;
using System.Collections.Generic;

object? oNull = null;
object oNotNull = new object();
MyCollection c = [oNull, oNotNull];

static class E
{
    public static void Add(this MyCollection c, object o) { }
}

public class MyCollection : IEnumerable<object>
{
    IEnumerator<object> IEnumerable<object>.GetEnumerator() => throw null!;
    IEnumerator IEnumerable.GetEnumerator() => throw null!;
}
  Message: 
System.InvalidOperationException : Did not find Microsoft.CodeAnalysis.CSharp.BoundLocal `oNull` in the map.

  Stack Trace: 
ThrowingTraceListener.Fail(String message, String detailMessage) line 26
TraceInternal.Fail(String message, String detailMessage)
Debug.Fail(String message, String detailMessage)
RoslynDebug.Assert(Boolean condition, AssertInterpolatedStringHandler& message) line 30
DebugVerifier.VerifyExpression(BoundExpression expression, Boolean overrideSkippedExpression) line 75
DebugVerifier.VisitExpressionOrPatternWithoutStackGuard(BoundNode node) line 84
BoundTreeVisitor.VisitExpressionOrPatternWithStackGuard(Int32& recursionDepth, BoundNode node) line 213
DebugVerifier.Visit(BoundNode node) line 100
BoundTreeWalker.VisitList[T](ImmutableArray`1 list) line 23
BoundTreeWalker.VisitCollectionElementInitializer(BoundCollectionElementInitializer node) line 10579
BoundCollectionElementInitializer.Accept(BoundTreeVisitor visitor) line 6893
BoundTreeVisitor.Visit(BoundNode node) line 151
DebugVerifier.VisitExpressionOrPatternWithoutStackGuard(BoundNode node) line 86
BoundTreeVisitor.VisitExpressionOrPatternWithStackGuard(Int32& recursionDepth, BoundNode node) line 213
DebugVerifier.Visit(BoundNode node) line 100
DebugVerifier.VisitCollectionExpression(BoundCollectionExpression node) line 146
BoundCollectionExpression.Accept(BoundTreeVisitor visitor) line 6461
BoundTreeVisitor.Visit(BoundNode node) line 151
DebugVerifier.VisitExpressionOrPatternWithoutStackGuard(BoundNode node) line 86
BoundTreeVisitor.VisitExpressionOrPatternWithStackGuard(Int32& recursionDepth, BoundNode node) line 213
DebugVerifier.Visit(BoundNode node) line 100
BoundTreeWalker.VisitConversion(BoundConversion node) line 10076
DebugVerifier.VisitConversion(BoundConversion node) line 408
BoundConversion.Accept(BoundTreeVisitor visitor) line 2978
BoundTreeVisitor.Visit(BoundNode node) line 151
DebugVerifier.VisitExpressionOrPatternWithoutStackGuard(BoundNode node) line 86
BoundTreeVisitor.VisitExpressionOrPatternWithStackGuard(Int32& recursionDepth, BoundNode node) line 213
DebugVerifier.Visit(BoundNode node) line 100
BoundTreeWalker.VisitLocalDeclaration(BoundLocalDeclaration node) line 10127
BoundLocalDeclaration.Accept(BoundTreeVisitor visitor) line 3419
BoundTreeVisitor.Visit(BoundNode node) line 151
DebugVerifier.Visit(BoundNode node) line 102
BoundTreeWalker.VisitList[T](ImmutableArray`1 list) line 23
BoundTreeWalker.VisitBlock(BoundBlock node) line 10111
BoundBlock.Accept(BoundTreeVisitor visitor) line 3323
BoundTreeVisitor.Visit(BoundNode node) line 151
DebugVerifier.Visit(BoundNode node) line 102
BoundTreeWalker.VisitNonConstructorMethodBody(BoundNonConstructorMethodBody node) line 10808
BoundNonConstructorMethodBody.Accept(BoundTreeVisitor visitor) line 8749
BoundTreeVisitor.Visit(BoundNode node) line 151
DebugVerifier.Visit(BoundNode node) line 102
DebugVerifier.Verify(ImmutableDictionary`2 analyzedNullabilityMap, SnapshotManager snapshotManagerOpt, BoundNode node) line 40
NullableWalker.AnalyzeWithSemanticInfo(CSharpCompilation compilation, Symbol symbol, BoundNode node, Binder binder, VariableState initialState, DiagnosticBag diagnostics, Boolean createSnapshots, Boolean requiresAnalysis) line 1634
NullableWalker.AnalyzeAndRewrite(CSharpCompilation compilation, Symbol symbol, BoundNode node, Binder binder, VariableState initialState, DiagnosticBag diagnostics, Boolean createSnapshots, SnapshotManager& snapshotManager, ImmutableDictionary`2& remappedSymbols) line 1586
MethodCompiler.BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, BindingDiagnosticBag diagnostics, Boolean includeInitializersInBody, BoundNode initializersBody, Boolean reportNullableDiagnostics, ImportChain& importChain, Boolean& originalBodyNested, Boolean& prependedDefaultValueTypeConstructorInitializer, InitialState& forSemanticModel) line 1910
MethodCompiler.CompileMethod(MethodSymbol methodSymbol, Int32 methodOrdinal, ProcessedFieldInitializers& processedInitializers, SynthesizedSubmissionFields previous...

</details>

- Fixes dotnet/roslyn#78452

<!-- START COPILOT CODING AGENT TIPS -->
---

✨ Let Copilot coding agent [set things up for you](https://github.com/dotnet/roslyn/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot) — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] Fix assertion in nullability analysis of collection expression Fix nullability assertion failure with extension Add methods in collection expressions Oct 28, 2025
Copilot AI requested a review from jcouv October 28, 2025 08:20
Copilot finished work on behalf of jcouv October 28, 2025 08:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants