Open PathogenDavid opened 3 years ago
Obviously the above <Reference ...> item is extremely atypical of a modern .NET project, but what is more common is how this issue surfaces in various Roslyn-powered tools since they seem to love referencing the runtime assemblies directly.
It's more than atypical though, it's generally not supported. The reference assemblies are meant for compiling .NET programs, not the runtime assemblies. Compiling against the runtime assemblies is subject to a number of different problems (including breaks between versions).
If the runtime team wants to support this then they need to change the definition such that Span<T>
is recognized as a pointer illegal type. It's possible we end up agreeing that roslyn should just inherently recognize it as such but at the moment that is not the case. We depend on the runtime team to define the type in such a way that it's recognized as non-pointer legal.
I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.
(It could be argued this is the runtime's fault, but it's not clear to me where the fix would end up being -- assuming this should be fixed at all. I'm 80% reporting this issue because this probably isn't the first time I've done this and probably won't be the last and I need something that comes up when I search
CS0208
.)Version Used:
Steps to Reproduce:
Span<char>* elements = stackalloc Span<char>[16];
somewhere in an unsafe context.Expected Behavior: A compiler error should occur:
Actual Behavior: Code compiles and runs just fine.
In other Roslyn-powered tools
Obviously the above
<Reference ...>
item is extremely atypical of a modern .NET project, but what is more common is how this issue surfaces in various Roslyn-powered tools since they seem to love referencing the runtime assemblies directly.If you try the same on SharpLab you will not experience a compiler error.
Similarly, it works in the C# Interactive in Visual Studio (in both 17.0.0p3.1 and 16.11.1):
As well as CSharpRepl:
The underlying cause
The reason this happens is the actual implementation of
Span<T>
is technically unmanaged because it is just a pair ofByReference<T>
andint
. (The runtime has a special understanding of it, but as far as Roslyn is concernedByReference<T>
is just a struct with a singleIntPtr
field.)This is not normally an issue because generally speaking the compiler is invoked with the runtime's reference assemblies, and the reference assembly replaces the
ByReference<T>
field with anobject
dummy. (My understanding is this is special-cased here inIsOrContainsReferenceType
-- For context as to why private fields become dummies see https://github.com/dotnet/runtime/issues/16402.)Possible fixes
System.ByReference<T>
to beobject
-like.System.Span<T>
,System.ReadOnlySpan<T>
, andSystem.TypeReference
shouldn't be possible.ByReference<T>
to useobject
instead ofIntPtr
for the placeholder field. (Although I imagine there's a reason it doesn't.)stackalloc
an array of spans. (I swear it was kosher in context!)(Personally I am partial to option 8.)