diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 7b299faf57cdc..3608e46028073 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -3246,7 +3246,7 @@ private BoundExpression BindImplicitArrayCreationExpression(ImplicitArrayCreatio ImmutableArray boundInitializerExpressions = BindArrayInitializerExpressions(initializer, diagnostics, dimension: 1, rank: rank); CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); - TypeSymbol bestType = BestTypeInferrer.InferBestType(boundInitializerExpressions, this.Conversions, ref useSiteInfo); + TypeSymbol bestType = BestTypeInferrer.InferBestType(boundInitializerExpressions, this.Conversions, ref useSiteInfo, out _); diagnostics.Add(node, useSiteInfo); if ((object)bestType == null || bestType.IsVoidType()) // Dev10 also reports ERR_ImplicitlyTypedArrayNoBestType for void. @@ -3273,7 +3273,7 @@ private BoundExpression BindImplicitStackAllocArrayCreationExpression(ImplicitSt ImmutableArray boundInitializerExpressions = BindArrayInitializerExpressions(initializer, diagnostics, dimension: 1, rank: 1); CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); - TypeSymbol bestType = BestTypeInferrer.InferBestType(boundInitializerExpressions, this.Conversions, ref useSiteInfo); + TypeSymbol bestType = BestTypeInferrer.InferBestType(boundInitializerExpressions, this.Conversions, ref useSiteInfo, out _); diagnostics.Add(node, useSiteInfo); if ((object)bestType == null || bestType.IsVoidType()) diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs index 412fe53b7a8fd..89ebc123adfda 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/BestTypeInferrer.cs @@ -51,7 +51,8 @@ public static NullableFlowState GetNullableState(ArrayBuilder typ public static TypeSymbol? InferBestType( ImmutableArray exprs, ConversionsBase conversions, - ref CompoundUseSiteInfo useSiteInfo) + ref CompoundUseSiteInfo useSiteInfo, + out bool inferredFromFunctionType) { // SPEC: 7.5.2.14 Finding the best common type of a set of expressions // SPEC: In some cases, a common type needs to be inferred for a set of expressions. In particular, the element types of implicitly typed arrays and @@ -74,6 +75,7 @@ public static NullableFlowState GetNullableState(ArrayBuilder typ { if (type.IsErrorType()) { + inferredFromFunctionType = false; return type; } @@ -87,7 +89,14 @@ public static NullableFlowState GetNullableState(ArrayBuilder typ var result = GetBestType(builder, conversions, ref useSiteInfo); builder.Free(); - return (result as FunctionTypeSymbol)?.GetInternalDelegateType() ?? result; + if (result is FunctionTypeSymbol functionType) + { + inferredFromFunctionType = true; + return functionType.GetInternalDelegateType(); + } + + inferredFromFunctionType = false; + return result; } /// diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs index 529c703bdfb68..3d6df87fe2654 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/MethodTypeInference.cs @@ -1310,6 +1310,8 @@ private bool InferredReturnTypeInference(BoundExpression source, TypeWithAnnotat return false; } + Debug.Assert(inferredReturnType.Type is not FunctionTypeSymbol); + LowerBoundInference(inferredReturnType, returnType, ref useSiteInfo); return true; } @@ -2924,7 +2926,12 @@ private TypeWithAnnotations InferReturnType(BoundExpression source, NamedTypeSym // the anonymous function is explicitly typed. Make an inference from the // delegate parameters to the return type. - return anonymousFunction.InferReturnType(_conversions, fixedDelegate, ref useSiteInfo); + var returnType = anonymousFunction.InferReturnType(_conversions, fixedDelegate, ref useSiteInfo, out bool inferredFromFunctionType); + if (inferredFromFunctionType) + { + return default; + } + return returnType; } /// diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs index 07965c314f1c3..be0401ed762a0 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/OverloadResolution/OverloadResolution.cs @@ -2539,7 +2539,7 @@ private bool ExpressionMatchExactly(BoundExpression node, TypeSymbol t, ref Comp BoundLambda lambda = ((UnboundLambda)node).BindForReturnTypeInference(d); // - an inferred return type X exists for E in the context of the parameter list of D(ยง7.5.2.12), and an identity conversion exists from X to Y - var x = lambda.GetInferredReturnType(ref useSiteInfo); + var x = lambda.GetInferredReturnType(ref useSiteInfo, out _); if (x.HasType && Conversions.HasIdentityConversion(x.Type, y)) { return true; @@ -2962,7 +2962,7 @@ private bool CanDowngradeConversionFromLambdaToNeither(BetterResult currentResul return true; } - var x = lambda.InferReturnType(Conversions, d1, ref useSiteInfo); + var x = lambda.InferReturnType(Conversions, d1, ref useSiteInfo, out _); if (!x.HasType) { return true; diff --git a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs index aba8ee997b464..20f4e77f084f9 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/UnboundLambda.cs @@ -41,6 +41,7 @@ internal readonly struct InferredLambdaReturnType internal readonly bool HadExpressionlessReturn; internal readonly RefKind RefKind; internal readonly TypeWithAnnotations TypeWithAnnotations; + internal readonly bool InferredFromFunctionType; internal readonly ImmutableArray UseSiteDiagnostics; internal readonly ImmutableArray Dependencies; @@ -50,6 +51,7 @@ internal InferredLambdaReturnType( bool hadExpressionlessReturn, RefKind refKind, TypeWithAnnotations typeWithAnnotations, + bool inferredFromFunctionType, ImmutableArray useSiteDiagnostics, ImmutableArray dependencies) { @@ -58,6 +60,7 @@ internal InferredLambdaReturnType( HadExpressionlessReturn = hadExpressionlessReturn; RefKind = refKind; TypeWithAnnotations = typeWithAnnotations; + InferredFromFunctionType = inferredFromFunctionType; UseSiteDiagnostics = useSiteDiagnostics; Dependencies = dependencies; } @@ -85,10 +88,10 @@ public BoundLambda(SyntaxNode syntax, UnboundLambda unboundLambda, BoundBlock bo ); } - public TypeWithAnnotations GetInferredReturnType(ref CompoundUseSiteInfo useSiteInfo) + public TypeWithAnnotations GetInferredReturnType(ref CompoundUseSiteInfo useSiteInfo, out bool inferredFromFunctionType) { // Nullability (and conversions) are ignored. - return GetInferredReturnType(conversions: null, nullableState: null, ref useSiteInfo); + return GetInferredReturnType(conversions: null, nullableState: null, ref useSiteInfo, out inferredFromFunctionType); } /// @@ -96,7 +99,7 @@ public TypeWithAnnotations GetInferredReturnType(ref CompoundUseSiteInfo - public TypeWithAnnotations GetInferredReturnType(ConversionsBase? conversions, NullableWalker.VariableState? nullableState, ref CompoundUseSiteInfo useSiteInfo) + public TypeWithAnnotations GetInferredReturnType(ConversionsBase? conversions, NullableWalker.VariableState? nullableState, ref CompoundUseSiteInfo useSiteInfo, out bool inferredFromFunctionType) { if (!InferredReturnType.UseSiteDiagnostics.IsEmpty) { @@ -108,9 +111,11 @@ public TypeWithAnnotations GetInferredReturnType(ConversionsBase? conversions, N useSiteInfo.AddDependencies(InferredReturnType.Dependencies); } + InferredLambdaReturnType inferredReturnType; + if (nullableState == null || InferredReturnType.IsExplicitType) { - return InferredReturnType.TypeWithAnnotations; + inferredReturnType = InferredReturnType; } else { @@ -133,10 +138,12 @@ public TypeWithAnnotations GetInferredReturnType(ConversionsBase? conversions, N initialState: nullableState, returnTypes); diagnostics.Free(); - var inferredReturnType = InferReturnType(returnTypes, node: this, Binder, delegateType, Symbol.IsAsync, conversions); + inferredReturnType = InferReturnType(returnTypes, node: this, Binder, delegateType, Symbol.IsAsync, conversions); returnTypes.Free(); - return inferredReturnType.TypeWithAnnotations; } + + inferredFromFunctionType = inferredReturnType.InferredFromFunctionType; + return inferredReturnType.TypeWithAnnotations; } internal LambdaSymbol CreateLambdaSymbol(NamedTypeSymbol delegateType, Symbol containingSymbol) => @@ -202,13 +209,17 @@ private static InferredLambdaReturnType InferReturnTypeImpl(ArrayBuilder<(BoundR } var useSiteInfo = withDependencies ? new CompoundUseSiteInfo(binder.Compilation.Assembly) : CompoundUseSiteInfo.DiscardedDependencies; - var bestType = CalculateReturnType(binder, conversions, delegateType, types, isAsync, node, ref useSiteInfo); + var bestType = CalculateReturnType(binder, conversions, delegateType, types, isAsync, node, ref useSiteInfo, out bool inferredFromFunctionType); + Debug.Assert(bestType.Type is not FunctionTypeSymbol); int numExpressions = types.Count; types.Free(); return new InferredLambdaReturnType( numExpressions, isExplicitType: false, - hasReturnWithoutArgument, refKind, bestType, + hadExpressionlessReturn: hasReturnWithoutArgument, + refKind, + bestType, + inferredFromFunctionType: inferredFromFunctionType, useSiteInfo.Diagnostics.AsImmutableOrEmpty(), useSiteInfo.AccumulatesDependencies ? useSiteInfo.Dependencies.AsImmutableOrEmpty() : ImmutableArray.Empty); } @@ -220,26 +231,35 @@ private static TypeWithAnnotations CalculateReturnType( ArrayBuilder<(BoundExpression expr, TypeWithAnnotations resultType)> returns, bool isAsync, BoundNode node, - ref CompoundUseSiteInfo useSiteInfo) + ref CompoundUseSiteInfo useSiteInfo, + out bool inferredFromFunctionType) { TypeWithAnnotations bestResultType; int n = returns.Count; switch (n) { case 0: + inferredFromFunctionType = false; bestResultType = default; break; case 1: if (conversions.IncludeNullability) { + inferredFromFunctionType = false; bestResultType = returns[0].resultType; } else { - var exprType = returns[0].expr.GetTypeOrFunctionType(); - var bestType = exprType is FunctionTypeSymbol functionType ? - functionType.GetInternalDelegateType() : - exprType; + var bestType = returns[0].expr.GetTypeOrFunctionType(); + if (bestType is FunctionTypeSymbol functionType) + { + inferredFromFunctionType = true; + bestType = functionType.GetInternalDelegateType(); + } + else + { + inferredFromFunctionType = false; + } bestResultType = TypeWithAnnotations.Create(bestType); } break; @@ -247,11 +267,11 @@ private static TypeWithAnnotations CalculateReturnType( // Need to handle ref returns. See https://github.com/dotnet/roslyn/issues/30432 if (conversions.IncludeNullability) { - bestResultType = NullableWalker.BestTypeForLambdaReturns(returns, binder, node, (Conversions)conversions); + bestResultType = NullableWalker.BestTypeForLambdaReturns(returns, binder, node, (Conversions)conversions, out inferredFromFunctionType); } else { - var bestType = BestTypeInferrer.InferBestType(returns.SelectAsArray(pair => pair.expr), conversions, ref useSiteInfo); + var bestType = BestTypeInferrer.InferBestType(returns.SelectAsArray(pair => pair.expr), conversions, ref useSiteInfo, out inferredFromFunctionType); bestResultType = TypeWithAnnotations.Create(bestType); } break; @@ -424,8 +444,8 @@ public bool HasExplicitReturnType(out RefKind refKind, out TypeWithAnnotations r => Data.HasExplicitReturnType(out refKind, out returnType); public bool HasExplicitlyTypedParameterList { get { return Data.HasExplicitlyTypedParameterList; } } public int ParameterCount { get { return Data.ParameterCount; } } - public TypeWithAnnotations InferReturnType(ConversionsBase conversions, NamedTypeSymbol delegateType, ref CompoundUseSiteInfo useSiteInfo) - => BindForReturnTypeInference(delegateType).GetInferredReturnType(conversions, _nullableState, ref useSiteInfo); + public TypeWithAnnotations InferReturnType(ConversionsBase conversions, NamedTypeSymbol delegateType, ref CompoundUseSiteInfo useSiteInfo, out bool inferredFromFunctionType) + => BindForReturnTypeInference(delegateType).GetInferredReturnType(conversions, _nullableState, ref useSiteInfo, out inferredFromFunctionType); public RefKind RefKind(int index) { return Data.RefKind(index); } public void GenerateAnonymousFunctionConversionError(BindingDiagnosticBag diagnostics, TypeSymbol targetType) { Data.GenerateAnonymousFunctionConversionError(diagnostics, targetType); } @@ -816,6 +836,7 @@ private BoundLambda ReallyInferReturnType( hadExpressionlessReturn: false, refKind, returnType, + inferredFromFunctionType: false, ImmutableArray.Empty, ImmutableArray.Empty); } @@ -1094,7 +1115,15 @@ private BoundLambda ReallyBindForErrorRecovery( diagnostics.ToReadOnlyAndFree(), lambdaBodyBinder, delegateType, - new InferredLambdaReturnType(inferredReturnType.NumExpressions, isExplicitType: inferredReturnType.IsExplicitType, inferredReturnType.HadExpressionlessReturn, refKind, returnType, ImmutableArray.Empty, ImmutableArray.Empty)) + new InferredLambdaReturnType( + inferredReturnType.NumExpressions, + isExplicitType: inferredReturnType.IsExplicitType, + inferredReturnType.HadExpressionlessReturn, + refKind, + returnType, + inferredFromFunctionType: inferredReturnType.InferredFromFunctionType, + ImmutableArray.Empty, + ImmutableArray.Empty)) { WasCompilerGenerated = _unboundLambda.WasCompilerGenerated }; } diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs index 5f8526400fde5..7d5ac907f88dd 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker.cs @@ -3457,7 +3457,7 @@ private int GetOrCreatePlaceholderSlot(object identifier, TypeWithAnnotations ty if (!node.HasErrors) { var discardedUseSiteInfo = CompoundUseSiteInfo.Discarded; - bestType = BestTypeInferrer.InferBestType(placeholders, _conversions, ref discardedUseSiteInfo); + bestType = BestTypeInferrer.InferBestType(placeholders, _conversions, ref discardedUseSiteInfo, out _); } TypeWithAnnotations inferredType = (bestType is null) @@ -3517,7 +3517,8 @@ internal static TypeWithAnnotations BestTypeForLambdaReturns( ArrayBuilder<(BoundExpression, TypeWithAnnotations)> returns, Binder binder, BoundNode node, - Conversions conversions) + Conversions conversions, + out bool inferredFromFunctionType) { var walker = new NullableWalker(binder.Compilation, symbol: null, @@ -3545,7 +3546,7 @@ internal static TypeWithAnnotations BestTypeForLambdaReturns( var discardedUseSiteInfo = CompoundUseSiteInfo.Discarded; var placeholders = placeholdersBuilder.ToImmutableAndFree(); - TypeSymbol? bestType = BestTypeInferrer.InferBestType(placeholders, walker._conversions, ref discardedUseSiteInfo); + TypeSymbol? bestType = BestTypeInferrer.InferBestType(placeholders, walker._conversions, ref discardedUseSiteInfo, out inferredFromFunctionType); TypeWithAnnotations inferredType; if (bestType is { }) diff --git a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs index 4095c35d4d275..bde4416716685 100644 --- a/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs +++ b/src/Compilers/CSharp/Portable/FlowAnalysis/NullableWalker_Patterns.cs @@ -819,7 +819,7 @@ private void VisitSwitchExpressionCore(BoundSwitchExpression node, bool inferTyp var discardedUseSiteInfo = CompoundUseSiteInfo.Discarded; TypeSymbol inferredType = - (inferType ? BestTypeInferrer.InferBestType(placeholders, _conversions, ref discardedUseSiteInfo) : null) + (inferType ? BestTypeInferrer.InferBestType(placeholders, _conversions, ref discardedUseSiteInfo, out _) : null) ?? node.Type?.SetUnknownNullabilityForReferenceTypes(); var inferredTypeWithAnnotations = TypeWithAnnotations.Create(inferredType); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/DelegateTypeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/DelegateTypeTests.cs index f41b2be42c353..f50ef99d07f28 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/DelegateTypeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/DelegateTypeTests.cs @@ -3405,11 +3405,19 @@ static void Main() F((string s) => { }); } }"; - var comp = CreateCompilation(source); - comp.VerifyDiagnostics( + + var expectedDiagnostics = new[] + { // (8,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F(Action)' and 'Program.F(StringAction)' // F((string s) => { }); - Diagnostic(ErrorCode.ERR_AmbigCall, "F").WithArguments("Program.F(System.Action)", "Program.F(StringAction)").WithLocation(8, 9)); + Diagnostic(ErrorCode.ERR_AmbigCall, "F").WithArguments("Program.F(System.Action)", "Program.F(StringAction)").WithLocation(8, 9) + }; + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source, parseOptions: TestOptions.Regular10); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source); + comp.VerifyDiagnostics(expectedDiagnostics); } [Fact] @@ -3429,11 +3437,19 @@ static void Main() F1(M); } }"; - var comp = CreateCompilation(source); - comp.VerifyDiagnostics( + + var expectedDiagnostics = new[] + { // (10,9): error CS0411: The type arguments for method 'Program.F0(Action)' cannot be inferred from the usage. Try specifying the type arguments explicitly. // F0(M); - Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F0").WithArguments("Program.F0(System.Action)").WithLocation(10, 9)); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F0").WithArguments("Program.F0(System.Action)").WithLocation(10, 9) + }; + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source, parseOptions: TestOptions.Regular10); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source); + comp.VerifyDiagnostics(expectedDiagnostics); } [Fact] @@ -3452,14 +3468,22 @@ static void Main() F(M); } }"; - var comp = CreateCompilation(source); - comp.VerifyDiagnostics( + + var expectedDiagnostics = new[] + { // (9,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F(Action)' and 'Program.F(MyAction)' // F((string s) => { }); Diagnostic(ErrorCode.ERR_AmbigCall, "F").WithArguments("Program.F(System.Action)", "Program.F(MyAction)").WithLocation(9, 9), // (10,9): error CS0411: The type arguments for method 'Program.F(Action)' cannot be inferred from the usage. Try specifying the type arguments explicitly. // F(M); - Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F").WithArguments("Program.F(System.Action)").WithLocation(10, 9)); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "F").WithArguments("Program.F(System.Action)").WithLocation(10, 9) + }; + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source, parseOptions: TestOptions.Regular10); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source); + comp.VerifyDiagnostics(expectedDiagnostics); } [Fact] @@ -3479,14 +3503,22 @@ static void Main() F((string s) => { }); } }"; - var comp = CreateCompilation(source); - comp.VerifyDiagnostics( + + var expectedDiagnostics = new[] + { // (10,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F(Action)' and 'Program.F(StringAction)' // F(M); Diagnostic(ErrorCode.ERR_AmbigCall, "F").WithArguments("Program.F(System.Action)", "Program.F(StringAction)").WithLocation(10, 9), // (11,9): error CS0121: The call is ambiguous between the following methods or properties: 'Program.F(Action)' and 'Program.F(StringAction)' // F((string s) => { }); - Diagnostic(ErrorCode.ERR_AmbigCall, "F").WithArguments("Program.F(System.Action)", "Program.F(StringAction)").WithLocation(11, 9)); + Diagnostic(ErrorCode.ERR_AmbigCall, "F").WithArguments("Program.F(System.Action)", "Program.F(StringAction)").WithLocation(11, 9) + }; + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source, parseOptions: TestOptions.Regular10); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source); + comp.VerifyDiagnostics(expectedDiagnostics); } [Fact] @@ -6490,6 +6522,364 @@ static void Main() Diagnostic(ErrorCode.WRN_NullReferenceReceiver, "y4").WithLocation(25, 9)); } + [WorkItem(57517, "https://github.com/dotnet/roslyn/issues/57517")] + [Fact] + public void TypeInference_03() + { + var source = +@"using System; +using System.Linq.Expressions; + +void Test1(Func exp) {} +void Test2(Expression> exp) {} +void Test3(Func> exp) {} +void Test4(Func>> exp) {} + +Test1(() => 1); +Test2(() => 2); +Test3(() => () => 3); +Test4(() => () => 4); +"; + + var expectedDiagnostics = new[] + { + // (6,6): warning CS8321: The local function 'Test3' is declared but never used + // void Test3(Func> exp) {} + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test3").WithArguments("Test3").WithLocation(6, 6), + // (7,6): warning CS8321: The local function 'Test4' is declared but never used + // void Test4(Func>> exp) {} + Diagnostic(ErrorCode.WRN_UnreferencedLocalFunction, "Test4").WithArguments("Test4").WithLocation(7, 6), + // (11,1): error CS0411: The type arguments for method 'Test3(Func>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // Test3(() => () => 3); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Test3").WithArguments("Test3(System.Func>)").WithLocation(11, 1), + // (12,1): error CS0411: The type arguments for method 'Test4(Func>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // Test4(() => () => 4); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Test4").WithArguments("Test4(System.Func>>)").WithLocation(12, 1) + }; + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source, parseOptions: TestOptions.Regular10); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source); + comp.VerifyDiagnostics(expectedDiagnostics); + } + + [WorkItem(57517, "https://github.com/dotnet/roslyn/issues/57517")] + [Fact] + public void TypeInference_04() + { + var source = +@"#nullable enable +using System; +using System.Linq.Expressions; +delegate int D(); +class Program +{ + static int F() => 0; + static void M1(T t, Func f) { } + static void M2(T t, Expression> e) { } + static void Main() + { + D d = null; + M1(d, () => F); + M2(d, () => F); + M1(d, () => () => 1); + M2(d, () => () => 2); + } +}"; + + CompileAndVerify(source, parseOptions: TestOptions.Regular9); + CompileAndVerify(source, parseOptions: TestOptions.Regular10); + CompileAndVerify(source); + } + + [WorkItem(57517, "https://github.com/dotnet/roslyn/issues/57517")] + [Fact] + public void TypeInference_05() + { + var source = +@"#nullable enable +using System; +using System.Linq.Expressions; +delegate int D(); +class Program +{ + static int F() => 0; + static void M1(ref T t, Func f) { } + static void M2(ref T t, Expression> e) { } + static void Main() + { + D d = null; + M1(ref d, () => F); + M2(ref d, () => F); + M1(ref d, () => () => 1); + M2(ref d, () => () => 2); + } +}"; + + CompileAndVerify(source, parseOptions: TestOptions.Regular9); + CompileAndVerify(source, parseOptions: TestOptions.Regular10); + CompileAndVerify(source); + } + + [WorkItem(57517, "https://github.com/dotnet/roslyn/issues/57517")] + [Fact] + public void TypeInference_06() + { + var source = +@"#nullable enable +using System; +using System.Linq.Expressions; +class Program +{ + static int F() => 0; + static void M1(Func f) { } + static void M2(Expression> e) { } + static void Main() + { + M1(() => F); + M2(() => F); + M1(() => () => 1); + M2(() => () => 2); + } +}"; + + var expectedDiagnostics = new[] + { + // (11,9): error CS0411: The type arguments for method 'Program.M1(Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // M1(() => F); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M1").WithArguments("Program.M1(System.Func)").WithLocation(11, 9), + // (12,9): error CS0411: The type arguments for method 'Program.M2(Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // M2(() => F); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M2").WithArguments("Program.M2(System.Linq.Expressions.Expression>)").WithLocation(12, 9), + // (13,9): error CS0411: The type arguments for method 'Program.M1(Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // M1(() => () => 1); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M1").WithArguments("Program.M1(System.Func)").WithLocation(13, 9), + // (14,9): error CS0411: The type arguments for method 'Program.M2(Expression>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // M2(() => () => 2); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M2").WithArguments("Program.M2(System.Linq.Expressions.Expression>)").WithLocation(14, 9) + }; + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source, parseOptions: TestOptions.Regular10); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source); + comp.VerifyDiagnostics(expectedDiagnostics); + } + + [WorkItem(57517, "https://github.com/dotnet/roslyn/issues/57517")] + [Fact] + public void TypeInference_07() + { + var source = +@"#nullable enable +using System; +using System.Linq.Expressions; +class Program +{ + static int F() => 0; + static void M1(Func> f) { } + static void M2(Func>> e) { } + static void M3(Expression>> e) { } + static void Main() + { + M1(() => () => F); + M2(() => () => F); + M3(() => () => F); + M1(() => () => () => 1); + M2(() => () => () => 2); + M3(() => () => () => 3); + } +}"; + + var expectedDiagnostics = new[] + { + // (12,9): error CS0411: The type arguments for method 'Program.M1(Func>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // M1(() => () => F); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M1").WithArguments("Program.M1(System.Func>)").WithLocation(12, 9), + // (13,9): error CS0411: The type arguments for method 'Program.M2(Func>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // M2(() => () => F); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M2").WithArguments("Program.M2(System.Func>>)").WithLocation(13, 9), + // (14,9): error CS0411: The type arguments for method 'Program.M3(Expression>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // M3(() => () => F); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M3").WithArguments("Program.M3(System.Linq.Expressions.Expression>>)").WithLocation(14, 9), + // (15,9): error CS0411: The type arguments for method 'Program.M1(Func>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // M1(() => () => () => 1); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M1").WithArguments("Program.M1(System.Func>)").WithLocation(15, 9), + // (16,9): error CS0411: The type arguments for method 'Program.M2(Func>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // M2(() => () => () => 2); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M2").WithArguments("Program.M2(System.Func>>)").WithLocation(16, 9), + // (17,9): error CS0411: The type arguments for method 'Program.M3(Expression>>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // M3(() => () => () => 3); + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "M3").WithArguments("Program.M3(System.Linq.Expressions.Expression>>)").WithLocation(17, 9) + }; + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source, parseOptions: TestOptions.Regular10); + comp.VerifyDiagnostics(expectedDiagnostics); + comp = CreateCompilation(source); + comp.VerifyDiagnostics(expectedDiagnostics); + } + + [WorkItem(57517, "https://github.com/dotnet/roslyn/issues/57517")] + [Fact] + public void TypeInference_08() + { + var source = +@"#nullable enable +using System; +using System.Linq.Expressions; +delegate int D(); +class Program +{ + static int F() => 0; + static void M1(T t, Func> f) { } + static void M2(T t, Func>> e) { } + static void M3(T t, Expression>> e) { } + static void Main() + { + D d = null; + M1(d, () => () => F); + M2(d, () => () => F); + M3(d, () => () => F); + M1(d, () => () => () => 1); + M2(d, () => () => () => 2); + M3(d, () => () => () => 3); + } +}"; + + CompileAndVerify(source, parseOptions: TestOptions.Regular9); + CompileAndVerify(source, parseOptions: TestOptions.Regular10); + CompileAndVerify(source); + } + + [WorkItem(57517, "https://github.com/dotnet/roslyn/issues/57517")] + [Fact] + public void TypeInference_09() + { + var source = +@"#nullable enable +using System; +delegate void D(object x, T y); +class Program +{ + static void F(object x, int y) { } + static void M(T t, Func f) { } + static void Main() + { + D d = null; + M(d, () => F); + M(d, () => (object x, int y) => { }); + } +}"; + + CompileAndVerify(source, parseOptions: TestOptions.Regular9); + CompileAndVerify(source, parseOptions: TestOptions.Regular10); + CompileAndVerify(source); + } + + [WorkItem(57517, "https://github.com/dotnet/roslyn/issues/57517")] + [Fact] + public void TypeInference_10() + { + var source = +@"#nullable enable +using System; +delegate void D1(object x, T y); +delegate T D2(); +class Program +{ + static void F(object x, int y) { } + static void M(T t, D2 d) { } + static void Main() + { + D1 d = null; + M(d, () => F); + M(d, () => (object x, int y) => { }); + } +}"; + + CompileAndVerify(source, parseOptions: TestOptions.Regular9); + CompileAndVerify(source, parseOptions: TestOptions.Regular10); + CompileAndVerify(source); + } + + [WorkItem(57517, "https://github.com/dotnet/roslyn/issues/57517")] + [Fact] + public void TypeInference_11() + { + var source = +@"#nullable enable +using System; +delegate T D1(); +delegate T D2(ref object o); +class Program +{ + static int F() => 0; + static void M(T t, D2 d) { } + static void Main() + { + D1 d = null; + M(d, (ref object o) => F); + M(d, (ref object o) => () => 1); + } +}"; + + CompileAndVerify(source, parseOptions: TestOptions.Regular9); + CompileAndVerify(source, parseOptions: TestOptions.Regular10); + CompileAndVerify(source); + } + + [WorkItem(57517, "https://github.com/dotnet/roslyn/issues/57517")] + [Fact] + public void TypeInference_12() + { + var source = +@"#nullable enable +using System; +delegate int D(); +class Program +{ + static void M(T t, Func f) { } + static void Main() + { + D d = null; + M(d, (bool b) => { if (b) return () => 1; return () => 2; }); + } +}"; + + CompileAndVerify(source, parseOptions: TestOptions.Regular9); + CompileAndVerify(source, parseOptions: TestOptions.Regular10); + CompileAndVerify(source); + } + + [WorkItem(57630, "https://github.com/dotnet/roslyn/issues/57630")] + [Fact] + public void TypeInference_13() + { + var source = +@"#nullable enable +using System; +delegate void D(); +class C { } +static class E +{ + public static void F(this C c, Func f) { } +} +class Program +{ + static void Main() + { + var c = new C(); + c.F(() => () => { }); + } +}"; + + CompileAndVerify(source, parseOptions: TestOptions.Regular9); + CompileAndVerify(source, parseOptions: TestOptions.Regular10); + CompileAndVerify(source); + } + [Fact] public void Variance_01() {