Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

C# compiler incorrectly generates arrays for params of an enumerable of a ref struct type #77827

Copy link
Copy link
@hamarb123

Description

@hamarb123
Issue body actions

/cc @RikkiGibson

Version Used: Sharplab.io

Steps to Reproduce:

using System;
using System.Collections.Generic;
using System.Linq;
public class C
{
    public void M(params IEnumerable<Span<int>> a)
    {
        M([1], [1, 2]);
    }
}

link

This gets emitted as

Span<int>[] array = new Span<int>[2];
int reference = 1;
array[0] = new Span<int>(ref reference);
<>y__InlineArray2<int> buffer = default(<>y__InlineArray2<int>);
<PrivateImplementationDetails>.InlineArrayElementRef<<>y__InlineArray2<int>, int>(ref buffer, 0) = 1;
<PrivateImplementationDetails>.InlineArrayElementRef<<>y__InlineArray2<int>, int>(ref buffer, 1) = 2;
array[1] = <PrivateImplementationDetails>.InlineArrayAsSpan<<>y__InlineArray2<int>, int>(ref buffer, 2);
M(new <>z__ReadOnlyArray<Span<int>>(array));

Note the first line is already illegal, as it's allocating an array of spans.

Diagnostic Id:

There should be an error, but there is none.

Expected Behavior:

Doesn't compile.

OR

Compiles to something very different.

You could probably make some cases, like this one work, for Span/ReadOnlySpan, but in general it is not possible to emit such things. E.g., for this one, you could lower the [1], [1, 2] to a span enumeration wrapper that converts a <>z__ReadOnlyArray<int[]> to something that is IEnumerable<Span<int>>, but you definitely cannot do this sort of thing with arbitrary Span values (unless you emit some more crazy code, e.g., doing something with Span<int>* referring to the values which are stored on the stack or something like that, but I'm not convinced the lifetimes would work properly to allow this to work as expected for general usage of IEnumerables, e.g., you wouldn't be able to pass that across threads, nor keep using the IEnumerable value past the function call which took it as params - not that you probably want to emit this anyway, just thought I'd mention the theoretical option).

Actual Behavior:

Compiles and produces invalid code. This ends up giving TypeLoadException at runtime.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions

    Morty Proxy This is a proxified and sanitized view of the page, visit original site.