using System; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Semantics; using Microsoft.CodeAnalysis.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { // Test list drawn from Microsoft.CodeAnalysis.CSharp.ConversionKind public partial class IOperationTests : SemanticModelTestBase { #region Implicit Conversions [Fact] public void ConversionExpression_Implicit_IdentityConversionDynamic() { string source = @" class Program { static void Main(string[] args) { object o1 = new object(); dynamic /**/d1 = o1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'dynamic /*< ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'dynamic /*< ... **/;') Variables: Local_1: dynamic d1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: dynamic) (Syntax: 'o1') ILocalReferenceExpression: o1 (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'o1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } /// /// This test documents the fact that there is no IConversionExpression between two objects of the same type. /// [Fact] public void ConversionExpression_Implicit_IdentityConversion() { string source = @" class Program { static void Main(string[] args) { object o1 = new object(); object /**/o2 = o1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'object /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'object /**/;') Variables: Local_1: System.Object o2 Initializer: ILocalReferenceExpression: o1 (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'o1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Implicit_NumericConversion_Valid() { string source = @" class Program { static void Main(string[] args) { float f1 = 1.0f; double /**/d1 = f1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'double /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'double /**/;') Variables: Local_1: System.Double d1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Double) (Syntax: 'f1') ILocalReferenceExpression: f1 (OperationKind.LocalReferenceExpression, Type: System.Single) (Syntax: 'f1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_NumericConversion_InvalidIllegalTypes() { string source = @" class Program { static void Main(string[] args) { float f1 = 1.0f; int /**/i1 = f1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'int /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'int /**/;') Variables: Local_1: System.Int32 i1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int32, IsInvalid) (Syntax: 'f1') ILocalReferenceExpression: f1 (OperationKind.LocalReferenceExpression, Type: System.Single) (Syntax: 'f1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'float' to 'int'. An explicit conversion exists (are you missing a cast?) // int /**/i1 = f1/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "f1").WithArguments("float", "int").WithLocation(7, 28) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/20175")] public void ConversionExpression_Implicit_NumericConversion_InvalidNoInitializer() { string source = @" using System; class Program { static void Main(string[] args) { int /**/i1 =/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'int /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'int /**/;') Variables: Local_1: System.Int32 i1 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Int32, IsInvalid) (Syntax: '') IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1525: Invalid expression term ';' // int /**/i1 =/**/; Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(8, 38) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_EnumConversion_ZeroToEnum() { string source = @" class Program { static void Main(string[] args) { Enum1 /**/e1 = 0/**/; } } enum Enum1 { Option1, Option2 } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'Enum1 /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'Enum1 /**/;') Variables: Local_1: Enum1 e1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: Enum1, Constant: 0) (Syntax: '0') ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 'e1' is assigned but its value is never used // Enum1 /**/e1 = 0/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "e1").WithArguments("e1").WithLocation(5, 25) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_EnumConversion_IntToEnum_Invalid() { string source = @" class Program { static void Main(string[] args) { int i1 = 1; Enum1 /**/e1 = i1/**/; } } enum Enum1 { Option1, Option2 } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Enum1 /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Enum1 /**/;') Variables: Local_1: Enum1 e1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: Enum1, IsInvalid) (Syntax: 'i1') ILocalReferenceExpression: i1 (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'int' to 'Program.Enum1'. An explicit conversion exists (are you missing a cast?) // Enum1 /**/e1 = i1/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "i1").WithArguments("int", "Enum1").WithLocation(7, 30) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_EnumConversion_OneToEnum_Invalid() { string source = @" class Program { static void Main(string[] args) { Enum1 /**/e1 = 1/**/; } } enum Enum1 { Option1, Option2 } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Enum1 /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Enum1 /**/;') Variables: Local_1: Enum1 e1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: Enum1, IsInvalid) (Syntax: '1') ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'int' to 'Program.Enum1'. An explicit conversion exists (are you missing a cast?) // Enum1 /**/e1 = 1/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "1").WithArguments("int", "Enum1").WithLocation(5, 30) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/20175")] public void ConversionExpression_Implicit_EnumConversion_NoInitalizer_Invalid() { string source = @" class Program { static void Main(string[] args) { Enum1 /**/e1 =/**/; } } enum Enum1 { Option1, Option2 } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Enum1 /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Enum1 /**/;') Variables: Local_1: Enum1 e1 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: Enum1, IsInvalid) (Syntax: '') IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1525: Invalid expression term ';' // Enum1 /**/e1 =/**/; Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(6, 40) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ThrowExpressionConversion() { string source = @" using System; class Program { static void Main(string[] args) { object /**/o = new object() ?? throw new Exception()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'object /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'object /**/;') Variables: Local_1: System.Object o Initializer: INullCoalescingExpression (OperationKind.NullCoalescingExpression, Type: System.Object) (Syntax: 'new object( ... Exception()') Left: IObjectCreationExpression (Constructor: System.Object..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Object) (Syntax: 'new object()') Right: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Object) (Syntax: 'throw new Exception()') IThrowExpression (OperationKind.ThrowExpression, Type: null) (Syntax: 'throw new Exception()') IObjectCreationExpression (Constructor: System.Exception..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'new Exception()') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier() { SyntaxSelector = (syntax) => { var initializer = (BinaryExpressionSyntax)((VariableDeclaratorSyntax)syntax).Initializer.Value; return initializer.Right; }, OperationSelector = (operation) => { var initializer = ((IVariableDeclarationStatement)operation).Declarations.Single().Initializer; return (IConversionExpression)((INullCoalescingExpression)initializer).SecondaryOperand; } }.Verify); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/20175")] public void ConversionExpression_Implicit_ThrowExpressionConversion_InvalidSyntax() { string source = @" using System; class Program { static void Main(string[] args) { object /**/o = throw new Exception()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'object /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'object /**/;') Variables: Local_1: System.Object o Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Object, IsInvalid) (Syntax: 'throw new Exception()') IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: 'throw new Exception()') Children(1): IOperation: (OperationKind.None, IsInvalid) (Syntax: 'throw new Exception()') Children(1): IObjectCreationExpression (Constructor: System.Exception..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Exception) (Syntax: 'new Exception()') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS8115: A throw expression is not allowed in this context. // object /**/o = throw new Exception()/**/; Diagnostic(ErrorCode.ERR_ThrowMisplaced, "throw").WithLocation(8, 30) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_NullToClassConversion() { string source = @" class Program { static void Main(string[] args) { string /**/s1 = null/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'string /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'string /**/;') Variables: Local_1: System.String s1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.String, Constant: null) (Syntax: 'null') ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 's1' is assigned but its value is never used // string /**/s1 = null/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "s1").WithArguments("s1").WithLocation(6, 26) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_NullToNullableValueConversion() { string source = @" interface I1 { } struct S1 { void M1() { S1? /**/s1 = null/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'S1? /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'S1? /**/;') Variables: Local_1: S1? s1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: S1?, Constant: null) (Syntax: 'null') ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 's1' is assigned but its value is never used // S1? /**/s1 = null/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "s1").WithArguments("s1").WithLocation(10, 23) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_NullToNonNullableConversion_Invalid() { string source = @" class Program { static void Main(string[] args) { int /**/i1 = null/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'int /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'int /**/;') Variables: Local_1: System.Int32 i1 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Int32, IsInvalid) (Syntax: 'null') ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0037: Cannot convert null to 'int' because it is a non-nullable value type // int /**/i1 = null/**/; Diagnostic(ErrorCode.ERR_ValueCantBeNull, "null").WithArguments("int").WithLocation(6, 28) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_DefaultToValueConversion() { string source = @" using System; class S1 { void M1() { long /**/i1 = default/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'long /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'long /**/;') Variables: Local_1: System.Int64 i1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int64, Constant: 0) (Syntax: 'default') IDefaultValueExpression (OperationKind.DefaultValueExpression, Type: System.Int64, Constant: 0) (Syntax: 'default') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 'i1' is assigned but its value is never used // long /**/i1 = default(int)/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "i1").WithArguments("i1").WithLocation(8, 24) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, parseOptions: TestOptions.Regular7_1, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_DefaultOfImplicitlyConvertableTypeToValueConversion() { string source = @" using System; class S1 { void M1() { long /**/i1 = default(int)/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'long /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'long /**/;') Variables: Local_1: System.Int64 i1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int64, Constant: 0) (Syntax: 'default(int)') IDefaultValueExpression (OperationKind.DefaultValueExpression, Type: System.Int32, Constant: 0) (Syntax: 'default(int)') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 'i1' is assigned but its value is never used // long /**/i1 = default(int)/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "i1").WithArguments("i1").WithLocation(8, 24) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } /// /// This test documents the fact that `default(T)` is already T, and does not introduce a conversion /// [Fact] public void ConversionExpression_Implicit_DefaultToClassNoConversion() { string source = @" using System; class S1 { void M1() { string /**/i1 = default(string)/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'string /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'string /**/;') Variables: Local_1: System.String i1 Initializer: IDefaultValueExpression (OperationKind.DefaultValueExpression, Type: System.String, Constant: null) (Syntax: 'default(string)') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 'i1' is assigned but its value is never used // string /**/i1 = default(string)/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "i1").WithArguments("i1").WithLocation(8, 26) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Implicit_NullableFromConstantConversion() { string source = @" class Program { static void Main(string[] args) { int? /**/i1 = 1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'int? /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'int? /**/;') Variables: Local_1: System.Int32? i1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int32?) (Syntax: '1') ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 'i1' is assigned but its value is never used // int? /**/i1 = 1/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "i1").WithArguments("i1").WithLocation(6, 24) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_NullableToNullableConversion() { string source = @" class Program { static void Main(string[] args) { int? i1 = 1; long? /**/l1 = i1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'long? /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'long? /**/;') Variables: Local_1: System.Int64? l1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int64?) (Syntax: 'i1') ILocalReferenceExpression: i1 (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'i1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_NullableFromNonNullableConversion() { string source = @" class Program { static void Main(string[] args) { int i1 = 1; int? /**/i2 = i1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'int? /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'int? /**/;') Variables: Local_1: System.Int32? i2 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int32?) (Syntax: 'i1') ILocalReferenceExpression: i1 (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_NullableToNonNullableConversion_Invalid() { string source = @" class Program { static void Main(string[] args) { int? i1 = 1; int /**/i2 = i1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'int /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'int /**/;') Variables: Local_1: System.Int32 i2 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int32, IsInvalid) (Syntax: 'i1') ILocalReferenceExpression: i1 (OperationKind.LocalReferenceExpression, Type: System.Int32?) (Syntax: 'i1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'int?' to 'int'. An explicit conversion exists (are you missing a cast?) // int /**/i2 = i1/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "i1").WithArguments("int?", "int").WithLocation(7, 28) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_InterpolatedStringToIFormattableExpression() { // This needs to be updated once https://github.com/dotnet/roslyn/issues/20046 is addressed. string source = @" using System; class Program { static void Main(string[] args) { IFormattable /**/f1 = $""{1}""/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'IFormattabl ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'IFormattabl ... **/;') Variables: Local_1: System.IFormattable f1 Initializer: IConversionExpression (ConversionKind.InterpolatedString, Implicit) (OperationKind.ConversionExpression, Type: System.IFormattable) (Syntax: '$""{1}""') IInterpolatedStringExpression (OperationKind.InterpolatedStringExpression, Type: System.String) (Syntax: '$""{1}""') Parts(1): IInterpolation (OperationKind.Interpolation) (Syntax: '{1}') Expression: ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceToObjectConversion() { string source = @" using System; class C1 { static void Main(string[] args) { object /**/o1 = new C1()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'object /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'object /**/;') Variables: Local_1: System.Object o1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Object) (Syntax: 'new C1()') IObjectCreationExpression (Constructor: C1..ctor()) (OperationKind.ObjectCreationExpression, Type: C1) (Syntax: 'new C1()') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceToDynamicConversion() { string source = @" using System; class C1 { static void Main(string[] args) { dynamic /**/d1 = new C1()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'dynamic /*< ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'dynamic /*< ... **/;') Variables: Local_1: dynamic d1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: dynamic) (Syntax: 'new C1()') IObjectCreationExpression (Constructor: C1..ctor()) (OperationKind.ObjectCreationExpression, Type: C1) (Syntax: 'new C1()') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceClassToClassConversion() { string source = @" using System; class C1 { static void Main(string[] args) { C1 /**/c1 = new C2()/**/; } } class C2 : C1 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C1 /* ... **/;') Variables: Local_1: C1 c1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: C1) (Syntax: 'new C2()') IObjectCreationExpression (Constructor: C2..ctor()) (OperationKind.ObjectCreationExpression, Type: C2) (Syntax: 'new C2()') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceClassToClassConversion_Invalid() { string source = @" using System; class C1 { static void Main(string[] args) { C1 /**/c1 = new C2()/**/; } } class C2 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'C1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'C1 /* ... **/;') Variables: Local_1: C1 c1 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: C1, IsInvalid) (Syntax: 'new C2()') IObjectCreationExpression (Constructor: C2..ctor()) (OperationKind.ObjectCreationExpression, Type: C2) (Syntax: 'new C2()') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'C2' to 'C1' // C1 /**/c1 = new C2()/**/; Diagnostic(ErrorCode.ERR_NoImplicitConv, "new C2()").WithArguments("C2", "C1").WithLocation(8, 27) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceConversion_InvalidSyntax() { string source = @" using System; class C1 { static void Main(string[] args) { C1 /**/c1 = new/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'C1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'C1 /* ... **/;') Variables: Local_1: C1 c1 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: C1, IsInvalid) (Syntax: 'new/**/') IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: 'new/**/') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1031: Type expected // C1 /**/c1 = new/**/; Diagnostic(ErrorCode.ERR_TypeExpected, ";").WithLocation(8, 41), // CS1526: A new expression requires (), [], or {} after type // C1 /**/c1 = new/**/; Diagnostic(ErrorCode.ERR_BadNewExpr, ";").WithLocation(8, 41) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceClassToInterfaceConversion() { string source = @" using System; interface I1 { } class C1 : I1 { static void Main(string[] args) { I1 /**/i1 = new C1()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'I1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'I1 /* ... **/;') Variables: Local_1: I1 i1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1) (Syntax: 'new C1()') IObjectCreationExpression (Constructor: C1..ctor()) (OperationKind.ObjectCreationExpression, Type: C1) (Syntax: 'new C1()') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceClassToInterfaceConversion_Invalid() { string source = @" using System; interface I1 { } class C1 { static void Main(string[] args) { I1 /**/i1 = new C1()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'I1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'I1 /* ... **/;') Variables: Local_1: I1 i1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1, IsInvalid) (Syntax: 'new C1()') IObjectCreationExpression (Constructor: C1..ctor()) (OperationKind.ObjectCreationExpression, Type: C1) (Syntax: 'new C1()') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'C1' to 'I1'. An explicit conversion exists (are you missing a cast?) // I1 /**/i1 = new C1()/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "new C1()").WithArguments("C1", "I1").WithLocation(12, 27) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceInterfaceToClassConversion_Invalid() { string source = @" using System; interface I1 { } class C1 { static void Main(string[] args) { C1 /**/i1 = new I1()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'C1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'C1 /* ... **/;') Variables: Local_1: C1 i1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: C1, IsInvalid) (Syntax: 'new I1()') IInvalidExpression (OperationKind.InvalidExpression, Type: I1, IsInvalid) (Syntax: 'new I1()') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0144: Cannot create an instance of the abstract class or interface 'I1' // C1 /**/i1 = new I1()/**/; Diagnostic(ErrorCode.ERR_NoNewAbstract, "new I1()").WithArguments("I1").WithLocation(12, 27) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceInterfaceToInterfaceConversion() { string source = @" using System; interface I1 { } interface I2 : I1 { } class C1 : I2 { static void Main(string[] args) { I2 i2 = new C1(); I1 /**/i1 = i2/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'I1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'I1 /* ... **/;') Variables: Local_1: I1 i1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1) (Syntax: 'i2') ILocalReferenceExpression: i2 (OperationKind.LocalReferenceExpression, Type: I2) (Syntax: 'i2') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceInterfaceToInterfaceConversion_Invalid() { string source = @" using System; interface I1 { } interface I2 { } class C1 : I2 { static void Main(string[] args) { I2 i2 = new C1(); I1 /**/i1 = i2/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'I1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'I1 /* ... **/;') Variables: Local_1: I1 i1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1, IsInvalid) (Syntax: 'i2') ILocalReferenceExpression: i2 (OperationKind.LocalReferenceExpression, Type: I2) (Syntax: 'i2') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'I2' to 'I1'. An explicit conversion exists (are you missing a cast?) // I1 /**/i1 = i2/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "i2").WithArguments("I2", "I1").WithLocation(17, 27) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceArrayToArrayConversion() { string source = @" using System; class C1 { static void Main(string[] args) { C2[] c2arr = new C2[10]; C1[] /**/c1arr = c2arr/**/; } } class C2 : C1 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C1[] /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C1[] /**/;') Variables: Local_1: C1[] c1arr Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: C1[]) (Syntax: 'c2arr') ILocalReferenceExpression: c2arr (OperationKind.LocalReferenceExpression, Type: C2[]) (Syntax: 'c2arr') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceArrayToArrayConversion_InvalidDimenionMismatch() { string source = @" using System; class C1 { static void Main(string[] args) { C2[] c2arr = new C2[10]; C1[][] /**/c1arr = c2arr/**/; } } class C2 : C1 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'C1[][] /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'C1[][] /**/;') Variables: Local_1: C1[][] c1arr Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: C1[][], IsInvalid) (Syntax: 'c2arr') ILocalReferenceExpression: c2arr (OperationKind.LocalReferenceExpression, Type: C2[]) (Syntax: 'c2arr') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'C2[]' to 'C1[][]' // C1[][] /**/c1arr = c2arr/**/; Diagnostic(ErrorCode.ERR_NoImplicitConv, "c2arr").WithArguments("C2[]", "C1[][]").WithLocation(9, 34) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceArrayToArrayConversion_InvalidNoReferenceConversion() { string source = @" using System; class C1 { static void Main(string[] args) { C2[] c2arr = new C2[10]; C1[] /**/c1arr = c2arr/**/; } } class C2 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'C1[] /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'C1[] /**/;') Variables: Local_1: C1[] c1arr Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: C1[], IsInvalid) (Syntax: 'c2arr') ILocalReferenceExpression: c2arr (OperationKind.LocalReferenceExpression, Type: C2[]) (Syntax: 'c2arr') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'C2[]' to 'C1[]' // C1[] /**/c1arr = c2arr/**/; Diagnostic(ErrorCode.ERR_NoImplicitConv, "c2arr").WithArguments("C2[]", "C1[]").WithLocation(9, 32) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceArrayToArrayConversion_InvalidValueTypeToReferenceType() { string source = @" using System; class C1 { static void Main(string[] args) { I1[] /**/i1arr = new S1[10]/**/; } } interface I1 { } struct S1 : I1 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'I1[] /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'I1[] /**/;') Variables: Local_1: I1[] i1arr Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: I1[], IsInvalid) (Syntax: 'new S1[10]') IArrayCreationExpression (Element Type: S1) (OperationKind.ArrayCreationExpression, Type: S1[]) (Syntax: 'new S1[10]') Dimension Sizes(1): ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'S1[]' to 'I1[]' // I1[] /**/i1arr = new S1[10]/**/; Diagnostic(ErrorCode.ERR_NoImplicitConv, "new S1[10]").WithArguments("S1[]", "I1[]").WithLocation(8, 32) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceArrayToSystemArrayConversion() { string source = @" using System; class C1 { static void Main(string[] args) { Array /**/a1 = new object[10]/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'Array /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'Array /**/;') Variables: Local_1: System.Array a1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Array) (Syntax: 'new object[10]') IArrayCreationExpression (Element Type: System.Object) (OperationKind.ArrayCreationExpression, Type: System.Object[]) (Syntax: 'new object[10]') Dimension Sizes(1): ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceArrayToSystemArrayConversion_MultiDimensionalArray() { string source = @" using System; class C1 { static void Main(string[] args) { Array /**/a1 = new int[10][]/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'Array /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'Array /**/;') Variables: Local_1: System.Array a1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Array) (Syntax: 'new int[10][]') IArrayCreationExpression (Element Type: System.Int32[]) (OperationKind.ArrayCreationExpression, Type: System.Int32[][]) (Syntax: 'new int[10][]') Dimension Sizes(1): ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceArrayToSystemArrayConversion_InvalidNotArrayType() { string source = @" using System; class C1 { static void Main(string[] args) { Array /**/a1 = new object()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Array /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Array /**/;') Variables: Local_1: System.Array a1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Array, IsInvalid) (Syntax: 'new object()') IObjectCreationExpression (Constructor: System.Object..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Object) (Syntax: 'new object()') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'object' to 'System.Array'. An explicit conversion exists (are you missing a cast?) // Array /**/a1 = new object()/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "new object()").WithArguments("object", "System.Array").WithLocation(8, 30) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceArrayToIListTConversion() { string source = @" using System.Collections.Generic; class C1 { static void Main(string[] args) { IList /**/a1 = new int[10]/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'IList ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'IList ... **/;') Variables: Local_1: System.Collections.Generic.IList a1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Collections.Generic.IList) (Syntax: 'new int[10]') IArrayCreationExpression (Element Type: System.Int32) (OperationKind.ArrayCreationExpression, Type: System.Int32[]) (Syntax: 'new int[10]') Dimension Sizes(1): ILiteralExpression (Text: 10) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 10) (Syntax: '10') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceArrayToIListTConversion_InvalidNonArrayType() { string source = @" using System.Collections.Generic; class C1 { static void Main(string[] args) { IList /**/a1 = new object()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'IList ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'IList ... **/;') Variables: Local_1: System.Collections.Generic.IList a1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Collections.Generic.IList, IsInvalid) (Syntax: 'new object()') IObjectCreationExpression (Constructor: System.Object..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Object) (Syntax: 'new object()') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'object' to 'System.Collections.Generic.IList'. An explicit conversion exists (are you missing a cast?) // IList /**/a1 = new object()/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "new object()").WithArguments("object", "System.Collections.Generic.IList").WithLocation(8, 35) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceDelegateTypeToSystemDelegateConversion() { string source = @" using System; class C1 { delegate void DType(); void M1() { DType d1 = M2; Delegate /**/d2 = d1/**/; } void M2() { } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'Delegate /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'Delegate /* ... **/;') Variables: Local_1: System.Delegate d2 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Delegate) (Syntax: 'd1') ILocalReferenceExpression: d1 (OperationKind.LocalReferenceExpression, Type: C1.DType) (Syntax: 'd1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceDelegateTypeToSystemDelegateConversion_InvalidNonDelegateType() { string source = @" using System; class C1 { delegate void DType(); void M1() { DType d1 = M2; Delegate /**/d2 = d1()/**/; } void M2() { } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Delegate /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Delegate /* ... **/;') Variables: Local_1: System.Delegate d2 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Delegate, IsInvalid) (Syntax: 'd1()') IInvocationExpression (virtual void C1.DType.Invoke()) (OperationKind.InvocationExpression, Type: System.Void) (Syntax: 'd1()') Instance Receiver: ILocalReferenceExpression: d1 (OperationKind.LocalReferenceExpression, Type: C1.DType) (Syntax: 'd1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'void' to 'System.Delegate' // Delegate /**/d2 = d1()/**/; Diagnostic(ErrorCode.ERR_NoImplicitConv, "d1()").WithArguments("void", "System.Delegate").WithLocation(10, 33) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/20175")] public void ConversionExpression_Implicit_ReferenceDelegateTypeToSystemDelegateConversion_InvalidSyntax() { string source = @" using System; class C1 { delegate void DType(); void M1() { Delegate /**/d2 =/**/; } void M2() { } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Delegate /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Delegate /* ... **/;') Variables: Local_1: System.Delegate d2 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Delegate, IsInvalid) (Syntax: '') IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1525: Invalid expression term ';' // Delegate /**/d2 =/**/; Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(9, 43) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } /// /// This method is documenting the fact that there is no conversion expression here. /// [Fact] public void ConversionExpression_Implicit_ReferenceMethodToDelegateConversion_NoConversion() { string source = @" class Program { delegate void DType(); void Main() { DType /**/d1 = M1/**/; } void M1() { } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'DType /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'DType /**/;') Variables: Local_1: Program.DType d1 Initializer: IMethodBindingExpression: void Program.M1() (OperationKind.MethodBindingExpression, Type: Program.DType) (Syntax: 'M1') Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: Program) (Syntax: 'M1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Implicit_ReferenceMethodToDelegateConversion_InvalidIdentifier() { string source = @" class Program { delegate void DType(); void Main() { DType /**/d1 = M1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'DType /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'DType /**/;') Variables: Local_1: Program.DType d1 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: Program.DType, IsInvalid) (Syntax: 'M1') IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: 'M1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0103: The name 'M1' does not exist in the current context // DType /**/d1 = M1/**/; Diagnostic(ErrorCode.ERR_NameNotInContext, "M1").WithArguments("M1").WithLocation(7, 30) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceLambdaToDelegateConversion() { // TODO: There should be an IDelegateCreationExpression (or something like it) here, wrapping the IConversionExpression. // See https://github.com/dotnet/roslyn/issues/20095. string source = @" class Program { delegate void DType(); void Main() { DType /**/d1 = () => { }/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'DType /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'DType /**/;') Variables: Local_1: Program.DType d1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: Program.DType) (Syntax: '() => { }') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '() => { }') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ }') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '{ }') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceLambdaToDelegateConversion_InvalidMismatchedTypes() { string source = @" class Program { delegate void DType(); void Main() { DType /**/d1 = (string s) => { }/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'DType /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'DType /**/;') Variables: Local_1: Program.DType d1 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: Program.DType, IsInvalid) (Syntax: '(string s) => { }') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '(string s) => { }') IBlockStatement (0 statements) (OperationKind.BlockStatement) (Syntax: '{ }') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1593: Delegate 'Program.DType' does not take 1 arguments // DType /**/d1 = (string s) => { }/**/; Diagnostic(ErrorCode.ERR_BadDelArgCount, "(string s) => { }").WithArguments("Program.DType", "1").WithLocation(7, 30) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); Func f = (int num) => num; } [Fact] public void ConversionExpression_Implicit_ReferenceLambdaToDelegateConversion_InvalidSyntax() { string source = @" class Program { delegate void DType(); void Main() { DType /**/d1 = () =>/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'DType /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'DType /**/;') Variables: Local_1: Program.DType d1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: Program.DType, IsInvalid) (Syntax: '() =>/**/') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: '() =>/**/') IBlockStatement (2 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '') IExpressionStatement (OperationKind.ExpressionStatement, IsInvalid) (Syntax: '') IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1525: Invalid expression term ';' // DType /**/d1 = () =>/**/; Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(7, 46) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } /// /// This is documenting the fact that there are currently not conversion expressions in this tree. Once /// https://github.com/dotnet/roslyn/issues/18839 is addressed, there should be. /// [Fact] public void ConversionExpression_Implicit_ReferenceLambdaToDelegateConstructor_NoConversion() { string source = @" using System; class Program { static void Main(string[] args) { Action a = /**/new Action(() => { })/**/; } } "; string expectedOperationTree = @" IOperation: (OperationKind.None) (Syntax: 'new Action(() => { })') Children(1): ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '() => { }') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ }') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '{ }') "; var expectedDiagnostics = DiagnosticDescription.None; var a = new Action(() => { }); VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Implicit_ReferenceTransitiveConversion() { string source = @" class C1 { void M1() { C1 /**/c1 = new C3()/**/; } } class C2 : C1 { } class C3 : C2 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C1 /* ... **/;') Variables: Local_1: C1 c1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: C1) (Syntax: 'new C3()') IObjectCreationExpression (Constructor: C3..ctor()) (OperationKind.ObjectCreationExpression, Type: C3) (Syntax: 'new C3()') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceCovarianceTransitiveConversion() { string source = @" interface I1 { } class C1 : I1 { void M1() { C2 c2 = new C2(); I1 /**/c1 = c2/**/; } } class C2 : C1 { } class C3 { } class C4 : C3 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'I1 /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'I1 /**/;') Variables: Local_1: I1 c1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1) (Syntax: 'c2') ILocalReferenceExpression: c2 (OperationKind.LocalReferenceExpression, Type: C2) (Syntax: 'c2') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceCovarianceTransitiveConversion_Invalid() { string source = @" interface I1 { } class C1 : I1 { void M1() { C2 c2 = new C2(); I1 /**/c1 = c2/**/; } } class C2 : C1 { } class C3 { } class C4 : C3 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'I1 /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'I1 /**/;') Variables: Local_1: I1 c1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1, IsInvalid) (Syntax: 'c2') ILocalReferenceExpression: c2 (OperationKind.LocalReferenceExpression, Type: C2) (Syntax: 'c2') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'C2' to 'I1'. An explicit conversion exists (are you missing a cast?) // I1 /**/c1 = c2/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "c2").WithArguments("C2", "I1").WithLocation(11, 31) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceContravarianceTransitiveConversion() { string source = @" interface I1 { } class C1 : I1 { void M1() { C2 c2 = new C2(); I1 /**/c1 = c2/**/; } } class C2 : C1 { } class C3 { } class C4 : C3 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'I1 /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'I1 /**/;') Variables: Local_1: I1 c1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1) (Syntax: 'c2') ILocalReferenceExpression: c2 (OperationKind.LocalReferenceExpression, Type: C2) (Syntax: 'c2') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceContravarianceTransitiveConversion_Invalid() { string source = @" interface I1 { } class C1 : I1 { void M1() { C2 c2 = new C2(); I1 /**/c1 = c2/**/; } } class C2 : C1 { } class C3 { } class C4 : C3 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'I1 /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'I1 /**/;') Variables: Local_1: I1 c1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1, IsInvalid) (Syntax: 'c2') ILocalReferenceExpression: c2 (OperationKind.LocalReferenceExpression, Type: C2) (Syntax: 'c2') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'C2' to 'I1'. An explicit conversion exists (are you missing a cast?) // I1 /**/c1 = c2/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "c2").WithArguments("C2", "I1").WithLocation(11, 31) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceInvariantTransitiveConversion() { string source = @" using System.Collections.Generic; class C1 { static void M1() { IList /**/list = new List()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'IList*/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'IList*/;') Variables: Local_1: System.Collections.Generic.IList list Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Collections.Generic.IList) (Syntax: 'new List()') IObjectCreationExpression (Constructor: System.Collections.Generic.List..ctor()) (OperationKind.ObjectCreationExpression, Type: System.Collections.Generic.List) (Syntax: 'new List()') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceTypeParameterClassConversion() { string source = @" class C1 { static void M1() where T : C2, new() { C1 /**/c1 = new T()/**/; } } class C2 : C1 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C1 /* ... **/;') Variables: Local_1: C1 c1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: C1) (Syntax: 'new T()') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T) (Syntax: 'new T()') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceTypeParameterClassConversion_InvalidConversion() { string source = @" class C1 { static void M1() where T : class, new() { C1 /**/c1 = new T()/**/; } } class C2 : C1 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'C1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'C1 /* ... **/;') Variables: Local_1: C1 c1 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: C1, IsInvalid) (Syntax: 'new T()') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T) (Syntax: 'new T()') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'T' to 'C1' // C1 /**/c1 = new T()/**/; Diagnostic(ErrorCode.ERR_NoImplicitConv, "new T()").WithArguments("T", "C1").WithLocation(7, 27) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceTypeParameterInterfaceConversion() { string source = @" interface I1 { } class C1 : I1 { static void M1() where T : C1, new() { I1 /**/i1 = new T()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'I1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'I1 /* ... **/;') Variables: Local_1: I1 i1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1) (Syntax: 'new T()') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T) (Syntax: 'new T()') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceTypeParameterToInterfaceConversion_InvalidConversion() { string source = @" interface I1 { } class C1 { static void M1() where T : C1, new() { I1 /**/i1 = new T()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'I1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'I1 /* ... **/;') Variables: Local_1: I1 i1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1, IsInvalid) (Syntax: 'new T()') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T) (Syntax: 'new T()') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'T' to 'I1'. An explicit conversion exists (are you missing a cast?) // I1 /**/i1 = new T()/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "new T()").WithArguments("T", "I1").WithLocation(11, 27) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceTypeParameterToConstraintParameterConversion() { string source = @" interface I1 { } class C1 { static void M1() where T : U, new() where U : class { U /**/u = new T()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'U /** ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'U /** ... **/;') Variables: Local_1: U u Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: U) (Syntax: 'new T()') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T) (Syntax: 'new T()') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceTypeParameterToConstraintParameter_InvalidConversion() { string source = @" interface I1 { } class C1 { static void M1() where T : class, new() where U : class { U /**/u = new T()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'U /** ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'U /** ... **/;') Variables: Local_1: U u Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: U, IsInvalid) (Syntax: 'new T()') ITypeParameterObjectCreationExpression (OperationKind.TypeParameterObjectCreationExpression, Type: T) (Syntax: 'new T()') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'T' to 'U' // U /**/u = new T()/**/; Diagnostic(ErrorCode.ERR_NoImplicitConv, "new T()").WithArguments("T", "U").WithLocation(12, 25) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceTypeParameterFromNull() { string source = @" interface I1 { } class C1 { static void M1() where T : class, new() { T /**/t = null/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'T /** ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'T /** ... **/;') Variables: Local_1: T t Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: T, Constant: null) (Syntax: 'null') ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 't' is assigned but its value is never used // T /**/t = null/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "t").WithArguments("t").WithLocation(11, 21) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReferenceTypeParameterFromNull_InvalidNoReferenceConstraint() { string source = @" interface I1 { } class C1 { static void M1() where T : new() { T /**/t = null/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'T /** ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'T /** ... **/;') Variables: Local_1: T t Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: T, IsInvalid) (Syntax: 'null') ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0403: Cannot convert null to type parameter 'T' because it could be a non-nullable value type. Consider using 'default(T)' instead. // T /**/t = null/**/; Diagnostic(ErrorCode.ERR_TypeVarCantBeNull, "null").WithArguments("T").WithLocation(11, 25) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_BoxingNonNullableValueToObjectConversion() { string source = @" class C1 { static void M1() { int i = 1; object /**/o = i/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'object /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'object /**/;') Variables: Local_1: System.Object o Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Object) (Syntax: 'i') ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_BoxingNonNullableValueToDynamicConversion() { string source = @" class C1 { static void M1() { int i = 1; dynamic /**/d = i/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'dynamic /*< ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'dynamic /*< ... **/;') Variables: Local_1: dynamic d Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: dynamic) (Syntax: 'i') ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_BoxingValueToSystemValueTypeConversion() { string source = @" using System; struct S1 { void M1() { ValueType /**/v1 = new S1()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'ValueType / ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'ValueType / ... **/;') Variables: Local_1: System.ValueType v1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.ValueType) (Syntax: 'new S1()') IObjectCreationExpression (Constructor: S1..ctor()) (OperationKind.ObjectCreationExpression, Type: S1) (Syntax: 'new S1()') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_BoxingNonNullableValueToSystemValueTypeConversion_InvalidNonValueType() { string source = @" using System; class C1 { void M1() { ValueType /**/v1 = new C1()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'ValueType / ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'ValueType / ... **/;') Variables: Local_1: System.ValueType v1 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.ValueType, IsInvalid) (Syntax: 'new C1()') IObjectCreationExpression (Constructor: C1..ctor()) (OperationKind.ObjectCreationExpression, Type: C1) (Syntax: 'new C1()') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'C1' to 'System.ValueType' // ValueType /**/v1 = new C1()/**/; Diagnostic(ErrorCode.ERR_NoImplicitConv, "new C1()").WithArguments("C1", "System.ValueType").WithLocation(8, 34) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_BoxingNonNullableValueToImplementingInterfaceConversion() { string source = @" interface I1 { } struct S1 : I1 { void M1() { I1 /**/i1 = new S1()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'I1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'I1 /* ... **/;') Variables: Local_1: I1 i1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1) (Syntax: 'new S1()') IObjectCreationExpression (Constructor: S1..ctor()) (OperationKind.ObjectCreationExpression, Type: S1) (Syntax: 'new S1()') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_BoxingNonNullableValueToImplementingInterfaceConversion_InvalidNotImplementing() { string source = @" interface I1 { } struct S1 { void M1() { I1 /**/i1 = new S1()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'I1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'I1 /* ... **/;') Variables: Local_1: I1 i1 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: I1, IsInvalid) (Syntax: 'new S1()') IObjectCreationExpression (Constructor: S1..ctor()) (OperationKind.ObjectCreationExpression, Type: S1) (Syntax: 'new S1()') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'S1' to 'I1' // I1 /**/i1 = new S1()/**/; Diagnostic(ErrorCode.ERR_NoImplicitConv, "new S1()").WithArguments("S1", "I1").WithLocation(10, 27) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_BoxingNullableValueToImplementingInterfaceConversion() { string source = @" interface I1 { } struct S1 : I1 { void M1() { S1? s1 = null; I1 /**/i1 = s1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'I1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'I1 /* ... **/;') Variables: Local_1: I1 i1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1) (Syntax: 's1') ILocalReferenceExpression: s1 (OperationKind.LocalReferenceExpression, Type: S1?) (Syntax: 's1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_BoxingNullableValueToImplementingInterfaceConversion_InvalidNotImplementing() { string source = @" interface I1 { } struct S1 { void M1() { S1? s1 = null; I1 /**/i1 = s1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'I1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'I1 /* ... **/;') Variables: Local_1: I1 i1 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: I1, IsInvalid) (Syntax: 's1') ILocalReferenceExpression: s1 (OperationKind.LocalReferenceExpression, Type: S1?) (Syntax: 's1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'S1?' to 'I1' // I1 /**/i1 = s1/**/; Diagnostic(ErrorCode.ERR_NoImplicitConv, "s1").WithArguments("S1?", "I1").WithLocation(11, 27) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_BoxingEnumToSystemEnumConversion() { string source = @" using System; enum E1 { E } struct S1 { void M1() { Enum /**/e = E1.E/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'Enum /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'Enum /**/;') Variables: Local_1: System.Enum e Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: System.Enum) (Syntax: 'E1.E') IFieldReferenceExpression: E1.E (Static) (OperationKind.FieldReferenceExpression, Type: E1, Constant: 0) (Syntax: 'E1.E') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_BoxingEnumToSystemEnumConversion_InvalidNotEnum() { string source = @" using System; enum E1 { E } struct S1 { void M1() { Enum /**/e = 1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Enum /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Enum /**/;') Variables: Local_1: System.Enum e Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Enum, IsInvalid) (Syntax: '1') ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'int' to 'System.Enum' // Enum /**/e = 1/**/; Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "System.Enum").WithLocation(13, 28) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_DynamicConversionToClass() { string source = @" class S1 { void M1() { dynamic d1 = 1; string /**/s1 = d1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'string /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'string /**/;') Variables: Local_1: System.String s1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.String) (Syntax: 'd1') ILocalReferenceExpression: d1 (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_DynamicConversionToValueType() { string source = @" class S1 { void M1() { dynamic d1 = null; int /**/i1 = d1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'int /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'int /**/;') Variables: Local_1: System.Int32 i1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int32) (Syntax: 'd1') ILocalReferenceExpression: d1 (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ConstantExpressionConversion() { string source = @" class S1 { void M1() { const int i1 = 1; const sbyte /**/s1 = i1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'const sbyte ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'const sbyte ... **/;') Variables: Local_1: System.SByte s1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.SByte, Constant: 1) (Syntax: 'i1') ILocalReferenceExpression: i1 (OperationKind.LocalReferenceExpression, Type: System.Int32, Constant: 1) (Syntax: 'i1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 's1' is assigned but its value is never used // const sbyte /**/s1 = i1/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "s1").WithArguments("s1").WithLocation(7, 31) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ConstantExpressionConversion_InvalidValueTooLarge() { string source = @" class S1 { void M1() { const int i1 = 0x1000; const sbyte /**/s1 = i1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'const sbyte ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'const sbyte ... **/;') Variables: Local_1: System.SByte s1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.SByte, IsInvalid) (Syntax: 'i1') ILocalReferenceExpression: i1 (OperationKind.LocalReferenceExpression, Type: System.Int32, Constant: 4096) (Syntax: 'i1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0031: Constant value '4096' cannot be converted to a 'sbyte' // const sbyte /**/s1 = i1/**/; Diagnostic(ErrorCode.ERR_ConstOutOfRange, "i1").WithArguments("4096", "sbyte").WithLocation(7, 36) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ConstantExpressionConversion_InvalidNonConstantExpression() { string source = @" class S1 { void M1() { int i1 = 0; const sbyte /**/s1 = i1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'const sbyte ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'const sbyte ... **/;') Variables: Local_1: System.SByte s1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.SByte, IsInvalid) (Syntax: 'i1') ILocalReferenceExpression: i1 (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'int' to 'sbyte'. An explicit conversion exists (are you missing a cast?) // const sbyte /**/s1 = i1/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "i1").WithArguments("int", "sbyte").WithLocation(7, 36) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_UserDefinedConversion() { string source = @" class C1 { void M1() { C2 /**/c2 = this/**/; } } class C2 { public static implicit operator C2(C1 c1) { return null; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C2 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C2 /* ... **/;') Variables: Local_1: C2 c2 Initializer: IConversionExpression (ConversionKind.OperatorMethod, Implicit) (OperatorMethod: C2 C2.op_Implicit(C1 c1)) (OperationKind.ConversionExpression, Type: C2) (Syntax: 'this') IInstanceReferenceExpression (InstanceReferenceKind.Explicit) (OperationKind.InstanceReferenceExpression, Type: C1) (Syntax: 'this') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_UserDefinedMultiImplicitStepConversion() { string source = @" class C1 { void M1() { int i1 = 1; C2 /**/c2 = i1/**/; } } class C2 { public static implicit operator C2(long c1) { return null; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C2 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C2 /* ... **/;') Variables: Local_1: C2 c2 Initializer: IConversionExpression (ConversionKind.OperatorMethod, Implicit) (OperatorMethod: C2 C2.op_Implicit(System.Int64 c1)) (OperationKind.ConversionExpression, Type: C2) (Syntax: 'i1') IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int64) (Syntax: 'i1') ILocalReferenceExpression: i1 (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier() { ConversionChildSelector = ExpectedSymbolVerifier.NestedConversionChildSelector }.Verify); } [Fact] public void ConversionExpression_Implicit_UserDefinedMultiImplicitAndExplicitStepConversion() { string source = @" class C1 { void M1() { int i1 = 1; C2 /**/c2 = (int)this/**/; } public static implicit operator int(C1 c1) { return 1; } } class C2 { public static implicit operator C2(long c1) { return null; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C2 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C2 /* ... **/;') Variables: Local_1: C2 c2 Initializer: IConversionExpression (ConversionKind.OperatorMethod, Implicit) (OperatorMethod: C2 C2.op_Implicit(System.Int64 c1)) (OperationKind.ConversionExpression, Type: C2) (Syntax: '(int)this') IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int64) (Syntax: '(int)this') IConversionExpression (ConversionKind.OperatorMethod, Explicit) (OperatorMethod: System.Int32 C1.op_Implicit(C1 c1)) (OperationKind.ConversionExpression, Type: System.Int32) (Syntax: '(int)this') IInstanceReferenceExpression (InstanceReferenceKind.Explicit) (OperationKind.InstanceReferenceExpression, Type: C1) (Syntax: 'this') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 'i1' is assigned but its value is never used // int i1 = 1; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "i1").WithArguments("i1").WithLocation(6, 13) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Implicit_UserDefinedMultiImplicitAndExplicitStepConversion_InvalidMissingExplicitConversion() { string source = @" class C1 { void M1() { int i1 = 1; C2 /**/c2 = this/**/; } public static implicit operator int(C1 c1) { return 1; } } class C2 { public static implicit operator C2(long c1) { return null; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'C2 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'C2 /* ... **/;') Variables: Local_1: C2 c2 Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: C2, IsInvalid) (Syntax: 'this') IInstanceReferenceExpression (InstanceReferenceKind.Explicit) (OperationKind.InstanceReferenceExpression, Type: C1) (Syntax: 'this') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'C1' to 'C2' // C2 /**/c2 = this/**/; Diagnostic(ErrorCode.ERR_NoImplicitConv, "this").WithArguments("C1", "C2").WithLocation(7, 27), // CS0219: The variable 'i1' is assigned but its value is never used // int i1 = 1; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "i1").WithArguments("i1").WithLocation(6, 13) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Implicit_UserDefinedMultipleCandidateConversion() { string source = @" class C1 { } class C2 : C1 { void M1() { C3 /**/c3 = this/**/; } } class C3 { public static implicit operator C3(C1 c1) { return null; } public static implicit operator C3(C2 c2) { return null; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C3 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C3 /* ... **/;') Variables: Local_1: C3 c3 Initializer: IConversionExpression (ConversionKind.OperatorMethod, Implicit) (OperatorMethod: C3 C3.op_Implicit(C2 c2)) (OperationKind.ConversionExpression, Type: C3) (Syntax: 'this') IInstanceReferenceExpression (InstanceReferenceKind.Explicit) (OperationKind.InstanceReferenceExpression, Type: C2) (Syntax: 'this') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_DelegateExpressionWithoutParamsToDelegateConversion() { string source = @" using System; class S1 { void M1() { Action /**/a = delegate { }/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'Action /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'Action /**/;') Variables: Local_1: System.Action a Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Action) (Syntax: 'delegate { }') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'delegate { }') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ }') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '{ }') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_DelegateExpressionWithParamsToDelegateConversion() { string source = @" using System; class S1 { void M1() { Action /**/a = delegate(int i) { }/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'Action ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'Action ... **/;') Variables: Local_1: System.Action a Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Action) (Syntax: 'delegate(int i) { }') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'delegate(int i) { }') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ }') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '{ }') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_DelegateExpressionWithParamsToDelegateConversion_InvalidMismatchedTypes() { string source = @" using System; class S1 { void M1() { Action /**/a = delegate() { }/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Action ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Action ... **/;') Variables: Local_1: System.Action a Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: 'delegate() { }') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'delegate() { }') IBlockStatement (0 statements) (OperationKind.BlockStatement) (Syntax: '{ }') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1593: Delegate 'Action' does not take 0 arguments // Action /**/a = delegate() { }/**/; Diagnostic(ErrorCode.ERR_BadDelArgCount, "delegate() { }").WithArguments("System.Action", "0").WithLocation(8, 35) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_PointerFromNullConversion() { string source = @" using System; class S1 { unsafe void M1() { void* /**/v1 = null/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'void* /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'void* /**/;') Variables: Local_1: System.Void* v1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Void*) (Syntax: 'null') ILiteralExpression (Text: null) (OperationKind.LiteralExpression, Type: null, Constant: null) (Syntax: 'null') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, compilationOptions: TestOptions.UnsafeReleaseDll, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_PointerToVoidConversion() { string source = @" using System; class S1 { unsafe void M1() { int* i1 = null; void* /**/v1 = i1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'void* /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'void* /**/;') Variables: Local_1: System.Void* v1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Void*) (Syntax: 'i1') ILocalReferenceExpression: i1 (OperationKind.LocalReferenceExpression, Type: System.Int32*) (Syntax: 'i1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, compilationOptions: TestOptions.UnsafeReleaseDll, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_PointerFromVoidConversion_Invalid() { string source = @" using System; class S1 { unsafe void M1() { void* v1 = null; int* /**/i1 = v1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'int* /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'int* /**/;') Variables: Local_1: System.Int32* i1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int32*, IsInvalid) (Syntax: 'v1') ILocalReferenceExpression: v1 (OperationKind.LocalReferenceExpression, Type: System.Void*) (Syntax: 'v1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'void*' to 'int*'. An explicit conversion exists (are you missing a cast?) // int* /**/i1 = v1/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "v1").WithArguments("void*", "int*").WithLocation(9, 29) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, compilationOptions: TestOptions.UnsafeReleaseDll, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_PointerFromIntegerConversion_Invalid() { string source = @" using System; class S1 { unsafe void M1() { void* /**/v1 = 0/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'void* /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'void* /**/;') Variables: Local_1: System.Void* v1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Void*, IsInvalid) (Syntax: '0') ILiteralExpression (Text: 0) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 0) (Syntax: '0') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'int' to 'void*'. An explicit conversion exists (are you missing a cast?) // void* /**/v1 = 0/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "0").WithArguments("int", "void*").WithLocation(8, 30), }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, compilationOptions: TestOptions.UnsafeReleaseDll, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ExpressionTreeConversion() { string source = @" using System; using System.Linq.Expressions; class Program { static void Main(string[] args) { Expression> /**/exp = num => num < 5/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'Expression< ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'Expression< ... **/;') Variables: Local_1: System.Linq.Expressions.Expression> exp Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Linq.Expressions.Expression>) (Syntax: 'num => num < 5') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: 'num => num < 5') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: 'num < 5') IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'num < 5') IBinaryOperatorExpression (BinaryOperationKind.IntegerLessThan) (OperationKind.BinaryOperatorExpression, Type: System.Boolean) (Syntax: 'num < 5') Left: IParameterReferenceExpression: num (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'num') Right: ILiteralExpression (Text: 5) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 5) (Syntax: '5') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact(Skip = "https://github.com/dotnet/roslyn/issues/20291")] public void ConversionExpression_Implicit_ExpressionTreeConversion_InvalidIncorrectLambdaType() { string source = @" using System; using System.Linq.Expressions; class Program { static void Main(string[] args) { Expression> /**/exp = num => num/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Expression< ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Expression< ... **/;') Variables: Local_1: System.Linq.Expressions.Expression> exp Initializer: IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Linq.Expressions.Expression>, IsInvalid) (Syntax: 'num => num') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'num => num') IBlockStatement (1 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: 'num') IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: 'num') IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Boolean, IsInvalid) (Syntax: 'num') IParameterReferenceExpression: num (OperationKind.ParameterReferenceExpression, Type: System.Int32) (Syntax: 'num') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0029: Cannot implicitly convert type 'int' to 'bool' // Expression> /**/exp = num => num/**/; Diagnostic(ErrorCode.ERR_NoImplicitConv, "num").WithArguments("int", "bool").WithLocation(9, 60), // CS1662: Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type // Expression> /**/exp = num => num/**/; Diagnostic(ErrorCode.ERR_CantConvAnonMethReturns, "num").WithArguments("lambda expression").WithLocation(9, 60) }; // Due to https://github.com/dotnet/roslyn/issues/20291, we cannot verify that the types of the ioperation tree and the sematic model // match, as they do not actually match. VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ExpressionTreeConversion_InvalidSyntax() { string source = @" using System; using System.Linq.Expressions; class Program { static void Main(string[] args) { Expression> /**/exp = num =>/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Expression< ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Expression< ... **/;') Variables: Local_1: System.Linq.Expressions.Expression> exp Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Linq.Expressions.Expression>, IsInvalid) (Syntax: 'num =>/**/') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: 'num =>/**/') IBlockStatement (1 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '') IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: '') IConversionExpression (ConversionKind.Invalid, Implicit) (OperationKind.ConversionExpression, Type: System.Boolean, IsInvalid) (Syntax: '') IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1525: Invalid expression term ';' // Expression> /**/exp = num =>/**/; Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(9, 70) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReturnStatementConversion() { string source = @" class C1 { public long M1() { int i = 1; /**/return i;/**/ } } "; string expectedOperationTree = @" IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'return i;') IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int64) (Syntax: 'i') ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: System.Int32) (Syntax: 'i') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Implicit_ReturnStatementConversion_InvalidConversion() { string source = @" class C1 { public int M1() { float f = 1; /**/return f;/**/ } } "; string expectedOperationTree = @" IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'return f;') IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int32) (Syntax: 'f') ILocalReferenceExpression: f (OperationKind.LocalReferenceExpression, Type: System.Single) (Syntax: 'f') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'float' to 'int'. An explicit conversion exists (are you missing a cast?) // /**/return f;/**/ Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "f").WithArguments("float", "int").WithLocation(7, 26) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } #endregion #region Explicit Conversion [Fact] public void ConversionExpression_Explicit_ExplicitIdentityConversionCreatesIConversionExpression() { string source = @" class C1 { public void M1() { int /**/i = (int)1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'int /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'int /**/;') Variables: Local_1: System.Int32 i Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: System.Int32, Constant: 1) (Syntax: '(int)1') ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 'i' is assigned but its value is never used // int /**/i = (int)1/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "i").WithArguments("i").WithLocation(6, 23) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Explicit_ImplicitAndExplicitConversion() { string source = @" class C1 { public void M1() { long /**/i = (int)1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'long /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'long /**/;') Variables: Local_1: System.Int64 i Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int64, Constant: 1) (Syntax: '(int)1') IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: System.Int32, Constant: 1) (Syntax: '(int)1') ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 'i' is assigned but its value is never used // long /**/i = (int)1/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "i").WithArguments("i").WithLocation(6, 24) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, AdditionalOperationTreeVerifier: new ExpectedSymbolVerifier().Verify); } [Fact] public void ConversionExpression_Explicit_SimpleNumericCast() { string source = @" class C1 { public void M1() { int i = /**/(int)1.0/**/; } } "; string expectedOperationTree = @" IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: System.Int32, Constant: 1) (Syntax: '(int)1.0') ILiteralExpression (OperationKind.LiteralExpression, Type: System.Double, Constant: 1) (Syntax: '1.0') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 'i' is assigned but its value is never used // int i = /**/(int)1.0/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "i").WithArguments("i").WithLocation(6, 13) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_SimpleNumericConversion_InvalidNoImplicitConversion() { string source = @" class C1 { public void M1() { int /**/i = (float)1.0/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'int /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'int /**/;') Variables: Local_1: System.Int32 i Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int32, IsInvalid) (Syntax: '(float)1.0') IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: System.Single, Constant: 1) (Syntax: '(float)1.0') ILiteralExpression (OperationKind.LiteralExpression, Type: System.Double, Constant: 1) (Syntax: '1.0') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'float' to 'int'. An explicit conversion exists (are you missing a cast?) // int /**/i = (float)1.0/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(float)1.0").WithArguments("float", "int").WithLocation(6, 27) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_SimpleNumericConversion_InvalidSyntax() { string source = @" class C1 { public void M1() { long /**/i = (int)/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'long /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'long /**/;') Variables: Local_1: System.Int64 i Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int64, IsInvalid) (Syntax: '(int)/**/') IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: System.Int32, IsInvalid) (Syntax: '(int)/**/') IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1525: Invalid expression term ';' // long /**/i = (int)/**/; Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(6, 44) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_EnumFromNumericLiteralConversion() { string source = @" class C1 { public void M1() { E1 /**/e1 = (E1)1/**/; } } enum E1 { One, Two } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'E1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'E1 /* ... **/;') Variables: Local_1: E1 e1 Initializer: IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: E1, Constant: 1) (Syntax: '(E1)1') ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 'e1' is assigned but its value is never used // E1 /**/e1 = (E1)1/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "e1").WithArguments("e1").WithLocation(6, 22) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_EnumToNumericTypeConversion() { string source = @" class C1 { public void M1() { int /**/i = (int)E1.One/**/; } } enum E1 { One, Two } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'int /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'int /**/;') Variables: Local_1: System.Int32 i Initializer: IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: System.Int32, Constant: 0) (Syntax: '(int)E1.One') IFieldReferenceExpression: E1.One (Static) (OperationKind.FieldReferenceExpression, Type: E1, Constant: 0) (Syntax: 'E1.One') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 'i' is assigned but its value is never used // int /**/i = (int)E1.One/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "i").WithArguments("i").WithLocation(6, 23) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_EnumToEnumConversion() { string source = @" class C1 { public void M1() { E2 /**/e2 = (E2)E1.One/**/; } } enum E1 { One, Two } enum E2 { Three, Four } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'E2 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'E2 /* ... **/;') Variables: Local_1: E2 e2 Initializer: IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: E2, Constant: 0) (Syntax: '(E2)E1.One') IFieldReferenceExpression: E1.One (Static) (OperationKind.FieldReferenceExpression, Type: E1, Constant: 0) (Syntax: 'E1.One') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0219: The variable 'e2' is assigned but its value is never used // E2 /**/e2 = (E2)E1.One/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "e2").WithArguments("e2").WithLocation(6, 22) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_EnumToEnumConversion_InvalidOutOfRange() { string source = @" class C1 { public void M1() { E2 /**/e2 = (E2)E1.One/**/; } } enum E1 { One = 1000 } enum E2 : byte { Two } "; // Note: The lack of a constant value for the conversion is expected here, it matches the semantic model. // Because the enum value is larger than the destination enum, the conversion is bad string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'E2 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'E2 /* ... **/;') Variables: Local_1: E2 e2 Initializer: IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: E2, Constant: null) (Syntax: '(E2)E1.One') IFieldReferenceExpression: E1.One (Static) (OperationKind.FieldReferenceExpression, Type: E1, Constant: 1000) (Syntax: 'E1.One') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0221: Constant value '1000' cannot be converted to a 'E2' (use 'unchecked' syntax to override) // E2 /**/e2 = (E2)E1.One/**/; Diagnostic(ErrorCode.ERR_ConstOutOfRangeChecked, "(E2)E1.One").WithArguments("1000", "E2").WithLocation(6, 27), // CS0219: The variable 'e2' is assigned but its value is never used // E2 /**/e2 = (E2)E1.One/**/; Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "e2").WithArguments("e2").WithLocation(6, 22) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_NullableToNullableConversion() { string source = @" class Program { static void Main(string[] args) { long? l = null; int? /**/i = (int?)l/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'int? /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'int? /**/;') Variables: Local_1: System.Int32? i Initializer: IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: System.Int32?) (Syntax: '(int?)l') ILocalReferenceExpression: l (OperationKind.LocalReferenceExpression, Type: System.Int64?) (Syntax: 'l') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_NullableToNonNullableConversion() { string source = @" class Program { static void Main(string[] args) { long? l = null; int /**/i = (int)l/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'int /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'int /**/;') Variables: Local_1: System.Int32 i Initializer: IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: System.Int32) (Syntax: '(int)l') ILocalReferenceExpression: l (OperationKind.LocalReferenceExpression, Type: System.Int64?) (Syntax: 'l') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceFromObjectConversion() { string source = @" class C1 { static void M1() { object o = string.Empty; string /**/s = (string)o/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'string /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'string /**/;') Variables: Local_1: System.String s Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: System.String) (Syntax: '(string)o') ILocalReferenceExpression: o (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'o') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceFromDynamicConversion() { string source = @" class C1 { static void M1() { dynamic d = string.Empty; string /**/s = (string)d/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'string /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'string /**/;') Variables: Local_1: System.String s Initializer: IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: System.String) (Syntax: '(string)d') ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceFromSuperclassConversion() { string source = @" class C1 { static void M1() { C1 c1 = new C2(); C2 /**/c2 = (C2)c1/**/; } } class C2 : C1 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C2 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C2 /* ... **/;') Variables: Local_1: C2 c2 Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: C2) (Syntax: '(C2)c1') ILocalReferenceExpression: c1 (OperationKind.LocalReferenceExpression, Type: C1) (Syntax: 'c1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceFromSuperclassConversion_InvalidNoConversion() { string source = @" class C1 { static void M1() { C1 c1 = new C1(); C2 /**/c2 = (C2)c1/**/; } } class C2 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'C2 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'C2 /* ... **/;') Variables: Local_1: C2 c2 Initializer: IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: C2, IsInvalid) (Syntax: '(C2)c1') ILocalReferenceExpression: c1 (OperationKind.LocalReferenceExpression, Type: C1) (Syntax: 'c1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0030: Cannot convert type 'C1' to 'C2' // C2 /**/c2 = (C2)c1/**/; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(C2)c1").WithArguments("C1", "C2").WithLocation(7, 27) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceFromImplementedInterfaceConversion() { string source = @" interface I1 { } class C1 : I1 { static void M1() { I1 i1 = new C1(); C1 /**/c1 = (C1)i1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C1 /* ... **/;') Variables: Local_1: C1 c1 Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: C1) (Syntax: '(C1)i1') ILocalReferenceExpression: i1 (OperationKind.LocalReferenceExpression, Type: I1) (Syntax: 'i1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceFromUnimplementedInterfaceConversion() { string source = @" interface I1 { } class C1 { static void M1() { I1 i1 = null; C1 /**/c1 = (C1)i1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C1 /* ... **/;') Variables: Local_1: C1 c1 Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: C1) (Syntax: '(C1)i1') ILocalReferenceExpression: i1 (OperationKind.LocalReferenceExpression, Type: I1) (Syntax: 'i1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceFromUnimplementedInterfaceConversion_InvalidSealedClass() { string source = @" interface I1 { } sealed class C1 { static void M1() { I1 i1 = null; C1 /**/c1 = (C1)i1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'C1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'C1 /* ... **/;') Variables: Local_1: C1 c1 Initializer: IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: C1, IsInvalid) (Syntax: '(C1)i1') ILocalReferenceExpression: i1 (OperationKind.LocalReferenceExpression, Type: I1) (Syntax: 'i1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0030: Cannot convert type 'I1' to 'C1' // C1 /**/c1 = (C1)i1/**/; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(C1)i1").WithArguments("I1", "C1").WithLocation(9, 27) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceFromInterfaceToInterfaceConversion() { string source = @" interface I1 { } interface I2 { } sealed class C1 { static void M1() { I1 i1 = null; I2 /**/i2 = (I2)i1/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'I2 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'I2 /* ... **/;') Variables: Local_1: I2 i2 Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: I2) (Syntax: '(I2)i1') ILocalReferenceExpression: i1 (OperationKind.LocalReferenceExpression, Type: I1) (Syntax: 'i1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceConversion_InvalidSyntax() { string source = @" interface I2 { } sealed class C1 { static void M1() { I2 /**/i2 = (I2)()/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'I2 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'I2 /* ... **/;') Variables: Local_1: I2 i2 Initializer: IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: I2, IsInvalid) (Syntax: '(I2)()') IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1525: Invalid expression term ')' // I2 /**/i2 = (I2)()/**/; Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(8, 32) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceArrayTypeToArrayTypeConversion() { string source = @" class C1 { static void M1() { C1[] c1arr = new C2[1]; C2[] /**/c2arr = (C2[])c1arr/**/; } } class C2 : C1 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C2[] /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C2[] /**/;') Variables: Local_1: C2[] c2arr Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: C2[]) (Syntax: '(C2[])c1arr') ILocalReferenceExpression: c1arr (OperationKind.LocalReferenceExpression, Type: C1[]) (Syntax: 'c1arr') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceArrayTypeToArrayTypeConversion_InvalidNoElementTypeConversion() { string source = @" class C1 { static void M1() { C1[] c1arr = new C1[1]; C2[] /**/c2arr = (C2[])c1arr/**/; } } class C2 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'C2[] /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'C2[] /**/;') Variables: Local_1: C2[] c2arr Initializer: IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: C2[], IsInvalid) (Syntax: '(C2[])c1arr') ILocalReferenceExpression: c1arr (OperationKind.LocalReferenceExpression, Type: C1[]) (Syntax: 'c1arr') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0030: Cannot convert type 'C1[]' to 'C2[]' // C2[] /**/c2arr = (C2[])c1arr/**/; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(C2[])c1arr").WithArguments("C1[]", "C2[]").WithLocation(7, 32) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceArrayTypeToArrayTypeConversion_InvalidMismatchedSized() { string source = @" class C1 { static void M1() { C1[] c1arr = new C1[1]; C1[][] /**/c2arr = (C1[][])c1arr/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'C1[][] /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'C1[][] /**/;') Variables: Local_1: C1[][] c2arr Initializer: IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: C1[][], IsInvalid) (Syntax: '(C1[][])c1arr') ILocalReferenceExpression: c1arr (OperationKind.LocalReferenceExpression, Type: C1[]) (Syntax: 'c1arr') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0030: Cannot convert type 'C1[]' to 'C1[][]' // C1[][] /**/c2arr = (C1[][])c1arr/**/; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(C1[][])c1arr").WithArguments("C1[]", "C1[][]").WithLocation(7, 34) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceSystemArrayToArrayTypeConversion() { string source = @" using System; class C1 { static void M1() { Array c1arr = new C1[1]; C1[] /**/c2arr = (C1[])c1arr/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C1[] /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C1[] /**/;') Variables: Local_1: C1[] c2arr Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: C1[]) (Syntax: '(C1[])c1arr') ILocalReferenceExpression: c1arr (OperationKind.LocalReferenceExpression, Type: System.Array) (Syntax: 'c1arr') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceArrayToIListConversion() { string source = @" using System; using System.Collections.Generic; class C1 { static void M1() { C1[] c1arr = new C1[1]; IList /**/c1list = (IList)c1arr/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'IList / ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'IList / ... **/;') Variables: Local_1: System.Collections.Generic.IList c1list Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: System.Collections.Generic.IList) (Syntax: '(IList)c1arr') ILocalReferenceExpression: c1arr (OperationKind.LocalReferenceExpression, Type: C1[]) (Syntax: 'c1arr') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceArrayToIListConversion_InvalidMismatchedDimensions() { string source = @" using System; using System.Collections.Generic; class C1 { static void M1() { C1[][] c1arr = new C1[1][]; IList /**/c1list = (IList)c1arr/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'IList / ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'IList / ... **/;') Variables: Local_1: System.Collections.Generic.IList c1list Initializer: IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: System.Collections.Generic.IList, IsInvalid) (Syntax: '(IList)c1arr') ILocalReferenceExpression: c1arr (OperationKind.LocalReferenceExpression, Type: C1[][]) (Syntax: 'c1arr') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0030: Cannot convert type 'C1[][]' to 'System.Collections.Generic.IList' // IList /**/c1list = (IList)c1arr/**/; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(IList)c1arr").WithArguments("C1[][]", "System.Collections.Generic.IList").WithLocation(10, 38) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceIListToArrayTypeConversion() { string source = @" using System; using System.Collections.Generic; class C1 { static void M1() { IList c1List = new List(); C1[] /**/c1arr = (C1[])c1List/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C1[] /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C1[] /**/;') Variables: Local_1: C1[] c1arr Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: C1[]) (Syntax: '(C1[])c1List') ILocalReferenceExpression: c1List (OperationKind.LocalReferenceExpression, Type: System.Collections.Generic.IList) (Syntax: 'c1List') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceIListToArrayTypeConversion_InvalidMismatchedDimensions() { string source = @" using System; using System.Collections.Generic; class C1 { static void M1() { IList c1List = new List(); C1[][] /**/c1arr = (C1[][])c1List/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'C1[][] /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'C1[][] /**/;') Variables: Local_1: C1[][] c1arr Initializer: IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: C1[][], IsInvalid) (Syntax: '(C1[][])c1List') ILocalReferenceExpression: c1List (OperationKind.LocalReferenceExpression, Type: System.Collections.Generic.IList) (Syntax: 'c1List') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0030: Cannot convert type 'System.Collections.Generic.IList' to 'C1[][]' // C1[][] /**/c1arr = (C1[][])c1List/**/; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(C1[][])c1List").WithArguments("System.Collections.Generic.IList", "C1[][]").WithLocation(10, 34) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceDelegateToDelegateTypeConversion() { string source = @" using System; class C1 { static void M1() { Delegate d = (Action)(() => { }); Action /**/a = (Action)d/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'Action /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'Action /**/;') Variables: Local_1: System.Action a Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: System.Action) (Syntax: '(Action)d') ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: System.Delegate) (Syntax: 'd') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReferenceContravarianceConversion() { string source = @" interface I1 { } class C1 : I1 { void M1() { C2 c2 = new C2(); I1 /**/c1 = (I1)c2/**/; } } class C2 : C1 { } class C3 { } class C4 : C3 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'I1 /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'I1 /**/;') Variables: Local_1: I1 c1 Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: I1) (Syntax: '(I1)c2') ILocalReferenceExpression: c2 (OperationKind.LocalReferenceExpression, Type: C2) (Syntax: 'c2') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_UnboxingObjectToValueTypeConversion() { string source = @" class C1 { void M1() { object o = 1; int /**/i = (int)o/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'int /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'int /**/;') Variables: Local_1: System.Int32 i Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: System.Int32) (Syntax: '(int)o') ILocalReferenceExpression: o (OperationKind.LocalReferenceExpression, Type: System.Object) (Syntax: 'o') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_UnboxingDynamicToValueTypeConversion() { string source = @" class C1 { void M1() { dynamic d = 1; int /**/i = (int)d/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'int /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'int /**/;') Variables: Local_1: System.Int32 i Initializer: IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: System.Int32) (Syntax: '(int)d') ILocalReferenceExpression: d (OperationKind.LocalReferenceExpression, Type: dynamic) (Syntax: 'd') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_UnboxingSystemValueTypeToValueTypeConversion() { string source = @" using System; class C1 { void M1() { ValueType v = 1; int /**/i = (int)v/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'int /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'int /**/;') Variables: Local_1: System.Int32 i Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: System.Int32) (Syntax: '(int)v') ILocalReferenceExpression: v (OperationKind.LocalReferenceExpression, Type: System.ValueType) (Syntax: 'v') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_UnboxingSystemEnumToEnumConversion() { string source = @" using System; class C1 { void M1() { Enum e = E1.One; E1 /**/e1 = (E1)e/**/; } } enum E1 { One = 1 } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'E1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'E1 /* ... **/;') Variables: Local_1: E1 e1 Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: E1) (Syntax: '(E1)e') ILocalReferenceExpression: e (OperationKind.LocalReferenceExpression, Type: System.Enum) (Syntax: 'e') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_UnboxingReferenceToNullableTypeConversion() { string source = @" using System; class C1 { void M1() { Enum e = null; E1? /**/e1 = (E1?)e/**/; } } enum E1 { One = 1 } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'E1? /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'E1? /**/;') Variables: Local_1: E1? e1 Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: E1?) (Syntax: '(E1?)e') ILocalReferenceExpression: e (OperationKind.LocalReferenceExpression, Type: System.Enum) (Syntax: 'e') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_UnboxingReferenceToNullableTypeConversion_InvalidNoConversionToNonNullableType() { string source = @" using System; class C1 { void M1() { Enum e = null; int? /**/e1 = (E1?)e/**/; } } enum E1 { One = 1 } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'int? /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'int? /**/;') Variables: Local_1: System.Int32? e1 Initializer: IConversionExpression (ConversionKind.CSharp, Implicit) (OperationKind.ConversionExpression, Type: System.Int32?, IsInvalid) (Syntax: '(E1?)e') IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: E1?) (Syntax: '(E1?)e') ILocalReferenceExpression: e (OperationKind.LocalReferenceExpression, Type: System.Enum) (Syntax: 'e') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0266: Cannot implicitly convert type 'E1?' to 'int?'. An explicit conversion exists (are you missing a cast?) // int? /**/e1 = (E1?)e/**/; Diagnostic(ErrorCode.ERR_NoImplicitConvCast, "(E1?)e").WithArguments("E1?", "int?").WithLocation(9, 29) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_UnboxingValueTypeFromInterfaceConversion() { string source = @" using System; class C1 { void M1() { I1 i = null; S1 /**/s1 = (S1)i/**/; } } interface I1 { } struct S1 : I1 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'S1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'S1 /* ... **/;') Variables: Local_1: S1 s1 Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: S1) (Syntax: '(S1)i') ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: I1) (Syntax: 'i') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_UnboxingValueTypeFromInterfaceConversion_InvalidNoConversion() { string source = @" using System; class C1 { void M1() { I1 i = null; S1 /**/s1 = (S1)i/**/; } } interface I1 { } struct S1 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'S1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'S1 /* ... **/;') Variables: Local_1: S1 s1 Initializer: IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: S1, IsInvalid) (Syntax: '(S1)i') ILocalReferenceExpression: i (OperationKind.LocalReferenceExpression, Type: I1) (Syntax: 'i') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0030: Cannot convert type 'I1' to 'S1' // S1 /**/s1 = (S1)i/**/; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(S1)i").WithArguments("I1", "S1").WithLocation(9, 27) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_UnboxingVarianceConversion() { string source = @" using System; using System.Collections.Generic; class C1 { void M1() { IList i1List = new List(); IList /**/s1List = (IList)i1List/**/; } } interface I1 { } struct S1 : I1 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'IList / ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'IList / ... **/;') Variables: Local_1: System.Collections.Generic.IList s1List Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: System.Collections.Generic.IList) (Syntax: '(IList)i1List') ILocalReferenceExpression: i1List (OperationKind.LocalReferenceExpression, Type: System.Collections.Generic.IList) (Syntax: 'i1List') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_TypeParameterConstraintConversion() { string source = @" using System; class C1 { void M1(U u) where T : U { T /**/t = (T)u/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'T /** ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'T /** ... **/;') Variables: Local_1: T t Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: T) (Syntax: '(T)u') IParameterReferenceExpression: u (OperationKind.ParameterReferenceExpression, Type: U) (Syntax: 'u') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_TypeParameterConversion_InvalidNoConversion() { string source = @" using System; class C1 { void M1(U u) { T /**/t = (T)u/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'T /** ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'T /** ... **/;') Variables: Local_1: T t Initializer: IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: T, IsInvalid) (Syntax: '(T)u') IParameterReferenceExpression: u (OperationKind.ParameterReferenceExpression, Type: U) (Syntax: 'u') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0030: Cannot convert type 'U' to 'T' // T /**/t = (T)u/**/; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(T)u").WithArguments("U", "T").WithLocation(8, 25) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_TypeParameterToInterfaceConversion() { string source = @" interface I1 { } class C1 { void M1(I1 i) { T /**/t = (T)i/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'T /** ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'T /** ... **/;') Variables: Local_1: T t Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: T) (Syntax: '(T)i') IParameterReferenceExpression: i (OperationKind.ParameterReferenceExpression, Type: I1) (Syntax: 'i') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_TypeParameterFromInterfaceConversion() { string source = @" interface I1 { } class C1 { void M1(T t) { I1 /**/i = (I1)t/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'I1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'I1 /* ... **/;') Variables: Local_1: I1 i Initializer: IConversionExpression (ConversionKind.Cast, Explicit) (OperationKind.ConversionExpression, Type: I1) (Syntax: '(I1)t') IParameterReferenceExpression: t (OperationKind.ParameterReferenceExpression, Type: T) (Syntax: 't') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ImplicitUserDefinedConversionAsExplicitConversion() { string source = @" class C1 { void M1() { C1 c1 = new C1(); C2 /**/c2 = (C2)c1/**/; } public static implicit operator C2(C1 c1) => new C2(); } class C2 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C2 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C2 /* ... **/;') Variables: Local_1: C2 c2 Initializer: IConversionExpression (ConversionKind.OperatorMethod, Explicit) (OperatorMethod: C2 C1.op_Implicit(C1 c1)) (OperationKind.ConversionExpression, Type: C2) (Syntax: '(C2)c1') ILocalReferenceExpression: c1 (OperationKind.LocalReferenceExpression, Type: C1) (Syntax: 'c1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ExplicitUserDefinedConversion() { string source = @" class C1 { void M1() { C1 c1 = new C1(); C2 /**/c2 = (C2)c1/**/; } public static explicit operator C2(C1 c1) => new C2(); } class C2 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'C2 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'C2 /* ... **/;') Variables: Local_1: C2 c2 Initializer: IConversionExpression (ConversionKind.OperatorMethod, Explicit) (OperatorMethod: C2 C1.op_Explicit(C1 c1)) (OperationKind.ConversionExpression, Type: C2) (Syntax: '(C2)c1') ILocalReferenceExpression: c1 (OperationKind.LocalReferenceExpression, Type: C1) (Syntax: 'c1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ExplicitUserDefinedConversion_WithImplicitConversionAfter() { string source = @" interface I1 { } class C1 { void M1() { C1 c1 = new C1(); I1 /**/i1 = (C2)c1/**/; } public static explicit operator C2(C1 c1) => new C2(); } class C2 : I1 { } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'I1 /* ... **/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'I1 /* ... **/;') Variables: Local_1: I1 i1 Initializer: IConversionExpression (ConversionKind.Cast, Implicit) (OperationKind.ConversionExpression, Type: I1) (Syntax: '(C2)c1') IConversionExpression (ConversionKind.OperatorMethod, Explicit) (OperatorMethod: C2 C1.op_Explicit(C1 c1)) (OperationKind.ConversionExpression, Type: C2) (Syntax: '(C2)c1') ILocalReferenceExpression: c1 (OperationKind.LocalReferenceExpression, Type: C1) (Syntax: 'c1') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_DelegateFromLambdaExplicitCastConversion() { string source = @" using System; class C1 { void M1() { Action /**/a = (Action)(() => { })/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'Action /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'Action /**/;') Variables: Local_1: System.Action a Initializer: IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: System.Action) (Syntax: '(Action)(() => { })') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '() => { }') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ }') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '{ }') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_DelegateFromLambdaExplicitCastConversion_InvalidIncorrectReturnType() { string source = @" using System; class C1 { void M1() { Action /**/a = (Action)(() => 1)/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Action /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Action /**/;') Variables: Local_1: System.Action a Initializer: IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: '(Action)(() => 1)') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: '() => 1') IBlockStatement (2 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '1') IExpressionStatement (OperationKind.ExpressionStatement, IsInvalid) (Syntax: '1') ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement // Action /**/a = (Action)(() => 1)/**/; Diagnostic(ErrorCode.ERR_IllegalStatement, "1").WithLocation(8, 45) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_DelegateFromLambdaExplicitCastConversion_InvalidParameters() { string source = @" using System; class C1 { void M1() { Action /**/a = (Action)((string s) => { })/**/; } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Action /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Action /**/;') Variables: Local_1: System.Action a Initializer: IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: '(Action)((s ... s) => { })') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '(string s) => { }') IBlockStatement (0 statements) (OperationKind.BlockStatement) (Syntax: '{ }') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1593: Delegate 'Action' does not take 1 arguments // Action /**/a = (Action)((string s) => { })/**/; Diagnostic(ErrorCode.ERR_BadDelArgCount, "(string s) => { }").WithArguments("System.Action", "1").WithLocation(8, 39) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_DelegateCreationFromLambdaExplicitCastConversion() { string source = @" using System; class C1 { void M1() { Action a = /**/new Action((Action)(() => { }))/**/; } } "; string expectedOperationTree = @" IOperation: (OperationKind.None) (Syntax: 'new Action( ... () => { }))') Children(1): IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: System.Action) (Syntax: '(Action)(() => { })') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '() => { }') IBlockStatement (1 statements) (OperationKind.BlockStatement) (Syntax: '{ }') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '{ }') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_DelegateCreationFromLambdaExplicitCastConversion_InvalidReturnType() { string source = @" using System; class C1 { void M1() { Action a = /**/new Action((Action)(() => 1))/**/; } } "; string expectedOperationTree = @" IInvalidExpression (OperationKind.InvalidExpression, Type: System.Action, IsInvalid) (Syntax: 'new Action( ... )(() => 1))') Children(1): IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: '(Action)(() => 1)') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null, IsInvalid) (Syntax: '() => 1') IBlockStatement (2 statements) (OperationKind.BlockStatement, IsInvalid) (Syntax: '1') IExpressionStatement (OperationKind.ExpressionStatement, IsInvalid) (Syntax: '1') ILiteralExpression (Text: 1) (OperationKind.LiteralExpression, Type: System.Int32, Constant: 1) (Syntax: '1') IReturnStatement (OperationKind.ReturnStatement) (Syntax: '1') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0201: Only assignment, call, increment, decrement, and new object expressions can be used as a statement // Action a = /**/new Action((Action)(() => 1))/**/; Diagnostic(ErrorCode.ERR_IllegalStatement, "1").WithLocation(8, 56) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_DelegateCreationFromLambdaExplicitCastConversion_InvalidMismatchedParameters() { string source = @" using System; class C1 { void M1() { Action a = /**/new Action((Action)((string s) => { }))/**/; } } "; string expectedOperationTree = @" IInvalidExpression (OperationKind.InvalidExpression, Type: System.Action, IsInvalid) (Syntax: 'new Action( ... s) => { }))') Children(1): IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: '(Action)((s ... s) => { })') ILambdaExpression (Signature: lambda expression) (OperationKind.LambdaExpression, Type: null) (Syntax: '(string s) => { }') IBlockStatement (0 statements) (OperationKind.BlockStatement) (Syntax: '{ }') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1593: Delegate 'Action' does not take 1 arguments // Action a = /**/new Action((Action)((string s) => { }))/**/; Diagnostic(ErrorCode.ERR_BadDelArgCount, "(string s) => { }").WithArguments("System.Action", "1").WithLocation(8, 50) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_DelegateFromMethodReferenceExplicitCastConversion() { string source = @" using System; class C1 { void M1() { Action /**/a = (Action)M2/**/; } void M2() { } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'Action /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'Action /**/;') Variables: Local_1: System.Action a Initializer: IMethodBindingExpression: void C1.M2() (OperationKind.MethodBindingExpression, Type: System.Action) (Syntax: '(Action)M2') Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C1) (Syntax: 'M2') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_DelegateFromMethodReferenceExplicitCastConversion_InvalidMismatchedParameter() { string source = @" using System; class C1 { void M1() { Action /**/a = (Action)M2/**/; } void M2(int i) { } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Action /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Action /**/;') Variables: Local_1: System.Action a Initializer: IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: '(Action)M2') IOperation: (OperationKind.None) (Syntax: 'M2') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0030: Cannot convert type 'method' to 'Action' // Action /**/a = (Action)M2/**/; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(Action)M2").WithArguments("method", "System.Action").WithLocation(8, 30) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_DelegateFromMethodReferenceExplicitCastConversion_InvalidReturnType() { string source = @" using System; class C1 { void M1() { Action /**/a = (Action)M2/**/; } int M2() { } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement, IsInvalid) (Syntax: 'Action /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration, IsInvalid) (Syntax: 'Action /**/;') Variables: Local_1: System.Action a Initializer: IMethodBindingExpression: System.Int32 C1.M2() (OperationKind.MethodBindingExpression, Type: System.Action, IsInvalid) (Syntax: '(Action)M2') Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C1) (Syntax: 'M2') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0407: 'int C1.M2()' has the wrong return type // Action /**/a = (Action)M2/**/; Diagnostic(ErrorCode.ERR_BadRetType, "(Action)M2").WithArguments("C1.M2()", "int").WithLocation(8, 30), // CS0161: 'C1.M2()': not all code paths return a value // int M2() { } Diagnostic(ErrorCode.ERR_ReturnExpected, "M2").WithArguments("C1.M2()").WithLocation(11, 9) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_DelegateCreationFromMethodReferenceExplicitCastConversion() { string source = @" using System; class C1 { void M1() { Action /**/a = new Action((Action)M2)/**/; } void M2() { } } "; string expectedOperationTree = @" IVariableDeclarationStatement (1 declarations) (OperationKind.VariableDeclarationStatement) (Syntax: 'Action /**/;') IVariableDeclaration (1 variables) (OperationKind.VariableDeclaration) (Syntax: 'Action /**/;') Variables: Local_1: System.Action a Initializer: IOperation: (OperationKind.None) (Syntax: 'new Action((Action)M2)') Children(1): IMethodBindingExpression: void C1.M2() (OperationKind.MethodBindingExpression, Type: System.Action) (Syntax: '(Action)M2') Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C1) (Syntax: 'M2') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_DelegateCreationFromMethodBindingConversion_InvalidMismatchedParameters() { string source = @" using System; class C1 { void M1() { Action a = /**/new Action((Action)M2)/**/; } void M2(int i) { } } "; string expectedOperationTree = @" IInvalidExpression (OperationKind.InvalidExpression, Type: System.Action, IsInvalid) (Syntax: 'new Action((Action)M2)') Children(1): IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: System.Action, IsInvalid) (Syntax: '(Action)M2') IOperation: (OperationKind.None) (Syntax: 'M2') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0030: Cannot convert type 'method' to 'Action' // Action a = /**/new Action((Action)M2)/**/; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(Action)M2").WithArguments("method", "System.Action").WithLocation(8, 41) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_DelegateCreationFromMethodBindingConversion_InvalidReturnType() { string source = @" using System; class C1 { void M1() { Action a = /**/new Action((Action)M2)/**/; } int M2() { } } "; string expectedOperationTree = @" IInvalidExpression (OperationKind.InvalidExpression, Type: System.Action, IsInvalid) (Syntax: 'new Action((Action)M2)') Children(1): IMethodBindingExpression: System.Int32 C1.M2() (OperationKind.MethodBindingExpression, Type: System.Action, IsInvalid) (Syntax: '(Action)M2') Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: C1) (Syntax: 'M2') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0407: 'int C1.M2()' has the wrong return type // Action a = /**/new Action((Action)M2)/**/; Diagnostic(ErrorCode.ERR_BadRetType, "(Action)M2").WithArguments("C1.M2()", "int").WithLocation(8, 41), // CS0161: 'C1.M2()': not all code paths return a value // int M2() { } Diagnostic(ErrorCode.ERR_ReturnExpected, "M2").WithArguments("C1.M2()").WithLocation(11, 9) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReturnConversion() { string source = @" using System; class C1 { int M1() { /**/return (int)1.0;/**/ } } "; string expectedOperationTree = @" IReturnStatement (OperationKind.ReturnStatement) (Syntax: 'return (int)1.0;') IConversionExpression (ConversionKind.CSharp, Explicit) (OperationKind.ConversionExpression, Type: System.Int32, Constant: 1) (Syntax: '(int)1.0') ILiteralExpression (OperationKind.LiteralExpression, Type: System.Double, Constant: 1) (Syntax: '1.0') "; var expectedDiagnostics = DiagnosticDescription.None; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReturnConversion_InvalidConversion() { string source = @" using System; class C1 { int M1() { /**/return (int)"""";/**/ } } "; string expectedOperationTree = @" IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: 'return (int)"""";') IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: System.Int32, IsInvalid) (Syntax: '(int)""""') ILiteralExpression (OperationKind.LiteralExpression, Type: System.String, Constant: """") (Syntax: '""""') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS0030: Cannot convert type 'string' to 'int' // /**/return (int)"";/**/ Diagnostic(ErrorCode.ERR_NoExplicitConv, @"(int)""""").WithArguments("string", "int").WithLocation(8, 26) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } [Fact] public void ConversionExpression_Explicit_ReturnConversion_InvalidSyntax() { string source = @" using System; class C1 { int M1() { /**/return (int);/**/ } } "; string expectedOperationTree = @" IReturnStatement (OperationKind.ReturnStatement, IsInvalid) (Syntax: 'return (int);') IConversionExpression (ConversionKind.Invalid, Explicit) (OperationKind.ConversionExpression, Type: System.Int32, IsInvalid) (Syntax: '(int)') IInvalidExpression (OperationKind.InvalidExpression, Type: ?, IsInvalid) (Syntax: '') "; var expectedDiagnostics = new DiagnosticDescription[] { // CS1525: Invalid expression term ';' // /**/return (int);/**/ Diagnostic(ErrorCode.ERR_InvalidExprTerm, ";").WithArguments(";").WithLocation(8, 31) }; VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } #endregion private class ExpectedSymbolVerifier { public static SyntaxNode VariableDeclaratorSelector(SyntaxNode syntaxNode) => ((VariableDeclaratorSyntax)syntaxNode).Initializer.Value; public static SyntaxNode IdentitySelector(SyntaxNode syntaxNode) => syntaxNode; public static SyntaxNode ReturnStatementSelector(SyntaxNode syntaxNode) => ((ReturnStatementSyntax)syntaxNode).Expression; public static IConversionExpression IVariableDeclarationStatementSelector(IOperation operation) => (IConversionExpression)((IVariableDeclarationStatement)operation).Declarations.Single().Initializer; public static IConversionExpression IReturnDeclarationStatementSelector(IOperation operation) => (IConversionExpression)((IReturnStatement)operation).ReturnedValue; public static IOperation NestedConversionChildSelector(IConversionExpression conversion) => ((IConversionExpression)conversion.Operand).Operand; public Func OperationSelector { get; set; } public Func ConversionChildSelector { get; set; } = (conversion) => conversion.Operand; public Func SyntaxSelector { get; set; } /// /// Verifies that the given operation has the type information that the semantic model has for the given /// syntax node. A selector is used to walk the operation tree and syntax tree for the final /// nodes to compare type info for. /// /// is used to to select the syntax node to test. /// is used to select the IConversion node to test. /// is used to select what child node of the IConversion to compare original types to. /// this is useful for multiple conversion scenarios where we end up with multiple IConversion nodes in the tree. /// public void Verify(IOperation variableDeclaration, Compilation compilation, SyntaxNode syntaxNode) { var finalSyntax = GetAndInvokeSyntaxSelector(syntaxNode); var semanticModel = compilation.GetSemanticModel(finalSyntax.SyntaxTree); var typeInfo = semanticModel.GetTypeInfo(finalSyntax); var initializer = GetAndInvokeOperationSelector(variableDeclaration); var conversion = initializer; Assert.Equal(conversion.Type, typeInfo.ConvertedType); Assert.Equal(ConversionChildSelector(conversion).Type, typeInfo.Type); } private SyntaxNode GetAndInvokeSyntaxSelector(SyntaxNode syntax) { if (SyntaxSelector != null) { return SyntaxSelector(syntax); } else { switch (syntax) { case VariableDeclaratorSyntax _: return VariableDeclaratorSelector(syntax); case ReturnStatementSyntax _: return ReturnStatementSelector(syntax); case CastExpressionSyntax cast: return cast.Expression; default: throw new ArgumentException($"Cannot handle syntax of type {syntax.GetType()}"); } } } private IConversionExpression GetAndInvokeOperationSelector(IOperation operation) { if (OperationSelector != null) { return OperationSelector(operation); } switch (operation) { case IVariableDeclarationStatement _: return IVariableDeclarationStatementSelector(operation); case IReturnStatement _: return IReturnDeclarationStatementSelector(operation); case IConversionExpression conv: return conv; default: throw new ArgumentException($"Cannot handle arguments of type {operation.GetType()}"); } } } } }