Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check generic construction diagnostics for stackalloc to span conversions #25131

Merged
merged 2 commits into from
Mar 6, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,4 @@ Example: `Func<int> f = default(TypedReference).GetHashCode; // new error CS0123
This is changed in 15.6 to now produce an error that the variable is not definitely assigned.

- Visual Studio 2017 version 15.7: https://github.com/dotnet/roslyn/issues/19792 C# compiler will now reject [IsReadOnly] symbols that should have an [InAttribute] modreq, but don't.
- Visual Studio 2017 version 15.7: https://github.com/dotnet/roslyn/pull/25131 C# compiler will now check `stackalloc T [count]` expressions to see if T matches constraints of `Span<T>`.
8 changes: 7 additions & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3127,7 +3127,13 @@ private BoundExpression BindStackAllocArrayCreationExpression(
var spanType = GetWellKnownType(WellKnownType.System_Span_T, diagnostics, node);
if (!spanType.IsErrorType())
{
type = spanType.Construct(elementType);
type = ConstructNamedType(
type: spanType,
typeSyntax: node.Type,
typeArgumentsSyntax: default,
typeArguments: ImmutableArray.Create(elementType),
basesBeingResolved: null,
diagnostics: diagnostics);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -675,5 +675,72 @@ public static explicit operator Test(Span<int> value)
}
}", TestOptions.ReleaseDll).VerifyDiagnostics();
}

[Fact]
[WorkItem(25038, "https://github.com/dotnet/roslyn/issues/25038")]
public void StackAllocToSpanWithRefStructType()
{
CreateCompilationWithMscorlibAndSpan(@"
using System;
ref struct S {}
class Test
{
void M()
{
Span<S> explicitError = default;
var implicitError = explicitError.Length > 0 ? stackalloc S[10] : stackalloc S[100];
}
}").VerifyDiagnostics(
// (8,14): error CS0306: The type 'S' may not be used as a type argument
// Span<S> explicitError = default;
Diagnostic(ErrorCode.ERR_BadTypeArgument, "S").WithArguments("S").WithLocation(8, 14),
// (9,67): error CS0306: The type 'S' may not be used as a type argument
// var implicitError = explicitError.Length > 0 ? stackalloc S[10] : stackalloc S[100];
Diagnostic(ErrorCode.ERR_BadTypeArgument, "S[10]").WithArguments("S").WithLocation(9, 67),
// (9,86): error CS0306: The type 'S' may not be used as a type argument
// var implicitError = explicitError.Length > 0 ? stackalloc S[10] : stackalloc S[100];
Diagnostic(ErrorCode.ERR_BadTypeArgument, "S[100]").WithArguments("S").WithLocation(9, 86));
}

[Fact]
[WorkItem(25086, "https://github.com/dotnet/roslyn/issues/25086")]
public void StaackAllocToSpanWithCustomSpanAndConstraints()
{
var code = @"
using System;
namespace System
{
public unsafe readonly ref struct Span<T> where T : IComparable
{
public Span(void* ptr, int length)
{
Length = length;
}
public int Length { get; }
}
}
struct NonComparable { }
class Test
{
void M()
{
Span<NonComparable> explicitError = default;
var implicitError = explicitError.Length > 0 ? stackalloc NonComparable[10] : stackalloc NonComparable[100];
}
}";

var references = new List<MetadataReference>() { MscorlibRef_v4_0_30316_17626, SystemCoreRef, CSharpRef };

CreateEmptyCompilation(code, references, TestOptions.UnsafeReleaseDll).VerifyDiagnostics(
// (19,14): error CS0315: The type 'NonComparable' cannot be used as type parameter 'T' in the generic type or method 'Span<T>'. There is no boxing conversion from 'NonComparable' to 'System.IComparable'.
// Span<NonComparable> explicitError = default;
Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "NonComparable").WithArguments("System.Span<T>", "System.IComparable", "T", "NonComparable").WithLocation(19, 14),
// (20,67): error CS0315: The type 'NonComparable' cannot be used as type parameter 'T' in the generic type or method 'Span<T>'. There is no boxing conversion from 'NonComparable' to 'System.IComparable'.
// var implicitError = explicitError.Length > 0 ? stackalloc NonComparable[10] : stackalloc NonComparable[100];
Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "NonComparable[10]").WithArguments("System.Span<T>", "System.IComparable", "T", "NonComparable").WithLocation(20, 67),
// (20,98): error CS0315: The type 'NonComparable' cannot be used as type parameter 'T' in the generic type or method 'Span<T>'. There is no boxing conversion from 'NonComparable' to 'System.IComparable'.
// var implicitError = explicitError.Length > 0 ? stackalloc NonComparable[10] : stackalloc NonComparable[100];
Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedValType, "NonComparable[100]").WithArguments("System.Span<T>", "System.IComparable", "T", "NonComparable").WithLocation(20, 98));
}
}
}