-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Add span type inference #74646
Add span type inference #74646
Conversation
// var d1 = a.M; | ||
Diagnostic(ErrorCode.ERR_CannotInferDelegateType, "a.M").WithLocation(4, 10), | ||
Diagnostic(ErrorCode.ERR_MethDelegateMismatch, "M").WithArguments("M", "System.Func<int, int>").WithLocation(4, 12), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that type inference successfully infers the delegate type to be Func<int, int>
but then binding fails (because the span conversion doesn't exist for extension method receiver). I'm not sure if this is a problem, I think this could happen for some existing scenarios as well.
f408180
to
733cb63
Compare
733cb63
to
ede4c07
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly LGTM. Couple of minor comments.
|
||
private static TypeWithAnnotations GetSpanElementType(TypeSymbol type) | ||
{ | ||
return ((NamedTypeSymbol)type).TypeArgumentsWithAnnotationsNoUseSiteDiagnostics[0]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider assert that type
is Span
or ROS
. #Resolved
var comp = CreateCompilationWithSpanAndMemoryExtensions(source, parseOptions: TestOptions.Regular13); | ||
CompileAndVerify(comp, expectedOutput: "1").VerifyDiagnostics(); | ||
|
||
var expectedOutput = ExecutionConditionUtil.IsCoreClr ? "3" : "2"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exception is being thrown on CoreCLR? I assume something about variance? Consider leaving a comment. #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider reporting the exception type rather than "3", in this test and the next test.
using System; | ||
class C | ||
{ | ||
void M(ReadOnlySpan<string> a, object b) => M1(a, b); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's test a scenario like this with a non-variant non-array conversion, like ROS<int>
and object
/vice versa; I expect the former to fail, and the latter to succeed. #Resolved
|
||
comp = CreateCompilationWithSpanAndMemoryExtensions(source); | ||
CompileAndVerify(comp, expectedOutput: expectedOutput).VerifyDiagnostics(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// (4,43): error CS0411: The type arguments for method 'C.M1<T>(Span<T[]>, T)' cannot be inferred from the usage. Try specifying the type arguments explicitly. | ||
// void M(Span<string[]> a, object b) => M1(a, b); | ||
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M1").WithArguments("C.M1<T>(System.Span<T[]>, T)").WithLocation(4, 43)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"""; | ||
var comp = CreateCompilationWithSpanAndMemoryExtensions(source).VerifyDiagnostics(); | ||
AssertEx.Equal("C.M1<System.Object>", DisplayInvokedMethodTypeArguments(comp)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// (4,36): error CS0411: The type arguments for method 'C.M1<T>(Span<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. | ||
// void M(ReadOnlySpan<int> a) => M1(a); | ||
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M1").WithArguments("C.M1<T>(System.Span<T>)").WithLocation(4, 36)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -600,7 +600,7 @@ static bool CanConvertToSubpattern(IdentifierNameSyntax name, SemanticModel mode | |||
|
|||
// Process all nodes to refactor in reverse to ensure nested nodes | |||
// are processed before the outer nodes to refactor. | |||
foreach (var originalNode in nodes.Reverse()) | |||
foreach (var originalNode in Enumerable.Reverse(nodes)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are we now binding
nodes.Reverse()
toMemoryExtensions.Reverse<T>(Span<T>)
?
Yes.
And if so, is that an issue?
Yes, because MemoryExtensions.Reverse
returns void
.
@@ -105,14 +105,10 @@ private static string Concat(string container, string name) | |||
} | |||
} | |||
"""; | |||
internal const string s_collectionExtensionsWithSpan = s_collectionExtensions + | |||
internal const string s_collectionExtensionsWithReadOnlySpan = s_collectionExtensions + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not many additional changes, I can do that.
// (4,36): error CS0411: The type arguments for method 'C.M1<T>(Span<T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. | ||
// void M(ReadOnlySpan<int> a) => M1(a); | ||
Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M1").WithArguments("C.M1<T>(System.Span<T>)").WithLocation(4, 36)); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider testing variance when the array and span are the type arguments. For instance, with the following, for the calls with I<object[]>
and IOut<object[]>
I'd expect type inference to succeed but the subsequent argument conversion to fail, and for the call with IIn<object[]>
, I'd expect type inference to fail.
interface I<T> where T : allows ref struct { }
class A
{
static void M(I<object[]> a) => M1(a);
static void M1<T>(I<ReadOnlySpan<T>> x) { }
}
interface IOut<out T> where T : allows ref struct { }
class B
{
static void M(IOut<object[]> a) => M1(a);
static void M1<T>(IOut<ReadOnlySpan<T>> x) { }
}
interface IIn<in T> where T : allows ref struct { }
class C
{
static void M(IIn<object[]> a) => M1(a);
static void M1<T>(IIn<ReadOnlySpan<T>> x) { }
}
``` #Closed
Test plan: #73445
Corresponding speclet update: dotnet/csharplang#8333