Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 3, 2025

  • Understand the stack overflow issue with partial events implementing interfaces
  • Identify root cause: infinite recursion when computing event accessor parameter types during partial member merging
  • Implement fix to skip accessor signature comparison during merge
  • Create test case to reproduce and validate the fix
  • Run partial events tests - all 135 pass
  • Fix DuplicateDeclaration_07 test failure by tracking accessor presence
  • Run broader compiler test suite to ensure no regressions
  • Address code review feedback with improved comments
  • Run CodeQL security scan - no issues
  • Final code review - no issues found
  • Task complete
Original prompt

This section details on the original issue you should resolve

<issue_title>CSC and DevEnv crash with stack overflow when partial class with partial event implements interface</issue_title>
<issue_description>Version Used:

  • VS 18.0.0 Insiders [11123.170]
  • Microsoft (R) Visual C# Compiler Version 5.0.0-2.25502.107 (89c8f6a1)

Steps to Reproduce:
Paste the following code (or compile it with csc):

internal interface IC
{
    event EventHandler E;
}

partial class C : IC
{
    public partial event EventHandler E;
}

partial class C
{
    public partial event EventHandler E { add { } remove { } }
}

Expected Behavior:
No crash.

Actual Behavior:
Hard crash, both from devenv and csc.exe.

Excerpt from csc output, the section beginning and ending in dashes repeats over and over again.

   (repeated many times)
   ----
   at Microsoft.CodeAnalysis.CSharp.Symbols.SourceMemberContainerTypeSymbol.GetMembersUnordered()
   at Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol.MakeExplicitInterfaceImplementationMap()
   at Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol.GetExplicitImplementationForInterfaceMember(Microsoft.CodeAnalysis.CSharp.Symbol)
   at Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol.ComputeImplementationForInterfaceMember(Microsoft.CodeAnalysis.CSharp.Symbol, Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag, Boolean, Boolean ByRef)
   at Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol.ComputeImplementationAndDiagnosticsForInterfaceMember(Microsoft.CodeAnalysis.CSharp.Symbol, Boolean, Boolean ByRef)
   at Microsoft.CodeAnalysis.CSharp.Symbols.TypeSymbol.FindImplementationForInterfaceMemberInNonInterfaceWithDiagnostics(Microsoft.CodeAnalysis.CSharp.Symbol, Boolean)
   at Microsoft.CodeAnalysis.CSharp.Symbols.SourceEventSymbol.ComputeIsWindowsRuntimeEvent()
   at Microsoft.CodeAnalysis.CSharp.Symbols.SourceEventSymbol.get_IsWindowsRuntimeEvent()
   at Microsoft.CodeAnalysis.CSharp.Symbols.SynthesizedEventAccessorValueParameterSymbol+<>c.<get_TypeWithAnnotations>b__3_0(Microsoft.CodeAnalysis.CSharp.Symbols.SourceEventAccessorSymbol)
   at Roslyn.Utilities.SingleInitNullable`1[[Microsoft.CodeAnalysis.CSharp.Symbols.TypeWithAnnotations, Microsoft.CodeAnalysis.CSharp, Version=5.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]].Initialize[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Func`2<System.__Canon,Microsoft.CodeAnalysis.CSharp.Symbols.TypeWithAnnotations>, System.__Canon)
   at Microsoft.CodeAnalysis.CSharp.Symbols.SynthesizedEventAccessorValueParameterSymbol.get_TypeWithAnnotations()
   at Microsoft.CodeAnalysis.CSharp.Symbols.MemberSignatureComparer.HaveSameParameterType(Microsoft.CodeAnalysis.CSharp.Symbols.ParameterSymbol, Microsoft.CodeAnalysis.CSharp.Symbols.TypeMap, Microsoft.CodeAnalysis.CSharp.Symbols.ParameterSymbol, Microsoft.CodeAnalysis.CSharp.Symbols.TypeMap, RefKindCompareMode, Boolean, Microsoft.CodeAnalysis.TypeCompareKind)
   at Microsoft.CodeAnalysis.CSharp.Symbols.MemberSignatureComparer.HaveSameParameterTypes(System.ReadOnlySpan`1<Microsoft.CodeAnalysis.CSharp.Symbols.ParameterSymbol>, Microsoft.CodeAnalysis.CSharp.Symbols.TypeMap, System.ReadOnlySpan`1<Microsoft.CodeAnalysis.CSharp.Symbols.ParameterSymbol>, Microsoft.CodeAnalysis.CSharp.Symbols.TypeMap, RefKindCompareMode, Boolean, Microsoft.CodeAnalysis.TypeCompareKind)
   at Microsoft.CodeAnalysis.CSharp.Symbols.MemberSignatureComparer.Equals(Microsoft.CodeAnalysis.CSharp.Symbol, Microsoft.CodeAnalysis.CSharp.Symbol)
   at System.Collections.Generic.Dictionary`2[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].FindValue(System.__Canon)
   at System.Collections.Generic.Dictionary`2[[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=10.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].TryGetValue(System.__Canon, System.__Canon ByRef)
   at Microsoft.CodeAnalysis.CSharp.Symbols.SourceMemberContainerTypeSymbol.MergePartialMembers(System.Collections.Generic.Dictionary`2<System.ReadOnlyMemory`1<Char>,System.Object>, Microsoft.CodeAnalysis.PooledObjects.ArrayBuilder`1<Microsoft.CodeAnalysis.CSharp.Symbol>, Microsoft.CodeAnalysis.CSharp.BindingDiagnosticBag)
   at Microsoft.CodeAnalysis.CSharp.Symbols.SourceMemberContainerTypeSymbol.MergePartialMembersAndInitializeNonTypeMembers(System.Collections.Immutable.ImmutableArray`1<Microsoft.CodeAnalysis.CSharp.Symbol>, System.Collections.Immutable.ImmutableArray`1<Microsoft.CodeAnalysis.CSharp.Symbol> ByRef)
   at Microsoft.CodeAnalysis.CSharp.Symbols.SourceMemberContainerTypeSymbol+DeclaredMembersAndInitializers.GetNonTypeMember...

</details>

- Fixes dotnet/roslyn#80986

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

💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey).

Copilot AI and others added 2 commits November 3, 2025 10:44
Skip comparing event/property accessor signatures during partial member merging since they are handled by their associated member. This prevents infinite recursion when event accessors need to check IsWindowsRuntimeEvent during signature comparison.

Co-authored-by: jjonescz <[email protected]>
Copilot AI changed the title [WIP] CSC and DevEnv crash with stack overflow when partial class with partial event implements interface Fix stack overflow when partial event implements interface Nov 3, 2025
Copilot AI requested a review from jjonescz November 3, 2025 10:56
Copilot finished work on behalf of jjonescz November 3, 2025 10:56
Avoid comparing accessor signatures during partial member merging by skipping them entirely, but track when a name has accessors to suppress false diagnostics for partial methods with matching accessor names.

Co-authored-by: jjonescz <[email protected]>
Copilot AI requested a review from jjonescz November 3, 2025 12:32
Copilot finished work on behalf of jjonescz November 3, 2025 12:32
@dotnet dotnet deleted a comment from azure-pipelines bot Nov 3, 2025
@jjonescz jjonescz closed this Nov 3, 2025
@jjonescz jjonescz deleted the copilot/fix-9141961-29078997-9b00d2c0-78c3-4aa9-ad26-39405f93a686 branch November 3, 2025 17:46
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