diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 50c5af5d3838b..926e76fb7742c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -3165,6 +3165,10 @@ private BoundExpression BindArrayDimension(ExpressionSyntax dimension, Diagnosti hasErrors = true; } } + else + { + size = BindToTypeForErrorRecovery(size); + } return size; } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 4f55ba78ef4b5..9406b9fa4e8cc 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -2354,7 +2354,7 @@ internal BoundExpression BindBooleanExpression(ExpressionSyntax node, Diagnostic // The expression could not be bound. Insert a fake conversion // around it to bool and keep on going. // NOTE: no user-defined conversion candidates. - return BoundConversion.Synthesized(node, expr, Conversion.NoConversion, false, explicitCastInCode: false, conversionGroupOpt: null, ConstantValue.NotAvailable, boolean, hasErrors: true); + return BoundConversion.Synthesized(node, BindToTypeForErrorRecovery(expr), Conversion.NoConversion, false, explicitCastInCode: false, conversionGroupOpt: null, ConstantValue.NotAvailable, boolean, hasErrors: true); } // Oddly enough, "if(dyn)" is bound not as a dynamic conversion to bool, but as a dynamic diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs index 5a80651cfa5ca..8774cef88cb28 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IObjectCreationExpression.cs @@ -793,6 +793,132 @@ public void M1() VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: ImplicitObjectCreationOptions); } + [CompilerTrait(CompilerFeature.IOperation)] + [Fact, WorkItem(1198816, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1198816/")] + public void ImplicitObjectCreationUnconverted_ArrayIndex() + { + var comp = CreateCompilation("_ = new int[/**/new(bad)/**/];", options: TestOptions.ReleaseExe); + + var expectedDiagnostics = new DiagnosticDescription[] { + // (1,27): error CS0103: The name 'bad' does not exist in the current context + // _ = new int[/**/new(bad)/**/]; + Diagnostic(ErrorCode.ERR_NameNotInContext, "bad").WithArguments("bad").WithLocation(1, 27) + }; + + VerifyOperationTreeAndDiagnosticsForTest(comp, @" +IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'new(bad)') + Children(1): + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'bad') + Children(0) + ", expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact, WorkItem(1198816, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1198816/")] + public void ImplicitObjectCreationUnconverted_IfCondition() + { + var comp = CreateCompilation(@" +if (/**/new(bad)/**/) {} +", options: TestOptions.UnsafeReleaseExe); + + var expectedDiagnostics = new DiagnosticDescription[] { + // (2,19): error CS0103: The name 'bad' does not exist in the current context + // if (/**/new(bad)/**/) {} + Diagnostic(ErrorCode.ERR_NameNotInContext, "bad").WithArguments("bad").WithLocation(2, 19) + }; + + VerifyOperationTreeAndDiagnosticsForTest(comp, @" +IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'new(bad)') + Children(1): + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'bad') + Children(0) + ", expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact, WorkItem(1198816, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1198816/")] + public void ImplicitObjectCreationUnconverted_ConditionalOperator() + { + var source = +@"class Program +{ + static void Main() + { + _ = /**/new(bad)/**/ ? null : new object(); + } +}"; + var comp = CreateCompilation(source); + + var expectedDiagnostics = new DiagnosticDescription[] { + // (5,27): error CS0103: The name 'bad' does not exist in the current context + // _ = /**/new(bad)/**/ ? null : new object(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "bad").WithArguments("bad").WithLocation(5, 27) + }; + + VerifyOperationTreeAndDiagnosticsForTest(comp, @" +IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'new(bad)') + Children(1): + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'bad') + Children(0) + ", expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact, WorkItem(1198816, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1198816/")] + public void ImplicitObjectCreationUnconverted_ConditionalOperator_Nested1() + { + var source = +@"class Program +{ + static void Main() + { + _ = (/**/new(bad)/**/, null) ? null : new object(); + } +}"; + var comp = CreateCompilation(source); + + var expectedDiagnostics = new DiagnosticDescription[] { + // (5,28): error CS0103: The name 'bad' does not exist in the current context + // _ = (/**/new(bad)/**/, null) ? null : new object(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "bad").WithArguments("bad").WithLocation(5, 28) + }; + + VerifyOperationTreeAndDiagnosticsForTest(comp, @" +IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'new(bad)') + Children(1): + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'bad') + Children(0) + ", expectedDiagnostics); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact, WorkItem(1198816, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1198816/")] + public void ImplicitObjectCreationUnconverted_ConditionalOperator_Nested2() + { + var source = +@"class Program +{ + static void Main(int i) + { + _ = i switch { 1 => /**/new(bad)/**/, _ => null } ? null : new object(); + } +}"; + var comp = CreateCompilation(source); + + var expectedDiagnostics = new DiagnosticDescription[] { + // (5,43): error CS0103: The name 'bad' does not exist in the current context + // _ = i switch { 1 => /**/new(bad)/**/, _ => null } ? null : new object(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "bad").WithArguments("bad").WithLocation(5, 43) + }; + + VerifyOperationTreeAndDiagnosticsForTest(comp, @" +IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'new(bad)') + Children(1): + IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'bad') + Children(0) + ", expectedDiagnostics); + } + [CompilerTrait(CompilerFeature.IOperation)] [Fact] public void ImplicitObjectCreationWithDynamicMemberInitializer_01() diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/ConditionalOperatorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/ConditionalOperatorTests.cs index a2948049f8e80..6d8a5a0ac5dc8 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/ConditionalOperatorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/ConditionalOperatorTests.cs @@ -1499,5 +1499,24 @@ public TestClass Self() CompileAndVerify(compilation, expectedOutput: "---"); } + + [Fact, WorkItem(1198816, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1198816/")] + public void DefiniteAssignment_UnconvertedConditionalOperator() + { + var source = +@"class Program +{ + static void Main() + { + _ = new(bad) ? null : new object(); + } +}"; + var comp = CreateCompilation(source); + comp.VerifyDiagnostics( + // (5,17): error CS0103: The name 'bad' does not exist in the current context + // _ = new(bad) ? null : new object(); + Diagnostic(ErrorCode.ERR_NameNotInContext, "bad").WithArguments("bad").WithLocation(5, 17) + ); + } } }