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 /*