-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Open
Labels
Description
The following program reports an error on return spans
, but nothing in the spec indicates that should be the case. Strictly, the code seems valid to me. I think there is a spec gap due to the fact that ref structs were not anticipated to be valid element types under any conditions.
[Fact, WorkItem("https://github.com/dotnet/roslyn/issues/77827")]
public void RefStructElementType_SafeContext_06()
{
var source = """
#nullable enable
using System;
partial class Program
{
public static SpanCollection<Span<int>> Test(Span<int> span1, Span<int> span2)
{
SpanCollection<Span<int>> spans = [span1, span2];
return spans;
}
}
""";
var comp = CreateCompilation([source, s_collectionOfRefStructsSource], targetFramework: TargetFramework.Net90);
comp.VerifyDiagnostics(
// (9,16): error CS8352: Cannot use variable 'spans' in this context because it may expose referenced variables outside of their declaration scope
// return spans;
Diagnostic(ErrorCode.ERR_EscapeVariable, "spans").WithArguments("spans").WithLocation(9, 16));
}
private static readonly string s_collectionOfRefStructsSource = """
#nullable enable
using System;
using System.Collections;
using System.Collections.Generic;
ref struct SpanCollection<T>() : IEnumerable<T> where T : allows ref struct
{
int _count = 0;
T? _item0;
T? _item1;
public SpanEnumerator GetEnumerator()
=> new SpanEnumerator(this);
public void Add(T element)
{
switch (_count)
{
case 0: _item0 = element; break;
case 1: _item1 = element; break;
default: throw new InvalidOperationException();
}
_count++;
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
=> throw new NotImplementedException();
IEnumerator IEnumerable.GetEnumerator()
=> throw new NotImplementedException();
public ref struct SpanEnumerator(SpanCollection<T> spans)
{
private SpanCollection<T> spans = spans;
private int _index = -1;
public T Current
{
get
{
switch (_index)
{
case 0: return spans._item0!;
case 1: return spans._item1!;
default: throw new InvalidOperationException();
}
}
}
public bool MoveNext() => ++_index < spans._count;
}
}
""";