fix(csharp): recover arity-sibling base types dropped by the self-loop guard - #762
Conversation
…ropped by the self-loop guard
…c sibling instead of dropping the edge
…e package tier finds none
There was a problem hiding this comment.
Code Review
This pull request introduces support for C# arity overloading resolution during class ingestion. Specifically, it adds a helper method _csharp_arity_sibling to recover generic sibling types when a base class resolves to the declaring type itself (e.g., class Foo : Foo<object>), preventing the self-loop guard from dropping the inheritance edge. Unit tests have also been added to cover these scenarios. Feedback on the PR points out potential issues with the package-level sibling matching logic when dealing with root modules (no namespace) or subpackages, and provides a robust suggestion to compare exact parent packages instead.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
Problem
C# overloads type names by generic arity:
public sealed class PredicateBuilder : PredicateBuilder<object>declares a base that is a different type sharing the simple name. cgr's name resolution lands on the declaring type itself, and the deferred-inherits self-loop guard then drops the edge (dotted module-anchored remainder) or externalizes it. On Polly this silently lost 6 INHERITS edges (RetryStrategyOptions,CircuitBreakerStrategyOptions,PredicateBuilder,BrokenCircuitException<TResult>,ITtlStrategy,ExecuteParameters).Fix
When a deferred C# base resolves to the child itself, recover the arity sibling before falling back:
Foo.cs+Foo.TResult.cssibling layout.BrokenCircuitException<TResult> : BrokenCircuitExceptioninherits from Polly.Core), accept a project-wide unique declaration.Ambiguity at either tier keeps the no-edge answer rather than guessing, and the recovery is gated to C# — only C# can legally name a different type with the declaring type's own simple name, so other languages keep the existing shadowed-name semantics (e.g. thrift's
pub enum Errorimplementing stdError).Validation
RED → GREEN in commit history: failing tests first for the same-directory pair (class and interface variants), then the cross-directory pair.
On Polly, INHERITS false negatives drop from 5 to 2 (tp 192 → 195, F1 0.9253 → 0.9330). The two remaining misses have distinct root causes, out of scope here:
PredicateBuilder<TResult>ispartialacross two files, so the package tier sees two candidates and correctly refuses to guess; the opt-in Roslyn hybrid frontend's partial-group merge is the semantic answer for that shape.ExecuteParameters<T> : ExecuteParametersnests both types in one class, so their qualified names collide (the known duplicate-QN limitation; tracked separately).Full suite: 5224 passed, 10 skipped.