Measured on branch v5/clr-resolution (P4 remediation R5) and present at 311252e33.
def take(sb: StringBuilder) -> str:
return sb.to_string()
def main() -> None:
print("ok")
error[SPY0908]: internal error: generated C# failed to compile
(CS0246: The type or namespace name 'StringBuilder' could not be found ...)
Emitted:
public static string Take(StringBuilder sb)
Class
BuiltinRegistry.TryResolveClrType resolves a bare type name through its namespace list with no import at all, so the annotation type-checks. The emitter then names it from the symbol: TypeSyntaxMapper.GetMappedTypeNameFromSymbol routes a CLR-backed symbol through the qualification authority only when ClrType is { IsGenericType: true }, so a non-generic CLR-fallback type falls through to the short-name path and binds only if a using in the prelude happens to cover its namespace. List[int] looked fine for the same reason (using System.Collections.Generic); System.Text is not in the prelude, so StringBuilder is a hard SPY0908.
This is the non-generic half of #1765's "every CLR-backed type is named from its reflected type" contract. #1765's generic half is fixed on v5/clr-resolution (the registry entries for IEnumerable/IEnumerator now name the open generic definitions and the !typeSymbol.IsGeneric carve-out is gone), which is what made this half visible as a matrix hole.
Cells
ClrTypeResolutionPriorityTests (new, src/Sharpy.Compiler.Tests/Semantic/) covers kind {Sharpy-only, collision, CLR-only} x spelling {bare, imported, module-qualified, aliased, backtick}. The ClrOnly x bare cell is the only one carried as a [Fact(Skip = ...)] citing this issue; imported / module-qualified / aliased all run. Deleting the Skip is this issue's acceptance.
Either widen the qualification gate to every non-Sharpy ClrType (the seam is GetMappedTypeNameFromSymbol, one condition), or refuse a bare CLR name with no import by name instead of resolving it. Whichever is chosen, the fix is one predicate, not a per-namespace using list.
Measured on branch
v5/clr-resolution(P4 remediation R5) and present at311252e33.Emitted:
Class
BuiltinRegistry.TryResolveClrTyperesolves a bare type name through its namespace list with no import at all, so the annotation type-checks. The emitter then names it from the symbol:TypeSyntaxMapper.GetMappedTypeNameFromSymbolroutes a CLR-backed symbol through the qualification authority only whenClrType is { IsGenericType: true }, so a non-generic CLR-fallback type falls through to the short-name path and binds only if ausingin the prelude happens to cover its namespace.List[int]looked fine for the same reason (using System.Collections.Generic);System.Textis not in the prelude, soStringBuilderis a hard SPY0908.This is the non-generic half of #1765's "every CLR-backed type is named from its reflected type" contract. #1765's generic half is fixed on
v5/clr-resolution(the registry entries forIEnumerable/IEnumeratornow name the open generic definitions and the!typeSymbol.IsGenericcarve-out is gone), which is what made this half visible as a matrix hole.Cells
ClrTypeResolutionPriorityTests(new,src/Sharpy.Compiler.Tests/Semantic/) covers kind {Sharpy-only, collision, CLR-only} x spelling {bare, imported, module-qualified, aliased, backtick}. TheClrOnly x barecell is the only one carried as a[Fact(Skip = ...)]citing this issue; imported / module-qualified / aliased all run. Deleting theSkipis this issue's acceptance.Either widen the qualification gate to every non-Sharpy
ClrType(the seam isGetMappedTypeNameFromSymbol, one condition), or refuse a bare CLR name with no import by name instead of resolving it. Whichever is chosen, the fix is one predicate, not a per-namespace using list.