The C# 14 compiler lowers implicit span conversions to calls -
MemoryExtensions.AsSpan(string), ReadOnlySpan<T>.CastUp, and the span
op_Implicit operators - so decompiled code showed the lowered form even
though the conversion and betterness layers already implement the C# 14
rules. CallBuilder now folds those helper calls back into conversions,
riding the existing mechanism: the conversion is built as an explicit
cast, consumption sites make it implicit where the context allows, and
the overload-resolution recheck re-adds a cast when the bare argument
would bind to a different overload (which canonicalizes deliberate
AsSpan disambiguations to the equivalent explicit span cast).
Span conversions compose, so CastCanBeMadeImplicit lets a direct
input-to-target span conversion replace a chained pair; and an rvalue
bound to an in parameter gets the same chance to shed the cast as a
by-value argument, since ChangeDirectionExpressionTo bypasses the
by-value strip.
Part of #829.
Assisted-by: Claude:claude-fable-5:Claude Code
Turn on #nullable enable across the AST consumer layer: the output visitor, the
IL-to-C# builders (statement, call and expression builders, CSharpDecompiler,
TypeSystemAstBuilder), the translation-result wrappers, the sequence-point and
required-namespace collectors, and the annotation helpers. Optional inputs,
fields and returns are typed nullable, detector out-parameters use
[NotNullWhen(true)], and structurally-guaranteed dereferences use the
null-forgiving operator. A few public parameters that already tolerate null are
widened to match their downstream callers. The annotations emit no IL, so the
Pretty suite stays byte-identical.
Assisted-by: Claude:claude-opus-4-8:Claude Code
The previously emitted `ref *(TTo*)(&source)` only compiles when `source` is a local variable; otherwise C# complains about the memory not being pinned.
Note that we special-case local variables to keep the previous behavior around; this avoids pulling in `System.Runtime.CompilerServices.Unsafe.dll` when it's unnecessary.
This can happen if an application is compiled for .NET 4.6.2 and references
System.ValueTuple.dll; but ILSpy loads the latest mscorlib (e.g. .NET 4.7)
which also contains struct System.ValueTuple.