Repository navigation
C#: inline-declared receivers (out-var, is/case patterns) are not used as a typing source #2346
Description
Summary
Variables declared inline — out T x in an argument, and the pattern forms is T x, is not T x,
case T x: — are not recorded in the receiver type table, so calls on those receivers produce no
calls edge. This is independent of #2299: the behaviour is identical in 0.9.29 and 0.9.31, so the
per-method scoping fix neither caused nor changed it. It surfaced while verifying that fix, because
these receivers used to be resolved accidentally by the old file-wide table leaking a matching type
in from another method.
All four forms have the same shape in the C# grammar — a type node followed by a name node, as
declaration_expression (out-var) or declaration_pattern (the three pattern forms).
Repro
// Types.cs
public class Sect { public bool TryGetEntry(string k) { return true; } }
public class Node { public void Extend(string s) { } }
public class Leaf { public void Touch() { } }
public class Twig { public void Snap() { } }
public class Bag { public bool TryGetSection(string k, out Sect s) { s = null; return false; } }
// Uses.cs
public class Uses
{
public void OutVar(Bag bag)
{
if (bag.TryGetSection("k", out Sect sect)) { sect.TryGetEntry("x"); }
}
public void NegPattern(object o)
{
if (o is not Node nd) { return; }
nd.Extend("c");
}
public void PosPattern(object o)
{
if (o is Leaf lf) { lf.Touch(); }
}
public void CasePattern(object o)
{
switch (o) { case Twig tw: tw.Snap(); break; }
}
}graphify extract on this directory:
expected calls edge |
0.9.29 | 0.9.31 |
|---|---|---|
Uses.OutVar -> Bag.TryGetSection |
✅ | ✅ |
Uses.OutVar -> Sect.TryGetEntry |
— | — |
Uses.NegPattern -> Node.Extend |
— | — |
Uses.PosPattern -> Leaf.Touch |
— | — |
Uses.CasePattern -> Twig.Snap |
— | — |
1 of 5 edges in both versions. The four missing ones all have their type written explicitly at the
declaration site.
Why it matters
Both idioms are pervasive in modern C#: Try* methods with out parameters, and pattern matching in
if/switch. In our corpus (eight private repositories, ~10.3k .cs files) adding these two forms to
the receiver type table yields +78 additional calls edges with zero edges lost — measured on
identical extraction output, so the delta is attributable to this rule alone.
A representative real example, neutralised:
IniFile iniFile;
lock (IniLock) { iniFile = GetIniFile(path); }
if (iniFile.TryGetSection(pSection, out Section section))
{
if (section.TryGetEntry(pSetting, out KeyValueEntry entry)) // <- no edge
{
builder.Append(entry.Value);
}
}iniFile.TryGetSection resolves (0.9.31 handles declare-then-assign), but section.TryGetEntry does
not, even though section is explicitly typed Section two lines above.
Suggested fix
Populate the same per-method type table that #2299 introduced, from two additional node types:
declaration_expression—out T xdeclaration_pattern—is T x,is not T x,case T x:
Both expose a type node and a name node, so one branch covers all four forms. Scoping-wise these behave
like ordinary locals for the remainder of the enclosing block, so no change to the poisoning rules is
needed.
Notes
- Verified on 0.9.29 and 0.9.31; not a regression.
- Found while verifying C#: file-scoped receiver typing drops true
callsedges in unrelated methods (regression in 0.9.27) #2299 (thanks for that fix — confirmed separately on the same corpus).
Activity
fix(extract): C# inline-declared + partial-class receivers, Kotlin an…
chore: bump to 0.9.32; changelog for #2333/#2334/#2336/#2342/#2326/#2323
safishamsi commentedon Aug 1, 2026
Fixed in v0.9.32. C# member calls now resolve for receivers declared inline via
out var,is,case, and switch-arm patterns. Thanks for the repro.fix(csharp): scope receiver types per declaration so an untypeable re…
fix(extract): C# inline-declared + partial-class receivers, Kotlin an…
chore: bump to 0.9.32; changelog for Graphify-Labs#2333/Graphify-Labs…
fix(csharp): scope receiver types per declaration so an untypeable re…
merge: backport upstream C# receiver-typing fixes (Graphify-Labs#1609 G…