diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs index 19d872a4142fd..f4c2070227d3b 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs @@ -641,8 +641,10 @@ private BoundExpression BindLocalFunctionInvocationWithDynamicArgument( Debug.Assert(queryClause == null); var validResult = resolution.OverloadResolutionResult.ValidResult; + var args = resolution.AnalyzedArguments.Arguments.ToImmutable(); + + ReportBadDynamicArguments(syntax, args, diagnostics, queryClause); - var args = resolution.AnalyzedArguments.Arguments; var localFunction = validResult.Member; var methodResult = validResult.Result; @@ -659,7 +661,7 @@ private BoundExpression BindLocalFunctionInvocationWithDynamicArgument( var lastParamIndex = parameters.Length - 1; - for (int i = 0; i < args.Count; ++i) + for (int i = 0; i < args.Length; ++i) { var arg = args[i]; if (arg.HasDynamicType() && diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs index 726c9549447b3..23703add6fdcf 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs @@ -3090,5 +3090,52 @@ class Test : System.Attribute Assert.Equal("System.Boolean b1", b1Symbol.ToTestDisplayString()); Assert.Equal(SymbolKind.Local, b1Symbol.Kind); } + + [Fact] + [WorkItem(19778, "https://github.com/dotnet/roslyn/issues/19778")] + public void BindDynamicInvocation() + { + var source = +@"using System; +class C +{ + static void M() + { + dynamic L(Func t, object p) => p; + L(m => L(d => d, null), null); + L(m => L(d => d, m), null); + } +}"; + var comp = CreateCompilationWithMscorlib45(source, references: new[] { SystemCoreRef, CSharpRef }); + comp.VerifyEmitDiagnostics( + // (8,18): error CS1977: Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type. + // L(m => L(d => d, m), null); + Diagnostic(ErrorCode.ERR_BadDynamicMethodArgLambda, "d => d").WithLocation(8, 18)); + } + + [Fact] + [WorkItem(19778, "https://github.com/dotnet/roslyn/issues/19778")] + public void BindDynamicInvocation_Async() + { + var source = +@"using System; +using System.Threading.Tasks; +class C +{ + static void M() + { + async Task L(Func t, object p) + => await L(async m => L(async d => await d, m), p); + } +}"; + var comp = CreateCompilationWithMscorlib45(source, references: new[] { SystemCoreRef, CSharpRef }); + comp.VerifyEmitDiagnostics( + // (8,37): error CS1977: Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type. + // => await L(async m => L(async d => await d, m), p); + Diagnostic(ErrorCode.ERR_BadDynamicMethodArgLambda, "async d => await d").WithLocation(8, 37), + // (8,32): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread. + // => await L(async m => L(async d => await d, m), p); + Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(8, 32)); + } } }