diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
index 18d4c691a6950..59e99223b809f 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Operators.cs
@@ -5631,17 +5631,32 @@ private BoundExpression BindNullCoalescingAssignmentOperator(AssignmentExpressio
ReportSuppressionIfNeeded(leftOperand, diagnostics);
BoundExpression rightOperand = BindValue(node.Right, diagnostics, BindValueKind.RValue);
- // If either operand is bad, bail out preventing more cascading errors
- if (leftOperand.HasAnyErrors || rightOperand.HasAnyErrors)
+ TypeSymbol leftType = leftOperand.Type;
+
+ var rightOperandTargetType = leftType switch
+ {
+ { IsReferenceType: true } or { IsValueType: false, TypeKind: TypeKind.TypeParameter } => leftType,
+ { IsValueType: true } when leftType.IsNullableType() => leftType.GetNullableUnderlyingType(),
+ _ => null
+ };
+
+ // If left operand is bad or right operator is bad and we cannot determine its type, take the default error recovery path
+ if (leftOperand.HasAnyErrors || (rightOperandTargetType is null && rightOperand.HasAnyErrors))
{
leftOperand = BindToTypeForErrorRecovery(leftOperand);
rightOperand = BindToTypeForErrorRecovery(rightOperand);
return new BoundNullCoalescingAssignmentOperator(node, leftOperand, rightOperand, CreateErrorType(), hasErrors: true);
}
+ // If right operand is bad, but we know its type, make sure conversion is in place for better error recovery
+ else if (rightOperand.HasAnyErrors)
+ {
+ leftOperand = BindToTypeForErrorRecovery(leftOperand);
+ var conversion = GenerateConversionForAssignment(rightOperandTargetType, rightOperand, diagnostics, ConversionForAssignmentFlags.CompoundAssignment);
+ return new BoundNullCoalescingAssignmentOperator(node, leftOperand, conversion, rightOperandTargetType, hasErrors: true);
+ }
// Given a ??= b, the type of a is A, the type of B is b, and if A is a nullable value type, the underlying
// non-nullable value type of A is A0.
- TypeSymbol leftType = leftOperand.Type;
Debug.Assert((object)leftType != null);
// If A is a non-nullable value type, a compile-time error occurs
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullCoalesceAssignmentTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullCoalesceAssignmentTests.cs
index 158198d32499a..6a1c7dc0b62e8 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullCoalesceAssignmentTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullCoalesceAssignmentTests.cs
@@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
+using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
@@ -186,5 +187,635 @@ void M(int? a)
Assert.Equal(SpecialType.System_Int32, semanticModel.GetTypeInfo(defaultLiteral).Type.SpecialType);
Assert.Equal(SpecialType.System_Int32, semanticModel.GetTypeInfo(defaultLiteral).ConvertedType.SpecialType);
}
+
+ [Fact]
+ public void ErrorRecovery_ImplicitObjectCreation_ReferenceType()
+ {
+ var source = """
+ class C
+ {
+ void M()
+ {
+ C c = default;
+ c ??= /**/new(a)/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,29): error CS0103: The name 'a' does not exist in the current context
+ // c ??= /**/new(a)/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 29));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Equal("C", semanticInfo.Type.ToTestDisplayString());
+ Assert.Equal("C", semanticInfo.ConvertedType.ToTestDisplayString());
+
+ Assert.Null(semanticInfo.Symbol);
+ Assert.Collection(semanticInfo.CandidateSymbols,
+ static c => Assert.Equal("C..ctor()", c.ToTestDisplayString()));
+ }
+
+ [Fact]
+ public void ErrorRecovery_ImplicitObjectCreation_NullableValueType()
+ {
+ var source = """
+ struct S
+ {
+ void M()
+ {
+ S? s = default;
+ s ??= /**/new(a)/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,29): error CS0103: The name 'a' does not exist in the current context
+ // s ??= /**/new(a)/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 29));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Equal("S", semanticInfo.Type.ToTestDisplayString());
+ Assert.Equal("S", semanticInfo.ConvertedType.ToTestDisplayString());
+
+ Assert.Null(semanticInfo.Symbol);
+ Assert.Collection(semanticInfo.CandidateSymbols,
+ static c => Assert.Equal("S..ctor()", c.ToTestDisplayString()));
+ }
+
+ [Fact]
+ public void ErrorRecovery_ImplicitObjectCreation_NotNullableValueType()
+ {
+ var source = """
+ struct S
+ {
+ void M()
+ {
+ S s = default;
+ s ??= /**/new(a)/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,29): error CS0103: The name 'a' does not exist in the current context
+ // s ??= /**/new(a)/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 29));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.True(semanticInfo.Type.IsErrorType());
+ Assert.True(semanticInfo.ConvertedType.IsErrorType());
+
+ Assert.Null(semanticInfo.Symbol);
+ Assert.Empty(semanticInfo.CandidateSymbols);
+ }
+
+ [Fact]
+ public void ErrorRecovery_ImplicitObjectCreation_UnconstrainedGenericType()
+ {
+ var source = """
+ class C
+ {
+ void M() where T : new()
+ {
+ T t = default;
+ t ??= /**/new(a)/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,29): error CS0103: The name 'a' does not exist in the current context
+ // t ??= /**/new(a)/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 29));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Equal("T", semanticInfo.Type.ToTestDisplayString());
+ Assert.Equal("T", semanticInfo.ConvertedType.ToTestDisplayString());
+
+ Assert.Null(semanticInfo.Symbol);
+ Assert.Collection(semanticInfo.CandidateSymbols,
+ static c => Assert.Equal("T", c.ToTestDisplayString()));
+ }
+
+ [Fact]
+ public void ErrorRecovery_ImplicitObjectCreation_ReferenceGenericType()
+ {
+ var source = """
+ class C
+ {
+ void M() where T : class, new()
+ {
+ T t = default;
+ t ??= /**/new(a)/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,29): error CS0103: The name 'a' does not exist in the current context
+ // t ??= /**/new(a)/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 29));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Equal("T", semanticInfo.Type.ToTestDisplayString());
+ Assert.Equal("T", semanticInfo.ConvertedType.ToTestDisplayString());
+
+ Assert.Null(semanticInfo.Symbol);
+ Assert.Collection(semanticInfo.CandidateSymbols,
+ static c => Assert.Equal("T", c.ToTestDisplayString()));
+ }
+
+ [Fact]
+ public void ErrorRecovery_ImplicitObjectCreation_ValueGenericType_Nullable()
+ {
+ var source = """
+ class C
+ {
+ void M() where T : struct
+ {
+ T? t = default;
+ t ??= /**/new(a)/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,29): error CS0103: The name 'a' does not exist in the current context
+ // t ??= /**/new(a)/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 29));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Equal("T", semanticInfo.Type.ToTestDisplayString());
+ Assert.Equal("T", semanticInfo.ConvertedType.ToTestDisplayString());
+
+ Assert.Null(semanticInfo.Symbol);
+ Assert.Collection(semanticInfo.CandidateSymbols,
+ static c => Assert.Equal("T", c.ToTestDisplayString()));
+ }
+
+ [Fact]
+ public void ErrorRecovery_ImplicitObjectCreation_ValueGenericType_NotNullable()
+ {
+ var source = """
+ class C
+ {
+ void M() where T : struct
+ {
+ T t = default;
+ t ??= /**/new(a)/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,29): error CS0103: The name 'a' does not exist in the current context
+ // t ??= /**/new(a)/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 29));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.True(semanticInfo.Type.IsErrorType());
+ Assert.True(semanticInfo.ConvertedType.IsErrorType());
+
+ Assert.Null(semanticInfo.Symbol);
+ Assert.Empty(semanticInfo.CandidateSymbols);
+ }
+
+ [Fact]
+ public void ErrorRecovery_CollectionExpression_ReferenceType()
+ {
+ var source = """
+ class C
+ {
+ void M()
+ {
+ int[] arr = default;
+ arr ??= /**/[a]/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,28): error CS0103: The name 'a' does not exist in the current context
+ // arr ??= /**/[a]/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 28));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Null(semanticInfo.Type);
+ Assert.Equal("System.Int32[]", semanticInfo.ConvertedType.ToTestDisplayString());
+ }
+
+ [Fact]
+ public void ErrorRecovery_CollectionExpression_NullableValueType()
+ {
+ var source = """
+ using System.Collections.Immutable;
+
+ class C
+ {
+ void M()
+ {
+ ImmutableArray? arr = default;
+ arr ??= /**/[a]/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source, targetFramework: TargetFramework.Net100);
+ comp.VerifyDiagnostics(
+ // (8,28): error CS0103: The name 'a' does not exist in the current context
+ // arr ??= /**/[a]/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(8, 28));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Null(semanticInfo.Type);
+ Assert.Equal("System.Collections.Immutable.ImmutableArray", semanticInfo.ConvertedType.ToTestDisplayString());
+ }
+
+ [Fact]
+ public void ErrorRecovery_CollectionExpression_NotNullableValueType()
+ {
+ var source = """
+ using System.Collections.Immutable;
+
+ class C
+ {
+ void M()
+ {
+ ImmutableArray arr = default;
+ arr ??= /**/[a]/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source, targetFramework: TargetFramework.Net100);
+ comp.VerifyDiagnostics(
+ // (8,28): error CS0103: The name 'a' does not exist in the current context
+ // arr ??= /**/[a]/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(8, 28));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Null(semanticInfo.Type);
+ Assert.Null(semanticInfo.ConvertedType);
+ }
+
+ [Fact]
+ public void ErrorRecovery_TargetTypedTuple()
+ {
+ var source = """
+ class C
+ {
+ void M()
+ {
+ (C, int)? t = default;
+ t ??= /**/(new(a), 1)/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,30): error CS0103: The name 'a' does not exist in the current context
+ // t ??= /**/(new(a), 1)/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 30));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Null(semanticInfo.Type);
+ Assert.Equal("(C, System.Int32)", semanticInfo.ConvertedType.ToTestDisplayString());
+ }
+
+ [Fact]
+ public void ErrorRecovery_TargetTypedConditionalExpression_ReferenceType()
+ {
+ var source = """
+ class C
+ {
+ void M(bool b)
+ {
+ C c = default;
+ c ??= /**/b ? new(a) : default/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,33): error CS0103: The name 'a' does not exist in the current context
+ // c ??= /**/b ? new(a) : default/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 33));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.True(semanticInfo.Type.IsErrorType());
+ Assert.Equal("C", semanticInfo.ConvertedType.ToTestDisplayString());
+ }
+
+ [Fact]
+ public void ErrorRecovery_TargetTypedConditionalExpression_NullableValueType()
+ {
+ var source = """
+ struct S
+ {
+ void M(bool b)
+ {
+ S? s = default;
+ s ??= /**/b ? new(a) : default/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,33): error CS0103: The name 'a' does not exist in the current context
+ // s ??= /**/b ? new(a) : default/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 33));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.True(semanticInfo.Type.IsErrorType());
+ Assert.Equal("S", semanticInfo.ConvertedType.ToTestDisplayString());
+ }
+
+ [Fact]
+ public void ErrorRecovery_TargetTypedConditionalExpression_NotNullableValueType()
+ {
+ var source = """
+ struct S
+ {
+ void M(bool b)
+ {
+ S s = default;
+ s ??= /**/b ? new(a) : default/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,33): error CS0103: The name 'a' does not exist in the current context
+ // s ??= /**/b ? new(a) : default/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 33));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.True(semanticInfo.Type.IsErrorType());
+ Assert.True(semanticInfo.ConvertedType.IsErrorType());
+ }
+
+ [Fact]
+ public void ErrorRecovery_TargetTypedSwitchExpression_ReferenceType()
+ {
+ var source = """
+ class C
+ {
+ void M(int i)
+ {
+ C c = default;
+ c ??= /**/i switch
+ {
+ 1 => new(a),
+ _ => default,
+ }/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (8,22): error CS0103: The name 'a' does not exist in the current context
+ // 1 => new(a),
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(8, 22));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.True(semanticInfo.Type.IsErrorType());
+ Assert.Equal("C", semanticInfo.ConvertedType.ToTestDisplayString());
+ }
+
+ [Fact]
+ public void ErrorRecovery_TargetTypedSwitchExpression_NullableValueType()
+ {
+ var source = """
+ struct S
+ {
+ void M(int i)
+ {
+ S? s = default;
+ s ??= /**/i switch
+ {
+ 1 => new(a),
+ _ => default,
+ }/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (8,22): error CS0103: The name 'a' does not exist in the current context
+ // 1 => new(a),
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(8, 22));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.True(semanticInfo.Type.IsErrorType());
+ Assert.Equal("S", semanticInfo.ConvertedType.ToTestDisplayString());
+ }
+
+ [Fact]
+ public void ErrorRecovery_TargetTypedSwitchExpression_NotNullableValueType()
+ {
+ var source = """
+ struct S
+ {
+ void M(int i)
+ {
+ S s = default;
+ s ??= /**/i switch
+ {
+ 1 => new(a),
+ _ => default,
+ }/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (8,22): error CS0103: The name 'a' does not exist in the current context
+ // 1 => new(a),
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(8, 22));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.True(semanticInfo.Type.IsErrorType());
+ Assert.True(semanticInfo.ConvertedType.IsErrorType());
+ }
+
+ [Fact]
+ public void ErrorRecovery_TargetTypedInterpolatedString_ReferenceType()
+ {
+ var source = """
+ class C
+ {
+ void M(int i)
+ {
+ CustomInterpolatedStringHandler h = default;
+ h ??= /**/$"The value is {a}"/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation([source, GetInterpolatedStringCustomHandlerType("CustomInterpolatedStringHandler", "class", useBoolReturns: false)]);
+ comp.VerifyDiagnostics(
+ // (6,41): error CS0103: The name 'a' does not exist in the current context
+ // h ??= /**/$"The value is {a}"/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 41));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Equal("System.String", semanticInfo.Type.ToTestDisplayString());
+ Assert.Equal("CustomInterpolatedStringHandler", semanticInfo.ConvertedType.ToTestDisplayString());
+ }
+
+ [Fact]
+ public void ErrorRecovery_TargetTypedInterpolatedString_NullableValueType()
+ {
+ var source = """
+ class C
+ {
+ void M(int i)
+ {
+ CustomInterpolatedStringHandler? h = default;
+ h ??= /**/$"The value is {a}"/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation([source, GetInterpolatedStringCustomHandlerType("CustomInterpolatedStringHandler", "struct", useBoolReturns: false)]);
+ comp.VerifyDiagnostics(
+ // (6,41): error CS0103: The name 'a' does not exist in the current context
+ // h ??= /**/$"The value is {a}"/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 41));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Equal("System.String", semanticInfo.Type.ToTestDisplayString());
+ Assert.Equal("CustomInterpolatedStringHandler", semanticInfo.ConvertedType.ToTestDisplayString());
+ }
+
+ [Fact]
+ public void ErrorRecovery_TargetTypedInterpolatedString_NotNullableValueType()
+ {
+ var source = """
+ class C
+ {
+ void M(int i)
+ {
+ CustomInterpolatedStringHandler h = default;
+ h ??= /**/$"The value is {a}"/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation([source, GetInterpolatedStringCustomHandlerType("CustomInterpolatedStringHandler", "struct", useBoolReturns: false)]);
+ comp.VerifyDiagnostics(
+ // (6,41): error CS0103: The name 'a' does not exist in the current context
+ // h ??= /**/$"The value is {a}"/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 41));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Equal("System.String", semanticInfo.Type.ToTestDisplayString());
+ Assert.Equal("System.String", semanticInfo.ConvertedType.ToTestDisplayString());
+ }
+
+ [Fact]
+ public void ErrorRecovery_ReferenceType_ImplicitConversion()
+ {
+ var source = """
+ class C
+ {
+ void M()
+ {
+ object o = default;
+ o ??= /**/new C(a)/**/;
+ }
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,29): error CS1729: 'C' does not contain a constructor that takes 1 arguments
+ // o ??= /**/new C(a)/**/;
+ Diagnostic(ErrorCode.ERR_BadCtorArgCount, "C").WithArguments("C", "1").WithLocation(6, 29),
+ // (6,31): error CS0103: The name 'a' does not exist in the current context
+ // o ??= /**/new C(a)/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 31));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Equal("C", semanticInfo.Type.ToTestDisplayString());
+ Assert.Equal("System.Object", semanticInfo.ConvertedType.ToTestDisplayString());
+
+ Assert.Equal(ConversionKind.ImplicitReference, semanticInfo.ImplicitConversion.Kind);
+ }
+
+ [Fact]
+ public void ErrorRecovery_NullableValueType_ImplicitConversion()
+ {
+ var source = """
+ struct S
+ {
+ void M()
+ {
+ S? s = default;
+ s ??= /**/new ConvertibleToS(a)/**/;
+ }
+ }
+
+ class ConvertibleToS
+ {
+ public static implicit operator S(ConvertibleToS c) => default;
+ }
+ """;
+
+ var comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,29): error CS1729: 'ConvertibleToS' does not contain a constructor that takes 1 arguments
+ // s ??= /**/new ConvertibleToS(a)/**/;
+ Diagnostic(ErrorCode.ERR_BadCtorArgCount, "ConvertibleToS").WithArguments("ConvertibleToS", "1").WithLocation(6, 29),
+ // (6,44): error CS0103: The name 'a' does not exist in the current context
+ // s ??= /**/new ConvertibleToS(a)/**/;
+ Diagnostic(ErrorCode.ERR_NameNotInContext, "a").WithArguments("a").WithLocation(6, 44));
+
+ var semanticInfo = GetSemanticInfoForTest(comp);
+
+ Assert.Equal("ConvertibleToS", semanticInfo.Type.ToTestDisplayString());
+ Assert.Equal("S", semanticInfo.ConvertedType.ToTestDisplayString());
+
+ Assert.Equal(ConversionKind.ImplicitUserDefined, semanticInfo.ImplicitConversion.Kind);
+ Assert.Equal("S ConvertibleToS.op_Implicit(ConvertibleToS c)", semanticInfo.ImplicitConversion.Method.ToTestDisplayString());
+ }
}
}
diff --git a/src/Compilers/Test/Utilities/CSharp/SemanticModelTestBase.cs b/src/Compilers/Test/Utilities/CSharp/SemanticModelTestBase.cs
index 7faf243c35585..2fc14d5567eab 100644
--- a/src/Compilers/Test/Utilities/CSharp/SemanticModelTestBase.cs
+++ b/src/Compilers/Test/Utilities/CSharp/SemanticModelTestBase.cs
@@ -162,5 +162,10 @@ protected CompilationUtils.SemanticInfoSummary GetSemanticInfoForTest(string tes
{
return GetSemanticInfoForTest(testSrc);
}
+
+ protected CompilationUtils.SemanticInfoSummary GetSemanticInfoForTest(CSharpCompilation compilation)
+ {
+ return GetSemanticInfoForTest(compilation);
+ }
}
}