Dumping the implicit/explicit classification of all pairs from a 120-type
universe and diffing it against what csc actually compiles surfaced two
divergences (16 affected pairs), both proven by a compiling-and-running
snippet and captured here as ignored known-bug tests:
1. Nullable conversions derived from tuple conversions are missing:
csc accepts "(long, object)? a = t;" for t of type (int, string) as
well as the lifted and explicit forms, CSharpConversions returns None.
The ECMA spec's 10.6.1 does not list tuple conversions as liftable,
so this is a case of Roslyn exceeding the spec.
2. An explicit user-defined conversion to a nullable target is rejected
when the operator result additionally needs an explicit numeric
conversion: csc accepts "(int?)new ImplicitToLong()" (operator to
long, then explicit long -> int?), CSharpConversions returns None.
The same sweep confirmed the SByte..Decimal TypeCode range in
ImplicitEnumerationConversion is correct: csc accepts zero constants of
any numeric type (0.0, 0f, 0m) for enum conversion and rejects '\0',
matching the implementation exactly.
Assisted-by: Claude:claude-fable-5:Claude Code
Audit the conversion test suites against the conversions chapter of the
draft-v8 C# standard and add tests for every rule that had none:
exhaustive implicit/explicit numeric conversion matrix, tuple/ValueTuple
and nullable-annotation identity, interpolated-string / throw-expression /
tuple-literal conversions, the boxing rule set including variance-based
boxing and unboxing, delegate-to-System.Delegate and IReadOnlyList<T>
reference conversions, type-parameter variance and effective-base-class
casts, generic method groups (inference, explicit type arguments, no
inference from the return type), the anonymous-function compatibility
checks CSharpConversions performs itself (via a LambdaResolveResult test
double), standard-conversion exclusion of user-defined operators, and
operators declared in base classes of the source type.
Two rules are implementation gaps rather than test gaps and get ignored
placeholder tests naming the gap: default literal conversions (10.2.16)
are an explicit TODO in CSharpConversions, and switch expressions
(10.2.18) have no ResolveResult representation. The full
section-by-section map is in
Analyses/ILSpy/2026-07-24_conversions-spec-coverage.md.
Assisted-by: Claude:claude-fable-5:Claude Code
Convert the commented-out block in ExplicitConversionsTest the same way as
the implicit ConversionTest block: type-parameter casts via
DefaultTypeParameter with cross-referencing constraints, user-defined
operators as fixture types in the test assembly, constant sources via
ConstantResolveResult. The rr.Input asserts of the originals were resolver
artifacts and are dropped; UseDefinedExplicitConversion_Lifted instead
exercises the ResolveResult-based ExplicitConversion entry point.
Also extend PreferAmbiguousConversionOverReferenceConversion with the
overload-resolution half of the original NRefactory test (the ambiguous
conversion must not prevent M(BB) from being chosen over M(object)), which
the first revival pass had reduced to the conversion classification alone.
Assisted-by: Claude:claude-fable-5:Claude Code