HandleSequentialLocAllocInitializer formed a stackalloc initializer whenever the
explicit stores were contiguous from offset 0, even if they did not cover the
whole buffer. A 'stackalloc byte[16]' reinterpreted as int and written through
three of its four elements decompiled to 'stackalloc int[4] { 1, v, 3 }', whose
initializer has fewer elements than the declared length and does not compile.
Require every element to be written (from the constant data blob or an explicit
store) before forming the initializer; otherwise the buffer stays a plain
stackalloc with individual stores.
Found while exploring stackalloc-initializer coverage.
Assisted-by: Claude:claude-opus-4-8:Claude Code
A constant-size stackalloc initializer stores its constant elements through a
data blob (cpblk from a <PrivateImplementationDetails> field). ReadElement
decoded every element by width, so a 4-byte float was read as Int32 and an
8-byte double as Int64. The resulting constant carried the raw bit pattern
(1f decoded as 1.0653532E+09f) and its stack type no longer matched the store,
tripping StObj.CheckInvariant. Dispatch on the element's type code so Single and
Double are read as floating-point, matching the heap-array decoder.
Found while exploring stackalloc-initializer coverage around the element-type
hint fix; floating-point element types had no test case.
Assisted-by: Claude:claude-opus-4-8:Claude Code
DecodeArrayInitializer - Instead of relying on the Add method of a list to expand the underlying array when necessary, the code now allocates a big enough array to fit all the elements removing the need for the Add method to expand the array several times.
BlockFromInitializer now reuses a single instance of List<ILInstruction> instead of reallocating a new one every time and clears it when necessary. The same pre-allocation approach mentioned above has been implemented here too.
The C# translation of StObj will always apply delayed exceptions in these two cases, so putting an instruction with delayed exceptions in that slot would change program semantics.
* Use tuple literals instead of calling 'new ValueTuple<..>' constructor
* Where available, use element names for field access
* Make CallBuilder aware of tuple-name/dynamic type erasure, to avoid introducing casts when the types differ only in the tuple element names.
* Make CallBuilder provide a ResolveResult with the correct C# return type for the resulting expression.
Previously we were using the type-erased return type from the IL.
* Fix a bug that caused us to introduce returning casts when accessing an indexer.