diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.WithQueryLambdaParametersBinder.cs b/src/Compilers/CSharp/Portable/Binder/Binder.WithQueryLambdaParametersBinder.cs index 45327918bd41e34093538557ad3bc7b11f011791..ff049ee8b93ece76b3a9f24a07f3c0c2289e40ff 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder.WithQueryLambdaParametersBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder.WithQueryLambdaParametersBinder.cs @@ -72,10 +72,12 @@ private BoundExpression SelectField(SimpleNameSyntax node, BoundExpression recei { // We only construct transparent query variables using anonymous types, so if we're trying to navigate through // some other type, we must have some query API where the types don't match up as expected. - // We should report this as an error of some sort. - // TODO: DevDiv #737822 - reword error message and add test. var info = new CSDiagnosticInfo(ErrorCode.ERR_UnsupportedTransparentIdentifierAccess, name, receiver.ExpressionSymbol ?? receiverType); - Error(diagnostics, info, node); + if (receiver.Type?.IsErrorType() != true) + { + Error(diagnostics, info, node); + } + return new BoundBadExpression( node, LookupResultKind.Empty, diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs index 2705b1077a1963842464f69943ecaf2ee72223d6..299ebc62543fe50113497927450278127489f123 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs @@ -713,11 +713,23 @@ private static void CheckRestrictedTypeReceiver(BoundExpression expression, Comp if (!result.Succeeded) { - // If the arguments had an error reported about them then suppress further error - // reporting for overload resolution. - - if (!analyzedArguments.HasErrors) + if (analyzedArguments.HasErrors) + { + // Errors for arguments have already been reported, except for unbound lambdas. + // We report those now. + foreach (var argument in analyzedArguments.Arguments) + { + var unboundLambda = argument as UnboundLambda; + if (unboundLambda != null) + { + var boundWithErrors = unboundLambda.BindForErrorRecovery(); + diagnostics.AddRange(boundWithErrors.Diagnostics); + } + } + } + else { + // Since there were no argument errors to report, we report an error on the invocation itself. string name = (object)delegateTypeOpt == null ? methodName : null; result.ReportDiagnostics(this, GetLocationForOverloadResolutionDiagnostic(node, expression), diagnostics, name, methodGroup.Receiver, analyzedArguments, methodGroup.Methods.ToImmutable(), diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs index be9d12110146f24ffb084f398b4b42085c1d95df..69edbb35936bc9027d96348a5b0203821428f32b 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LambdaTests.cs @@ -1465,5 +1465,99 @@ static void Main(string[] args) CompileAndVerify(compilation); } + + [Fact] + [WorkItem(1867, "https://github.com/dotnet/roslyn/issues/1867")] + public void TestLambdaWithError01() + { + var source = +@"using System.Linq; +class C { C() { string.Empty.Select(() => { new Unbound1 }); } }"; + CreateCompilationWithMscorlibAndSystemCore(source).VerifyDiagnostics( + // (2,58): error CS1526: A new expression requires (), [], or {} after type + // class C { C() { string.Empty.Select(() => { new Unbound1 }); } } + Diagnostic(ErrorCode.ERR_BadNewExpr, "}").WithLocation(2, 58), + // (2,58): error CS1002: ; expected + // class C { C() { string.Empty.Select(() => { new Unbound1 }); } } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "}").WithLocation(2, 58), + // (2,49): error CS0246: The type or namespace name 'Unbound1' could not be found (are you missing a using directive or an assembly reference?) + // class C { C() { string.Empty.Select(() => { new Unbound1 }); } } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unbound1").WithArguments("Unbound1").WithLocation(2, 49) + ); + } + + [Fact] + [WorkItem(1867, "https://github.com/dotnet/roslyn/issues/1867")] + public void TestLambdaWithError02() + { + var source = +@"using System.Linq; +class C { C() { string.Empty.Select(() => { new Unbound1 ( ) }); } }"; + CreateCompilationWithMscorlibAndSystemCore(source).VerifyDiagnostics( + // (2,62): error CS1002: ; expected + // class C { C() { string.Empty.Select(() => { new Unbound1 ( ) }); } } + Diagnostic(ErrorCode.ERR_SemicolonExpected, "}").WithLocation(2, 62), + // (2,49): error CS0246: The type or namespace name 'Unbound1' could not be found (are you missing a using directive or an assembly reference?) + // class C { C() { string.Empty.Select(() => { new Unbound1 ( ) }); } } + Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Unbound1").WithArguments("Unbound1").WithLocation(2, 49) + ); + } + + [Fact] + [WorkItem(1867, "https://github.com/dotnet/roslyn/issues/1867")] + public void TestLambdaWithError03() + { + var source = +@"using System.Linq; +class C { C() { string.Empty.Select(x => Unbound1, Unbound2 Unbound2); } }"; + CreateCompilationWithMscorlibAndSystemCore(source).VerifyDiagnostics( + // (2,61): error CS1003: Syntax error, ',' expected + // class C { C() { string.Empty.Select(x => Unbound1, Unbound2 Unbound2); } } + Diagnostic(ErrorCode.ERR_SyntaxError, "Unbound2").WithArguments(",", "").WithLocation(2, 61), + // (2,52): error CS0103: The name 'Unbound2' does not exist in the current context + // class C { C() { string.Empty.Select(x => Unbound1, Unbound2 Unbound2); } } + Diagnostic(ErrorCode.ERR_NameNotInContext, "Unbound2").WithArguments("Unbound2").WithLocation(2, 52), + // (2,61): error CS0103: The name 'Unbound2' does not exist in the current context + // class C { C() { string.Empty.Select(x => Unbound1, Unbound2 Unbound2); } } + Diagnostic(ErrorCode.ERR_NameNotInContext, "Unbound2").WithArguments("Unbound2").WithLocation(2, 61), + // (2,42): error CS0103: The name 'Unbound1' does not exist in the current context + // class C { C() { string.Empty.Select(x => Unbound1, Unbound2 Unbound2); } } + Diagnostic(ErrorCode.ERR_NameNotInContext, "Unbound1").WithArguments("Unbound1").WithLocation(2, 42) + ); + } + + [Fact] + [WorkItem(1867, "https://github.com/dotnet/roslyn/issues/1867")] + public void TestLambdaWithError04() + { + var source = +@"using System.Linq; +class C { C() { string.Empty.Select(x => Unbound1, Unbound2); } }"; + CreateCompilationWithMscorlibAndSystemCore(source).VerifyDiagnostics( + // (2,52): error CS0103: The name 'Unbound2' does not exist in the current context + // class C { C() { string.Empty.Select(x => Unbound1, Unbound2); } } + Diagnostic(ErrorCode.ERR_NameNotInContext, "Unbound2").WithArguments("Unbound2").WithLocation(2, 52), + // (2,42): error CS0103: The name 'Unbound1' does not exist in the current context + // class C { C() { string.Empty.Select(x => Unbound1, Unbound2); } } + Diagnostic(ErrorCode.ERR_NameNotInContext, "Unbound1").WithArguments("Unbound1").WithLocation(2, 42) + ); + } + + [Fact] + [WorkItem(1867, "https://github.com/dotnet/roslyn/issues/1867")] + public void TestLambdaWithError05() + { + var source = +@"using System.Linq; +class C { C() { Unbound2.Select(x => Unbound1); } }"; + CreateCompilationWithMscorlibAndSystemCore(source).VerifyDiagnostics( + // (2,17): error CS0103: The name 'Unbound2' does not exist in the current context + // class C { C() { Unbound2.Select(x => Unbound1); } } + Diagnostic(ErrorCode.ERR_NameNotInContext, "Unbound2").WithArguments("Unbound2").WithLocation(2, 17), + // (2,38): error CS0103: The name 'Unbound1' does not exist in the current context + // class C { C() { Unbound2.Select(x => Unbound1); } } + Diagnostic(ErrorCode.ERR_NameNotInContext, "Unbound1").WithArguments("Unbound1").WithLocation(2, 38) + ); + } } }