Describe the bug
Analyzer tests using Microsoft.CodeAnalysis.Testing can hit a StackOverflowException inside WeightedMatch.MatchRecursive when there are many ambiguous/identical diagnostics to match.
This seems to be related to the recursive matching algorithm exploring a large number of possible pairings between expected and actual diagnostics, leading to stack exhaustion.
Repro
A minimal repro is to generate many diagnostics with the same ID and similar spans. This can be triggered by deeply nesting diagnostic markup:
static string CS0535(string interfaceName, int memberCount)
{
var result = interfaceName;
while (memberCount-- > 0)
result = $"{{|CS0535:{result}|}}";
return result;
}
Used in a test source string like this:
public class MyTestCase : {{CS0535("ITestCase", 19)}} { }
Running this through the standard analyzer verifier (e.g., VerifyAnalyzerAsync) causes a StackOverflowException during the diagnostic matching phase in the testing infrastructure.
Expected behavior
The test framework should either:
Handle large/ambiguous diagnostic sets without unbounded recursion.
Fail gracefully with a clear exception/message indicating that the diagnostic matching is too ambiguous to resolve.
Actual behavior
A StackOverflowException is thrown from Microsoft.CodeAnalysis.Testing.WeightedMatch.MatchRecursive.
Environment
.NET: 8.0
Microsoft.CodeAnalysis.Testing: 1.1.3
OS: macOS (observed in CI), but likely dependent on thread stack limits.
Notes:
The issue is easier to reproduce on macOS CI runners, likely due to lower default thread stack limits.
The same tests may pass on Windows/Linux but still exhibit high recursion depth.
Possible direction
It may help to:
Limit recursion depth or branching in WeightedMatch.
Introduce heuristics for identical diagnostics (same ID/span).
Provide an option to avoid exhaustive matching in favor of deterministic pairing.
CI logs
Example failure from macOS CI:
https://github.com/xunit/xunit.analyzers/actions/runs/24482992296/job/71551592115
Let me know if you'd like a reduced standalone repro project!
Describe the bug
Analyzer tests using
Microsoft.CodeAnalysis.Testingcan hit aStackOverflowExceptioninsideWeightedMatch.MatchRecursivewhen there are many ambiguous/identical diagnostics to match.This seems to be related to the recursive matching algorithm exploring a large number of possible pairings between expected and actual diagnostics, leading to stack exhaustion.
Repro
A minimal repro is to generate many diagnostics with the same ID and similar spans. This can be triggered by deeply nesting diagnostic markup:
Used in a test source string like this:
Running this through the standard analyzer verifier (e.g., VerifyAnalyzerAsync) causes a StackOverflowException during the diagnostic matching phase in the testing infrastructure.
Expected behavior
The test framework should either:
Handle large/ambiguous diagnostic sets without unbounded recursion.
Fail gracefully with a clear exception/message indicating that the diagnostic matching is too ambiguous to resolve.
Actual behavior
A StackOverflowException is thrown from Microsoft.CodeAnalysis.Testing.WeightedMatch.MatchRecursive.
Environment
.NET: 8.0
Microsoft.CodeAnalysis.Testing: 1.1.3
OS: macOS (observed in CI), but likely dependent on thread stack limits.
Notes:
The issue is easier to reproduce on macOS CI runners, likely due to lower default thread stack limits.
The same tests may pass on Windows/Linux but still exhibit high recursion depth.
Possible direction
It may help to:
Limit recursion depth or branching in WeightedMatch.
Introduce heuristics for identical diagnostics (same ID/span).
Provide an option to avoid exhaustive matching in favor of deterministic pairing.
CI logs
Example failure from macOS CI:
https://github.com/xunit/xunit.analyzers/actions/runs/24482992296/job/71551592115
Let me know if you'd like a reduced standalone repro project!