提交 0a0d8f2e 编写于 作者: V Vladimir Sadov 提交者: GitHub

Merge pull request #20058 from VSadov/spanDetect2

Fix detection of Span types 
......@@ -2061,7 +2061,10 @@ internal override bool IsByRefLikeType
if (this.TypeKind == TypeKind.Struct)
{
if (IsWellknownSpans())
//PROTOTYPE(span): Span and ReadOnlySpan should have ByRefLike attribute, eventually.
// For now assume that any "System.Span" and "System.ReadOnlySpan" structs
// are ByRefLike
if (this.IsSpanType())
{
isByRefLike = ThreeState.True;
}
......@@ -2108,27 +2111,6 @@ internal override bool IsReadOnly
}
}
//PROTOTYPE(span): Span and ReadonlySpan should have spanLike marker.
// For now assume that any "System.Span" and "System.ReadOnlySpan" structs
// are span-like
private bool IsWellknownSpans()
{
var originalDef = this.OriginalDefinition;
if (originalDef.Name != "Span" && originalDef.Name != "ReadonlySpan")
{
return false;
}
var ns = originalDef.ContainingSymbol as NamespaceSymbol;
if (ns?.Name != "System")
{
return false;
}
return ns.IsGlobalNamespace;
}
internal override bool HasDeclarativeSecurity
{
get { return (_flags & TypeAttributes.HasSecurity) != 0; }
......
......@@ -1278,6 +1278,31 @@ private static bool HasNamespaceName(NamespaceSymbol @namespace, string namespac
return (name.Length == length) && (string.Compare(name, 0, namespaceName, offset, length, comparison) == 0);
}
internal static bool IsSpanType(this TypeSymbol type)
{
if ((type as NamedTypeSymbol)?.Arity != 1)
{
// must be a generic type of arity '1'
return false;
}
if (type.Name != "Span" && type.Name != "ReadOnlySpan")
{
// must be called "Span" or "ReadOnlySpan"
return false;
}
var ns = type.ContainingSymbol as NamespaceSymbol;
if (ns?.Name != "System")
{
// must be in "System" namespace
return false;
}
// the "System" must be in the global namespace
return ns.ContainingNamespace.IsGlobalNamespace;
}
internal static bool IsNonGenericTaskType(this TypeSymbol type, CSharpCompilation compilation)
{
var namedType = type as NamedTypeSymbol;
......
......@@ -28,7 +28,7 @@ namespace System
public override int GetHashCode() => 1;
}
public ref struct ReadonlySpan<T>
public ref struct ReadOnlySpan<T>
{
public ref readonly T this[int i] => throw null;
public override int GetHashCode() => 2;
......@@ -40,6 +40,7 @@ namespace System
}
}
";
//PROTOTYPE(span): this will be updated when rules for defining span are implemented
// most likely we would just pick the actual binary/corlib where
// span lives.
......@@ -83,7 +84,7 @@ class Program
static void Main()
{
object x = new Span<int>();
object y = new ReadonlySpan<byte>();
object y = new ReadOnlySpan<byte>();
object z = new SpanLike<int>();
}
}
......@@ -95,9 +96,9 @@ static void Main()
// (8,20): error CS0029: Cannot implicitly convert type 'System.Span<int>' to 'object'
// object x = new Span<int>();
Diagnostic(ErrorCode.ERR_NoImplicitConv, "new Span<int>()").WithArguments("System.Span<int>", "object").WithLocation(8, 20),
// (9,20): error CS0029: Cannot implicitly convert type 'System.ReadonlySpan<byte>' to 'object'
// object y = new ReadonlySpan<byte>();
Diagnostic(ErrorCode.ERR_NoImplicitConv, "new ReadonlySpan<byte>()").WithArguments("System.ReadonlySpan<byte>", "object").WithLocation(9, 20),
// (9,20): error CS0029: Cannot implicitly convert type 'System.ReadOnlySpan<byte>' to 'object'
// object y = new ReadOnlySpan<byte>();
Diagnostic(ErrorCode.ERR_NoImplicitConv, "new ReadOnlySpan<byte>()").WithArguments("System.ReadOnlySpan<byte>", "object").WithLocation(9, 20),
// (10,20): error CS0029: Cannot implicitly convert type 'System.SpanLike<int>' to 'object'
// object z = new SpanLike<int>();
Diagnostic(ErrorCode.ERR_NoImplicitConv, "new SpanLike<int>()").WithArguments("System.SpanLike<int>", "object")
......@@ -109,9 +110,9 @@ static void Main()
// (8,20): error CS0029: Cannot implicitly convert type 'System.Span<int>' to 'object'
// object x = new Span<int>();
Diagnostic(ErrorCode.ERR_NoImplicitConv, "new Span<int>()").WithArguments("System.Span<int>", "object").WithLocation(8, 20),
// (9,20): error CS0029: Cannot implicitly convert type 'System.ReadonlySpan<byte>' to 'object'
// object y = new ReadonlySpan<byte>();
Diagnostic(ErrorCode.ERR_NoImplicitConv, "new ReadonlySpan<byte>()").WithArguments("System.ReadonlySpan<byte>", "object").WithLocation(9, 20),
// (9,20): error CS0029: Cannot implicitly convert type 'System.ReadOnlySpan<byte>' to 'object'
// object y = new ReadOnlySpan<byte>();
Diagnostic(ErrorCode.ERR_NoImplicitConv, "new ReadOnlySpan<byte>()").WithArguments("System.ReadOnlySpan<byte>", "object").WithLocation(9, 20),
// (10,20): error CS0029: Cannot implicitly convert type 'System.SpanLike<int>' to 'object'
// object z = new SpanLike<int>();
Diagnostic(ErrorCode.ERR_NoImplicitConv, "new SpanLike<int>()").WithArguments("System.SpanLike<int>", "object")
......@@ -743,5 +744,101 @@ static void Main()
Diagnostic(ErrorCode.ERR_MethDelegateMismatch, "ToString").WithArguments("ToString", "System.Func<string>").WithLocation(16, 46)
);
}
//PROTOTYPE(span): Span and ReadOnlySpan should have ByRefLike attribute, eventually.
// For now assume that any "System.Span" and "System.ReadOnlySpan" structs
// are ByRefLike
[Fact]
public void SpanDetect()
{
//span structs are not marked as "ref"
string spanSourceNoRefs = @"
namespace System
{
public struct Span<T>
{
public ref T this[int i] => throw null;
public override int GetHashCode() => 1;
}
public struct ReadOnlySpan<T>
{
public ref readonly T this[int i] => throw null;
public override int GetHashCode() => 2;
}
public struct RegularStruct<T>
{
}
// arity 0 - not a span
public struct Span
{
}
// arity 2 - not a span
public struct Span<T, U>
{
public ref T this[int i] => throw null;
public override int GetHashCode() => 1;
}
}
// nested
public struct S1
{
public struct Span<T>
{
public ref T this[int i] => throw null;
public override int GetHashCode() => 1;
}
}
public struct Span<T>
{
public ref T this[int i] => throw null;
public override int GetHashCode() => 1;
}
";
var reference = CreateCompilation(
spanSourceNoRefs,
references: new List<MetadataReference>() { MscorlibRef_v4_0_30316_17626, SystemCoreRef, CSharpRef },
options: TestOptions.ReleaseDll);
reference.VerifyDiagnostics();
var text = @"
using System;
class Program
{
static void Main()
{
object x = new System.Span<int>();
object y = new ReadOnlySpan<byte>();
object z1 = new Span();
object z2 = new Span<int, int>();
object z3 = new S1.Span<int>();
object z4 = new Span<int>();
}
}
";
var comp = CreateCompilation(
text,
references: new List<MetadataReference>() { MscorlibRef_v4_0_30316_17626, SystemCoreRef, CSharpRef, reference.EmitToImageReference() },
options: TestOptions.ReleaseExe);
comp.VerifyDiagnostics(
// (8,20): error CS0029: Cannot implicitly convert type 'System.Span<int>' to 'object'
// object x = new System.Span<int>();
Diagnostic(ErrorCode.ERR_NoImplicitConv, "new System.Span<int>()").WithArguments("System.Span<int>", "object").WithLocation(8, 20),
// (9,20): error CS0029: Cannot implicitly convert type 'System.ReadOnlySpan<byte>' to 'object'
// object y = new ReadOnlySpan<byte>();
Diagnostic(ErrorCode.ERR_NoImplicitConv, "new ReadOnlySpan<byte>()").WithArguments("System.ReadOnlySpan<byte>", "object").WithLocation(9, 20)
);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册