Ignore function types in return type inference#57713
Ignore function types in return type inference#57713cston merged 5 commits intodotnet:release/dev17.0-vs-depsfrom
Conversation
| var comp = CreateCompilation(source); | ||
| comp.VerifyDiagnostics( | ||
|
|
||
| var expectedDiagnostics = new[] |
|
@dotnet/roslyn-compiler, please review this fix for 17.0, thanks. |
| Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test4").WithArguments("Test4").WithLocation(7, 6), | ||
| // (11,1): error CS0411: The type arguments for method 'Test3<T>(Func<Func<T>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. | ||
| // Test3(() => () => 3); | ||
| Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Test3").WithArguments("Test3<T>(System.Func<System.Func<T>>)").WithLocation(11, 1), |
There was a problem hiding this comment.
I'm not familiar at all with the rules/specifications around this so feel free to ignore, but is it expected that this case shouldn't support inference? In my bug report (57517) I mentioned that Func<Func<T>> supported inference of T and it seems this change is going in the opposite direction and undoing something that was working? When I made the bug report I was thinking that the outcome would be that inference of T on Func<Expression<Func<T>>> would start working.
There was a problem hiding this comment.
Thanks @CameronAavik for catching this and for logging #57517.
With C#10 currently, there is a potential breaking change from C#9 in type inference when inferring from the return type of a lambda expression when the return value is another lambda expression or a method group
(see examples in #57517 (comment) and #57630).
We've decided to fix the breaking change for now by not inferring from the return type of a lambda if the return value is another lambda or method group. This effectively reverts the type inference behavior for those cases to the C#9 behavior.
(I've added this to the PR description above.)
In your examples above, as you noted, this means that inference fails for the calls to Test3() and Test4(), as in C#9.
Separately, we will investigate whether we can improve type inference (in a subsequent release) for these cases by inferring from the function type of the returned lambda or method group. If so, that should allow inference for Test3() and Test4().
I will log a separate issue for that investigation.
|
@dotnet/roslyn-compiler, please review, thanks. |
| } | ||
|
|
||
| public TypeWithAnnotations GetInferredReturnType(ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo) | ||
| public TypeWithAnnotations GetInferredReturnType(ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, bool allowInferredFromFunctionType) |
| { | ||
| // Note: so long as we have a best type, we can proceed. | ||
| var bestTypeWithObliviousAnnotation = TypeWithAnnotations.Create(bestType); | ||
| var unwrappedType = bestType is FunctionTypeSymbol functionType ? |
There was a problem hiding this comment.
Based on your suggestion offline, I've changed the various methods to return a TypeSymbol and a bool rather than requiring callers to pass in the correct value.
It looks like we can end up with Refers to: src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs:3569 in 692a53b. [](commit_id = 692a53b, deletion_comment = False) |
|
|
||
| if (!allowInferredFromFunctionType && inferredReturnType.InferredFromFunctionType) | ||
| { | ||
| return default; |
|
Done with review pass (commit 2) |
| case 1: | ||
| if (conversions.IncludeNullability) | ||
| { | ||
| inferredFromFunctionType = false; |
There was a problem hiding this comment.
I didn't follow, why is inferredFromFunctionType always false here?
There was a problem hiding this comment.
It's assumed that the caller has populated the returns array with the actual types of the corresponding BoundExpression (although if the caller is NullableWalker, the types may differ by inferred nullability). That assumption is unchanged with this PR since callers did not expect this method to return a function type previously.
|
Do we have a follow-up issue to either make further adjustments for 17.1, or to reify the current behavior into the spec (if we choose to stick with this behavior)? |
|
Logged #57779 to investigate inferring from the function type instead. |
With C#10 currently, there is a potential breaking change from C#9 in type inference when inferring from the return type of a lambda expression when the return value is another lambda expression or a method group.
See examples in #57517 (comment) and #57630.
To avoid the breaking change, type inference is updated to not infer from the return type of a lambda if the return value is another lambda or method group. This effectively reverts the type inference behavior for those cases to the C#9 behavior.
Fixes #57630.
See also https://dev.azure.com/devdiv/DevDiv/_workitems/edit/1437668.