Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
6709 lines (6034 sloc) 236 KB
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.IO;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
public class CodeGenExprLambdaTests : CSharpTestBase
{
protected CompilationVerifier CompileAndVerifyUtil(
CSharpTestSource source,
MetadataReference[] references = null,
string expectedOutput = null,
CSharpCompilationOptions options = null,
CSharpParseOptions parseOptions = null,
Verification verify = Verification.Passes) => CompileAndVerify(source, references, targetFramework: TargetFramework.Standard, expectedOutput: expectedOutput, options: options, parseOptions: parseOptions, verify: verify);
/// <summary>
/// Reference to an assembly that defines Expression Trees.
/// </summary>
protected static MetadataReference ExpressionAssemblyRef => SystemCoreRef_v46;
#region A string containing expression-tree dumping utilities
private const string ExpressionTestLibrary = @"
using System;
using System.Globalization;
using System.Linq.Expressions;
using System.Text;
public class TestBase
{
protected static void DCheck<T>(Expression<T> e, string expected) { Check(e.Dump(), expected); }
protected static void Check<T>(Expression<Func<T>> e, string expected) { Check(e.Dump(), expected); }
protected static void Check<T1, T2>(Expression<Func<T1, T2>> e, string expected) { Check(e.Dump(), expected); }
protected static void Check<T1, T2, T3>(Expression<Func<T1, T2, T3>> e, string expected) { Check(e.Dump(), expected); }
protected static void Check<T1, T2, T3, T4>(Expression<Func<T1, T2, T3, T4>> e, string expected) { Check(e.Dump(), expected); }
protected static string ToString<T>(Expression<Func<T>> e) { return e.Dump(); }
protected static string ToString<T1, T2>(Expression<Func<T1, T2>> e) { return e.Dump(); }
protected static string ToString<T1, T2, T3>(Expression<Func<T1, T2, T3>> e) { return e.Dump(); }
private static void Check(string actual, string expected)
{
if (expected != actual)
{
Console.WriteLine(""FAIL"");
Console.WriteLine(""expected: "" + expected);
Console.WriteLine(""actual: "" + actual);
// throw new Exception(""expected='"" + expected + ""'; actual='"" + actual + ""'"");
}
}
}
public static class ExpressionExtensions
{
public static string Dump<T>(this Expression<T> self)
{
return ExpressionPrinter.Print(self.Body);
}
}
class ExpressionPrinter : System.Linq.Expressions.ExpressionVisitor
{
private StringBuilder s = new StringBuilder();
public static string Print(Expression e)
{
var p = new ExpressionPrinter();
p.Visit(e);
return p.s.ToString();
}
public override Expression Visit(Expression node)
{
if (node == null) { s.Append(""null""); return null; }
s.Append(node.NodeType.ToString());
s.Append(""("");
base.Visit(node);
s.Append("" Type:"" + node.Type);
s.Append("")"");
return null;
}
protected override MemberBinding VisitMemberBinding(MemberBinding node)
{
if (node == null) { s.Append(""null""); return null; }
return base.VisitMemberBinding(node);
}
protected override MemberMemberBinding VisitMemberMemberBinding(MemberMemberBinding node)
{
s.Append(""MemberMemberBinding(Member="");
s.Append(node.Member.ToString());
foreach (var b in node.Bindings)
{
s.Append("" "");
VisitMemberBinding(b);
}
s.Append("")"");
return null;
}
protected override MemberListBinding VisitMemberListBinding(MemberListBinding node)
{
s.Append(""MemberListBinding(Member="");
s.Append(node.Member.ToString());
foreach (var i in node.Initializers)
{
s.Append("" "");
VisitElementInit(i);
}
s.Append("")"");
return null;
}
protected override MemberAssignment VisitMemberAssignment(MemberAssignment node)
{
s.Append(""MemberAssignment(Member="");
s.Append(node.Member.ToString());
s.Append("" Expression="");
Visit(node.Expression);
s.Append("")"");
return null;
}
protected override Expression VisitMemberInit(MemberInitExpression node)
{
s.Append(""NewExpression: "");
Visit(node.NewExpression);
s.Append("" Bindings:["");
bool first = true;
foreach (var b in node.Bindings)
{
if (!first) s.Append("" "");
VisitMemberBinding(b);
first = false;
}
s.Append(""]"");
return null;
}
protected override Expression VisitBinary(BinaryExpression node)
{
Visit(node.Left);
s.Append("" "");
Visit(node.Right);
if (node.Conversion != null)
{
s.Append("" Conversion:"");
Visit(node.Conversion);
}
if (node.IsLifted) s.Append("" Lifted"");
if (node.IsLiftedToNull) s.Append("" LiftedToNull"");
if (node.Method != null) s.Append("" Method:["" + node.Method + ""]"");
return null;
}
protected override Expression VisitConditional(ConditionalExpression node)
{
Visit(node.Test);
s.Append("" ? "");
Visit(node.IfTrue);
s.Append("" : "");
Visit(node.IfFalse);
return null;
}
protected override Expression VisitConstant(ConstantExpression node)
{
// s.Append(node.Value == null ? ""null"" : node.Value.ToString());
s.Append(node.Value == null ? ""null"" : GetCultureInvariantString(node.Value));
return null;
}
protected override Expression VisitDefault(DefaultExpression node)
{
return null;
}
protected override Expression VisitIndex(IndexExpression node)
{
Visit(node.Object);
s.Append(""["");
int n = node.Arguments.Count;
for (int i = 0; i < n; i++)
{
if (i != 0) s.Append("" "");
Visit(node.Arguments[i]);
}
s.Append(""]"");
if (node.Indexer != null) s.Append("" Indexer:"" + node.Indexer);
return null;
}
protected override Expression VisitInvocation(InvocationExpression node)
{
Visit(node.Expression);
s.Append(""("");
int n = node.Arguments.Count;
for (int i = 0; i < n; i++)
{
if (i != 0) s.Append("" "");
Visit(node.Arguments[i]);
}
s.Append("")"");
return null;
}
protected override Expression VisitLambda<T>(Expression<T> node)
{
s.Append(""("");
int n = node.Parameters.Count;
for (int i = 0; i < n; i++)
{
if (i != 0) s.Append("" "");
Visit(node.Parameters[i]);
}
s.Append("") => "");
if (node.Name != null) s.Append(node.Name);
Visit(node.Body);
if (node.ReturnType != null) s.Append("" ReturnType:"" + node.ReturnType);
if (node.TailCall) s.Append("" TailCall"");
return null;
}
protected override Expression VisitListInit(ListInitExpression node)
{
Visit(node.NewExpression);
s.Append(""{"");
int n = node.Initializers.Count;
for (int i = 0; i < n; i++)
{
if (i != 0) s.Append("" "");
Visit(node.Initializers[i]);
}
s.Append(""}"");
return null;
}
protected override ElementInit VisitElementInit(ElementInit node)
{
Visit(node);
return null;
}
private void Visit(ElementInit node)
{
s.Append(""ElementInit("");
s.Append(node.AddMethod);
int n = node.Arguments.Count;
for (int i = 0; i < n; i++)
{
s.Append("" "");
Visit(node.Arguments[i]);
}
s.Append("")"");
}
protected override Expression VisitMember(MemberExpression node)
{
Visit(node.Expression);
s.Append(""."");
s.Append(node.Member.Name);
return null;
}
protected override Expression VisitMethodCall(MethodCallExpression node)
{
Visit(node.Object);
s.Append("".["" + node.Method + ""]"");
s.Append(""("");
int n = node.Arguments.Count;
for (int i = 0; i < n; i++)
{
if (i != 0) s.Append("", "");
Visit(node.Arguments[i]);
}
s.Append("")"");
return null;
}
protected override Expression VisitNew(NewExpression node)
{
s.Append((node.Constructor != null) ? ""["" + node.Constructor + ""]"" : ""<.ctor>"");
s.Append(""("");
int n = node.Arguments.Count;
for (int i = 0; i < n; i++)
{
if (i != 0) s.Append("", "");
Visit(node.Arguments[i]);
}
s.Append("")"");
if (node.Members != null)
{
n = node.Members.Count;
if (n != 0)
{
s.Append(""{"");
for (int i = 0; i < n; i++)
{
var info = node.Members[i];
if (i != 0) s.Append("" "");
s.Append(info);
}
s.Append(""}"");
}
}
return null;
}
protected override Expression VisitNewArray(NewArrayExpression node)
{
s.Append(""["");
int n = node.Expressions.Count;
for (int i = 0; i < n; i++)
{
if (i != 0) s.Append("" "");
Visit(node.Expressions[i]);
}
s.Append(""]"");
return null;
}
protected override Expression VisitParameter(ParameterExpression node)
{
s.Append(node.Name);
if (node.IsByRef) s.Append("" ByRef"");
return null;
}
protected override Expression VisitTypeBinary(TypeBinaryExpression node)
{
Visit(node.Expression);
s.Append("" TypeOperand:"" + node.TypeOperand);
return null;
}
protected override Expression VisitUnary(UnaryExpression node)
{
Visit(node.Operand);
if (node.IsLifted) s.Append("" Lifted"");
if (node.IsLiftedToNull) s.Append("" LiftedToNull"");
if (node.Method != null) s.Append("" Method:["" + node.Method + ""]"");
return null;
}
public static string GetCultureInvariantString(object value)
{
var valueType = value.GetType();
if (valueType == typeof(string))
{
return value as string;
}
if (valueType == typeof(DateTime))
{
return ((DateTime)value).ToString(""M/d/yyyy h:mm:ss tt"", CultureInfo.InvariantCulture);
}
if (valueType == typeof(float))
{
return ((float)value).ToString(CultureInfo.InvariantCulture);
}
if (valueType == typeof(double))
{
return ((double)value).ToString(CultureInfo.InvariantCulture);
}
if (valueType == typeof(decimal))
{
return ((decimal)value).ToString(CultureInfo.InvariantCulture);
}
return value.ToString();
}
}
";
#endregion A string containing expression-tree dumping utilities
[Fact]
public void ExprLambdaReordering()
{
var verifier = CompileAndVerify(new[] { ExpressionTestLibrary, @"
using System;
using System.Linq;
class C
{
public static void Main() => F(new[] { 1, 2, 3}.AsQueryable());
static void F(IQueryable<int> q)
{
IQueryable<int> result = from/*0*/ a in q
join/*1*/ b in new[] { 5 } on a + 1 equals b - 1
group/*2*/ new { a, b = a + 5 } by new { c = a + 4 } into d
select/*3*/ d.Key.c;
Console.WriteLine(ExpressionPrinter.Print(result.Expression));
}
}" },
// The exact result of this test isn't important, only that it was unchanged
// by making AnonymousFunction conversions be side-affecting in the local rewriter
expectedOutput: @"Call(null.[System.Linq.IQueryable`1[System.Int32] Select[IGrouping`2,Int32](System.Linq.IQueryable`1[System.Linq.IGrouping`2[<>f__AnonymousType1`1[System.Int32],<>f__AnonymousType0`2[System.Int32,System.Int32]]], System.Linq.Expressions.Expression`1[System.Func`2[System.Linq.IGrouping`2[<>f__AnonymousType1`1[System.Int32],<>f__AnonymousType0`2[System.Int32,System.Int32]],System.Int32]])](Call(null.[System.Linq.IQueryable`1[System.Linq.IGrouping`2[<>f__AnonymousType1`1[System.Int32],<>f__AnonymousType0`2[System.Int32,System.Int32]]] GroupBy[<>f__AnonymousType0`2,<>f__AnonymousType1`1,<>f__AnonymousType0`2](System.Linq.IQueryable`1[<>f__AnonymousType0`2[System.Int32,System.Int32]], System.Linq.Expressions.Expression`1[System.Func`2[<>f__AnonymousType0`2[System.Int32,System.Int32],<>f__AnonymousType1`1[System.Int32]]], System.Linq.Expressions.Expression`1[System.Func`2[<>f__AnonymousType0`2[System.Int32,System.Int32],<>f__AnonymousType0`2[System.Int32,System.Int32]]])](Call(null.[System.Linq.IQueryable`1[<>f__AnonymousType0`2[System.Int32,System.Int32]] Join[Int32,Int32,Int32,<>f__AnonymousType0`2](System.Linq.IQueryable`1[System.Int32], System.Collections.Generic.IEnumerable`1[System.Int32], System.Linq.Expressions.Expression`1[System.Func`2[System.Int32,System.Int32]], System.Linq.Expressions.Expression`1[System.Func`2[System.Int32,System.Int32]], System.Linq.Expressions.Expression`1[System.Func`3[System.Int32,System.Int32,<>f__AnonymousType0`2[System.Int32,System.Int32]]])](Constant(System.Int32[] Type:System.Linq.EnumerableQuery`1[System.Int32]), Constant(System.Int32[] Type:System.Collections.Generic.IEnumerable`1[System.Int32]), Quote(Lambda((Parameter(a Type:System.Int32)) => Add(Parameter(a Type:System.Int32) Constant(1 Type:System.Int32) Type:System.Int32) ReturnType:System.Int32 Type:System.Func`2[System.Int32,System.Int32]) Type:System.Linq.Expressions.Expression`1[System.Func`2[System.Int32,System.Int32]]), Quote(Lambda((Parameter(b Type:System.Int32)) => Subtract(Parameter(b Type:System.Int32) Constant(1 Type:System.Int32) Type:System.Int32) ReturnType:System.Int32 Type:System.Func`2[System.Int32,System.Int32]) Type:System.Linq.Expressions.Expression`1[System.Func`2[System.Int32,System.Int32]]), Quote(Lambda((Parameter(a Type:System.Int32) Parameter(b Type:System.Int32)) => New([Void .ctor(Int32, Int32)](Parameter(a Type:System.Int32), Parameter(b Type:System.Int32)){Int32 a Int32 b} Type:<>f__AnonymousType0`2[System.Int32,System.Int32]) ReturnType:<>f__AnonymousType0`2[System.Int32,System.Int32] Type:System.Func`3[System.Int32,System.Int32,<>f__AnonymousType0`2[System.Int32,System.Int32]]) Type:System.Linq.Expressions.Expression`1[System.Func`3[System.Int32,System.Int32,<>f__AnonymousType0`2[System.Int32,System.Int32]]])) Type:System.Linq.IQueryable`1[<>f__AnonymousType0`2[System.Int32,System.Int32]]), Quote(Lambda((Parameter(<>h__TransparentIdentifier0 Type:<>f__AnonymousType0`2[System.Int32,System.Int32])) => New([Void .ctor(Int32)](Add(MemberAccess(Parameter(<>h__TransparentIdentifier0 Type:<>f__AnonymousType0`2[System.Int32,System.Int32]).a Type:System.Int32) Constant(4 Type:System.Int32) Type:System.Int32)){Int32 c} Type:<>f__AnonymousType1`1[System.Int32]) ReturnType:<>f__AnonymousType1`1[System.Int32] Type:System.Func`2[<>f__AnonymousType0`2[System.Int32,System.Int32],<>f__AnonymousType1`1[System.Int32]]) Type:System.Linq.Expressions.Expression`1[System.Func`2[<>f__AnonymousType0`2[System.Int32,System.Int32],<>f__AnonymousType1`1[System.Int32]]]), Quote(Lambda((Parameter(<>h__TransparentIdentifier0 Type:<>f__AnonymousType0`2[System.Int32,System.Int32])) => New([Void .ctor(Int32, Int32)](MemberAccess(Parameter(<>h__TransparentIdentifier0 Type:<>f__AnonymousType0`2[System.Int32,System.Int32]).a Type:System.Int32), Add(MemberAccess(Parameter(<>h__TransparentIdentifier0 Type:<>f__AnonymousType0`2[System.Int32,System.Int32]).a Type:System.Int32) Constant(5 Type:System.Int32) Type:System.Int32)){Int32 a Int32 b} Type:<>f__AnonymousType0`2[System.Int32,System.Int32]) ReturnType:<>f__AnonymousType0`2[System.Int32,System.Int32] Type:System.Func`2[<>f__AnonymousType0`2[System.Int32,System.Int32],<>f__AnonymousType0`2[System.Int32,System.Int32]]) Type:System.Linq.Expressions.Expression`1[System.Func`2[<>f__AnonymousType0`2[System.Int32,System.Int32],<>f__AnonymousType0`2[System.Int32,System.Int32]]])) Type:System.Linq.IQueryable`1[System.Linq.IGrouping`2[<>f__AnonymousType1`1[System.Int32],<>f__AnonymousType0`2[System.Int32,System.Int32]]]), Quote(Lambda((Parameter(d Type:System.Linq.IGrouping`2[<>f__AnonymousType1`1[System.Int32],<>f__AnonymousType0`2[System.Int32,System.Int32]])) => MemberAccess(MemberAccess(Parameter(d Type:System.Linq.IGrouping`2[<>f__AnonymousType1`1[System.Int32],<>f__AnonymousType0`2[System.Int32,System.Int32]]).Key Type:<>f__AnonymousType1`1[System.Int32]).c Type:System.Int32) ReturnType:System.Int32 Type:System.Func`2[System.Linq.IGrouping`2[<>f__AnonymousType1`1[System.Int32],<>f__AnonymousType0`2[System.Int32,System.Int32]],System.Int32]) Type:System.Linq.Expressions.Expression`1[System.Func`2[System.Linq.IGrouping`2[<>f__AnonymousType1`1[System.Int32],<>f__AnonymousType0`2[System.Int32,System.Int32]],System.Int32]])) Type:System.Linq.IQueryable`1[System.Int32])");
}
[Fact]
public void ExprLambdaIndexerCompoundAssignment()
{
var verifier = CompileAndVerify(@"
using System;
using System.Linq.Expressions;
class C
{
private static Expression<Func<int>> _f1;
private static Expression<Func<int>> _f2;
public static void Main() {
var c = new C();
c[() => 0] += 1;
Console.WriteLine(object.ReferenceEquals(_f1, _f2));
}
int this[Expression<Func<int>> f] {
get
{
Console.WriteLine(f.Compile()());
_f1 = f;
return 0;
}
set
{
Console.WriteLine(f.Compile()());
_f2 = f;
}
}
}", expectedOutput: @"0
0
True");
}
[WorkItem(544283, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544283")]
[Fact]
public void MissingLibrary()
{
string program = @"
using System;
using System.Linq.Expressions;
class Program
{
static void Main()
{
Expression<Func<int>> e = () => 1;
}
}
namespace System.Linq.Expressions
{
class Expression<T> { }
}";
CreateCompilationWithMscorlib40AndSystemCore(program).Emit(new System.IO.MemoryStream()).Diagnostics
.Verify(
// (9,9): warning CS0436: The type 'System.Linq.Expressions.Expression<T>' in '' conflicts with the imported type 'System.Linq.Expressions.Expression<TDelegate>' in 'System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089'. Using the type defined in ''.
// Expression<Func<int>> e = () => 1;
Diagnostic(ErrorCode.WRN_SameFullNameThisAggAgg, "Expression<Func<int>>").WithArguments("", "System.Linq.Expressions.Expression<T>", "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089", "System.Linq.Expressions.Expression<TDelegate>"),
// (9,35): error CS0656: Missing compiler required member 'System.Linq.Expressions.Expression.Lambda'
// Expression<Func<int>> e = () => 1;
Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "() => 1").WithArguments("System.Linq.Expressions.Expression", "Lambda")
);
}
[WorkItem(543322, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543322")]
[Fact]
public void CaptureParameterCallAddition()
{
string program =
@"using System;
delegate D D(int x);
class Program : TestBase
{
public static D F(int n)
{
Console.WriteLine(n);
return null;
}
public static void Main(string[] args)
{
int z = 1;
DCheck<D>(
x => y => F(x+y+z),
""Lambda((Parameter(y Type:System.Int32)) => Call(null.[D F(Int32)](Add(Add(Parameter(x Type:System.Int32) Parameter(y Type:System.Int32) Type:System.Int32) MemberAccess(Constant(Program+<>c__DisplayClass1_0 Type:Program+<>c__DisplayClass1_0).z Type:System.Int32) Type:System.Int32)) Type:D) ReturnType:D Type:D)"");
Console.Write('k');
}
}";
CompileAndVerifyUtil(
source: new string[] { program, ExpressionTestLibrary },
expectedOutput: @"k")
.VerifyDiagnostics();
}
[WorkItem(543322, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/543322")]
[Fact]
public void ExpressionConversionInExpression()
{
string program =
@"using System;
using System.Linq.Expressions;
delegate Expression<D> D(int x);
class Program : TestBase
{
public static Expression<D> F(int n)
{
Console.WriteLine(n);
return null;
}
public static void Main(string[] args)
{
int z = 1;
DCheck<D>(
x => y => F(x + y + z),
""Quote(Lambda((Parameter(y Type:System.Int32)) => Call(null.[System.Linq.Expressions.Expression`1[D] F(Int32)](Add(Add(Parameter(x Type:System.Int32) Parameter(y Type:System.Int32) Type:System.Int32) MemberAccess(Constant(Program+<>c__DisplayClass1_0 Type:Program+<>c__DisplayClass1_0).z Type:System.Int32) Type:System.Int32)) Type:System.Linq.Expressions.Expression`1[D]) ReturnType:System.Linq.Expressions.Expression`1[D] Type:D) Type:System.Linq.Expressions.Expression`1[D])"");
Console.Write('k');
}
}";
CompileAndVerifyUtil(
source: new string[] { program, ExpressionTestLibrary },
expectedOutput: @"k")
.VerifyDiagnostics();
}
[Fact]
public void ConversionAppliedInLambdaForNonMatchingTypes()
{
var program = @"
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
var invoices = new List<Invoice>().AsQueryable();
var oneTimeCharges = new List<OneTimeCharge>().AsQueryable();
var otcCharges = invoices.Join(oneTimeCharges, inv => inv.InvoiceId, otc => otc.Invoice, (inv, otc) => inv.InvoiceId);
Console.Write('k');
}
}
public class OneTimeCharge
{
public int OneTimeChargeId { get; set; }
public int? Invoice { get; set; }
}
public class Invoice
{
public int InvoiceId { get; set; }
}
}
";
CompileAndVerifyUtil(
source: new string[] { program, ExpressionTestLibrary },
expectedOutput: @"k")
.VerifyDiagnostics();
}
[Fact]
public void Addition()
{
var source =
@"using System;
class UD
{
public static UD operator +(UD l, UD r) { return null; }
}
struct UDS
{
public static UDS operator +(UDS l, UDS r) { return default(UDS); }
}
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, int, int>(
(l, r) => l + r,
""Add(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<UD, UD, UD>(
(l, r) => l + r,
""Add(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_Addition(UD, UD)] Type:UD)"");
checked
{
Check<int, int, int>(
(l, r) => l + r,
""AddChecked(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<int?, int?, int?>(
(l, r) => l + r,
""AddChecked(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UD, UD, UD>(
(l, r) => l + r,
""Add(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_Addition(UD, UD)] Type:UD)"");
}
Check<int?, int?, int?>(
(l, r) => l + r,
""Add(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UDS, UDS, UDS>(
(l, r) => l + r,
""Add(Parameter(l Type:UDS) Parameter(r Type:UDS) Method:[UDS op_Addition(UDS, UDS)] Type:UDS)"");
Check<decimal, decimal, decimal>(
(x, y) => x + y,
""Add(Parameter(x Type:System.Decimal) Parameter(y Type:System.Decimal) Method:[System.Decimal op_Addition(System.Decimal, System.Decimal)] Type:System.Decimal)"");
Check<string, string, string>(
(x, y) => x + y,
""Add(Parameter(x Type:System.String) Parameter(y Type:System.String) Method:[System.String Concat(System.String, System.String)] Type:System.String)"");
Check<string, int, string>(
(x, y) => x + y,
""Add(Parameter(x Type:System.String) Convert(Parameter(y Type:System.Int32) Type:System.Object) Method:[System.String Concat(System.Object, System.Object)] Type:System.String)"");
Check<int, string, string>(
(x, y) => x + y,
""Add(Convert(Parameter(x Type:System.Int32) Type:System.Object) Parameter(y Type:System.String) Method:[System.String Concat(System.Object, System.Object)] Type:System.String)"");
Check<Action, Action, Action>(
(x, y) => x + y,
""Convert(Add(Parameter(x Type:System.Action) Parameter(y Type:System.Action) Method:[System.Delegate Combine(System.Delegate, System.Delegate)] Type:System.Delegate) Type:System.Action)"");
Check<int?, int?>(
x => x + null,
""Add(Parameter(x Type:System.Nullable`1[System.Int32]) Constant(null Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new string[] { source, ExpressionTestLibrary },
expectedOutput: @"k");
}
[WorkItem(544027, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544027")]
[ConditionalFact(typeof(WindowsDesktopOnly), Reason = "https://github.com/dotnet/roslyn/issues/30160")]
public void AnonymousCreation()
{
var source =
@"using System;
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, string, object>(
(i, s) => new { A = i, B = s },
""New([Void .ctor(Int32, System.String)](Parameter(i Type:System.Int32), Parameter(s Type:System.String)){Int32 A System.String B} Type:<>f__AnonymousType0`2[System.Int32,System.String])"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: @"k");
}
[WorkItem(544028, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544028")]
[Fact]
public void ArrayIndex()
{
var source =
@"using System;
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, string>(
i => args[i],
""ArrayIndex(MemberAccess(Constant(Program+<>c__DisplayClass0_0 Type:Program+<>c__DisplayClass0_0).args Type:System.String[]) Parameter(i Type:System.Int32) Type:System.String)"");
string[,] s2 = new string[2, 2];
Check<int, string>(
i => s2[i,i],
""Call(MemberAccess(Constant(Program+<>c__DisplayClass0_0 Type:Program+<>c__DisplayClass0_0).s2 Type:System.String[,]).[System.String Get(Int32, Int32)](Parameter(i Type:System.Int32), Parameter(i Type:System.Int32)) Type:System.String)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: @"k");
}
[WorkItem(544029, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544029")]
[Fact]
public void ArrayCreation()
{
var source =
@"using System;
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, int[]>(
i => new int[i],
""NewArrayBounds([Parameter(i Type:System.Int32)] Type:System.Int32[])"");
Check<int, int[,]>(
i => new int[i,i],
""NewArrayBounds([Parameter(i Type:System.Int32) Parameter(i Type:System.Int32)] Type:System.Int32[,])"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: @"k");
}
[WorkItem(544030, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544030")]
[Fact]
public void ArrayInitialization()
{
var source =
@"using System;
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, int[]>(
i => new[] { i, i },
""NewArrayInit([Parameter(i Type:System.Int32) Parameter(i Type:System.Int32)] Type:System.Int32[])"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: @"k");
}
[WorkItem(544112, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544112")]
[Fact]
public void CS0838ERR_ExpressionTreeContainsMultiDimensionalArrayInitializer()
{
var source =
@"using System;
using System.Linq.Expressions;
class Program
{
public static void Main(string[] args)
{
Expression<Func<int, int[,]>> x = i => new[,] {{ i }};
}
}";
CreateCompilationWithMscorlib40AndSystemCore(source).VerifyDiagnostics(
// (7,48): error CS0838: An expression tree may not contain a multidimensional array initializer
// Expression<Func<int, int[,]>> x = i => new[,] {{ i }};
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsMultiDimensionalArrayInitializer, "new[,] {{ i }}")
);
}
[WorkItem(544031, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544031")]
[Fact]
public void ArrayLength()
{
var source =
@"using System;
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int[], int>(
s => s.Length,
""ArrayLength(Parameter(s Type:System.Int32[]) Type:System.Int32)"");
Check<int[,], int>(
a => a.Length,
""MemberAccess(Parameter(a Type:System.Int32[,]).Length Type:System.Int32)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: @"k");
}
[WorkItem(544032, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544032")]
[Fact]
public void AsOperator()
{
var source =
@"using System;
class Program : TestBase
{
public static void Main(string[] args)
{
Check<object, string>(
o => (o as string),
""TypeAs(Parameter(o Type:System.Object) Type:System.String)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[WorkItem(544034, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544034")]
[Fact]
public void BaseReference()
{
var source =
@"using System;
class Program0 : TestBase
{
protected virtual string M() { return ""base""; }
}
class Program : Program0
{
protected override string M() { return ""derived""; }
public static void Main(string[] args)
{
new Program().Main();
}
void Main()
{
Check<string>(
() => base.M(), """");
Console.Write('k');
}
}";
CreateCompilationWithMscorlib40AndSystemCore(new[] { Parse(source), Parse(ExpressionTestLibrary) }).VerifyDiagnostics(
// (265,19): error CS0831: An expression tree may not contain a base access
// () => base.M(), "");
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsBaseAccess, "base")
);
}
[Fact]
public void AsyncLambda()
{
var source =
@"
using System;
using System.Threading.Tasks;
class Program : TestBase
{
public static void Main(string[] args)
{
Check<Task<int>, Task<int>>(
async x => (await x), """");
Console.Write('k');
}
}";
CreateCompilationWithMscorlib46(new[] { Parse(source), Parse(ExpressionTestLibrary) }, new[] { ExpressionAssemblyRef }).VerifyDiagnostics(
// (10,13): error CS1989: Async lambda expressions cannot be converted to expression trees
// async x => (await x), "");
Diagnostic(ErrorCode.ERR_BadAsyncExpressionTree, "async x => (await x)").WithLocation(10, 13)
);
}
[WorkItem(544035, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544035")]
[Fact]
public void Multiply()
{
var source =
@"using System;
class UD
{
public static UD operator *(UD l, UD r) { return null; }
}
struct UDS
{
public static UDS operator *(UDS l, UDS r) { return default(UDS); }
}
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, int, int>(
(l, r) => l * r,
""Multiply(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<UD, UD, UD>(
(l, r) => l * r,
""Multiply(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_Multiply(UD, UD)] Type:UD)"");
checked
{
Check<int, int, int>(
(l, r) => l * r,
""MultiplyChecked(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<int?, int?, int?>(
(l, r) => l * r,
""MultiplyChecked(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UD, UD, UD>(
(l, r) => l * r,
""Multiply(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_Multiply(UD, UD)] Type:UD)"");
}
Check<int?, int?, int?>(
(l, r) => l * r,
""Multiply(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UDS, UDS, UDS>(
(l, r) => l * r,
""Multiply(Parameter(l Type:UDS) Parameter(r Type:UDS) Method:[UDS op_Multiply(UDS, UDS)] Type:UDS)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[WorkItem(544036, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544036")]
[Fact]
public void Subtract()
{
var source =
@"using System;
class UD
{
public static UD operator -(UD l, UD r) { return null; }
}
struct UDS
{
public static UDS operator -(UDS l, UDS r) { return default(UDS); }
}
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, int, int>(
(l, r) => l - r,
""Subtract(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<UD, UD, UD>(
(l, r) => l - r,
""Subtract(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_Subtraction(UD, UD)] Type:UD)"");
checked
{
Check<int, int, int>(
(l, r) => l - r,
""SubtractChecked(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<int?, int?, int?>(
(l, r) => l - r,
""SubtractChecked(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UD, UD, UD>(
(l, r) => l - r,
""Subtract(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_Subtraction(UD, UD)] Type:UD)"");
}
Check<int?, int?, int?>(
(l, r) => l - r,
""Subtract(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UDS, UDS, UDS>(
(l, r) => l - r,
""Subtract(Parameter(l Type:UDS) Parameter(r Type:UDS) Method:[UDS op_Subtraction(UDS, UDS)] Type:UDS)"");
Check<Action, Action, Action>(
(x, y) => x - y,
""Convert(Subtract(Parameter(x Type:System.Action) Parameter(y Type:System.Action) Method:[System.Delegate Remove(System.Delegate, System.Delegate)] Type:System.Delegate) Type:System.Action)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[WorkItem(544037, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544037")]
[Fact]
public void Divide()
{
var source =
@"using System;
class UD
{
public static UD operator /(UD l, UD r) { return null; }
}
struct UDS
{
public static UDS operator /(UDS l, UDS r) { return default(UDS); }
}
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, int, int>(
(l, r) => l / r,
""Divide(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<UD, UD, UD>(
(l, r) => l / r,
""Divide(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_Division(UD, UD)] Type:UD)"");
checked
{
Check<int, int, int>(
(l, r) => l / r,
""Divide(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<int?, int?, int?>(
(l, r) => l / r,
""Divide(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UD, UD, UD>(
(l, r) => l / r,
""Divide(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_Division(UD, UD)] Type:UD)"");
}
Check<int?, int?, int?>(
(l, r) => l / r,
""Divide(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UDS, UDS, UDS>(
(l, r) => l / r,
""Divide(Parameter(l Type:UDS) Parameter(r Type:UDS) Method:[UDS op_Division(UDS, UDS)] Type:UDS)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[WorkItem(544038, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544038")]
[Fact]
public void Remainder()
{
var source =
@"using System;
class UD
{
public static UD operator %(UD l, UD r) { return null; }
}
struct UDS
{
public static UDS operator %(UDS l, UDS r) { return default(UDS); }
}
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, int, int>(
(l, r) => l % r,
""Modulo(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<UD, UD, UD>(
(l, r) => l % r,
""Modulo(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_Modulus(UD, UD)] Type:UD)"");
checked
{
Check<int, int, int>(
(l, r) => l % r,
""Modulo(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<int?, int?, int?>(
(l, r) => l % r,
""Modulo(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UD, UD, UD>(
(l, r) => l % r,
""Modulo(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_Modulus(UD, UD)] Type:UD)"");
}
Check<int?, int?, int?>(
(l, r) => l % r,
""Modulo(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UDS, UDS, UDS>(
(l, r) => l % r,
""Modulo(Parameter(l Type:UDS) Parameter(r Type:UDS) Method:[UDS op_Modulus(UDS, UDS)] Type:UDS)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[WorkItem(544041, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544041")]
[Fact]
public void And()
{
var source =
@"using System;
class UD
{
public static UD operator &(UD l, UD r) { return null; }
}
struct UDS
{
public static UDS operator &(UDS l, UDS r) { return default(UDS); }
}
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, int, int>(
(l, r) => l & r,
""And(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<UD, UD, UD>(
(l, r) => l & r,
""And(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_BitwiseAnd(UD, UD)] Type:UD)"");
checked
{
Check<int, int, int>(
(l, r) => l & r,
""And(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<int?, int?, int?>(
(l, r) => l & r,
""And(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UD, UD, UD>(
(l, r) => l & r,
""And(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_BitwiseAnd(UD, UD)] Type:UD)"");
}
Check<int?, int?, int?>(
(l, r) => l & r,
""And(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UDS, UDS, UDS>(
(l, r) => l & r,
""And(Parameter(l Type:UDS) Parameter(r Type:UDS) Method:[UDS op_BitwiseAnd(UDS, UDS)] Type:UDS)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[WorkItem(544042, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544042")]
[Fact]
public void ExclusiveOr()
{
var source =
@"using System;
class UD
{
public static UD operator ^(UD l, UD r) { return null; }
}
struct UDS
{
public static UDS operator ^(UDS l, UDS r) { return default(UDS); }
}
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, int, int>(
(l, r) => l ^ r,
""ExclusiveOr(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<UD, UD, UD>(
(l, r) => l ^ r,
""ExclusiveOr(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_ExclusiveOr(UD, UD)] Type:UD)"");
checked
{
Check<int, int, int>(
(l, r) => l ^ r,
""ExclusiveOr(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<int?, int?, int?>(
(l, r) => l ^ r,
""ExclusiveOr(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UD, UD, UD>(
(l, r) => l ^ r,
""ExclusiveOr(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_ExclusiveOr(UD, UD)] Type:UD)"");
}
Check<int?, int?, int?>(
(l, r) => l ^ r,
""ExclusiveOr(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UDS, UDS, UDS>(
(l, r) => l ^ r,
""ExclusiveOr(Parameter(l Type:UDS) Parameter(r Type:UDS) Method:[UDS op_ExclusiveOr(UDS, UDS)] Type:UDS)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[WorkItem(544043, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544043")]
[Fact]
public void BitwiseOr()
{
var source =
@"using System;
class UD
{
public static UD operator |(UD l, UD r) { return null; }
}
struct UDS
{
public static UDS operator |(UDS l, UDS r) { return default(UDS); }
}
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, int, int>(
(l, r) => l | r,
""Or(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<UD, UD, UD>(
(l, r) => l | r,
""Or(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_BitwiseOr(UD, UD)] Type:UD)"");
checked
{
Check<int, int, int>(
(l, r) => l | r,
""Or(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32)"");
Check<int?, int?, int?>(
(l, r) => l | r,
""Or(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UD, UD, UD>(
(l, r) => l | r,
""Or(Parameter(l Type:UD) Parameter(r Type:UD) Method:[UD op_BitwiseOr(UD, UD)] Type:UD)"");
}
Check<int?, int?, int?>(
(l, r) => l | r,
""Or(Parameter(l Type:System.Nullable`1[System.Int32]) Parameter(r Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<UDS, UDS, UDS>(
(l, r) => l | r,
""Or(Parameter(l Type:UDS) Parameter(r Type:UDS) Method:[UDS op_BitwiseOr(UDS, UDS)] Type:UDS)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[WorkItem(544039, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544039"), WorkItem(544040, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544040")]
[Fact]
public void MoreBinaryOperators()
{
var source =
@"using System;
struct S { }
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, int, int>(
(l, r) => (l<<r) + (l>>r),
""Add(LeftShift(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32) RightShift(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Int32) Type:System.Int32)"");
Check<int, int, bool>(
(l, r) => (l == r),
""Equal(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Boolean)"");
Check<int, int, bool>(
(l, r) => (l != r),
""NotEqual(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Boolean)"");
Check<int, int, bool>(
(l, r) => (l < r),
""LessThan(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Boolean)"");
Check<int, int, bool>(
(l, r) => (l <= r),
""LessThanOrEqual(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Boolean)"");
Check<int, int, bool>(
(l, r) => (l > r),
""GreaterThan(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Boolean)"");
Check<int, int, bool>(
(l, r) => (l >= r),
""GreaterThanOrEqual(Parameter(l Type:System.Int32) Parameter(r Type:System.Int32) Type:System.Boolean)"");
Check<int?, bool>(
x => x == null,
""Equal(Parameter(x Type:System.Nullable`1[System.Int32]) Constant(null Type:System.Nullable`1[System.Int32]) Lifted Type:System.Boolean)"");
Check<S?, bool>(
x => x == null,
""Equal(Parameter(x Type:System.Nullable`1[S]) Constant(null Type:System.Nullable`1[S]) Lifted Type:System.Boolean)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[WorkItem(544059, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544059")]
[Fact]
public void UnaryOperators()
{
var source =
@"using System;
class UD
{
public static UD operator +(UD l) { return null; }
}
struct UDS
{
public static UDS operator +(UDS l) { return default(UDS); }
}
class Program : TestBase
{
public static void Main(string[] args)
{
Check<int, int>(
x => +x,
""Parameter(x Type:System.Int32)"");
Check<UD, UD>(
x => +x,
""UnaryPlus(Parameter(x Type:UD) Method:[UD op_UnaryPlus(UD)] Type:UD)"");
Check<UDS, UDS>(
x => +x,
""UnaryPlus(Parameter(x Type:UDS) Method:[UDS op_UnaryPlus(UDS)] Type:UDS)"");
Check<int, int>(
x => -x,
""Negate(Parameter(x Type:System.Int32) Type:System.Int32)"");
Check<int, int>(
x => checked (-x),
""NegateChecked(Parameter(x Type:System.Int32) Type:System.Int32)"");
Check<int, int>(
x => ~x,
""Not(Parameter(x Type:System.Int32) Type:System.Int32)"");
Check<bool, bool>(
x => !x,
""Not(Parameter(x Type:System.Boolean) Type:System.Boolean)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[Fact]
public void GrabBag01()
{
var source =
@"using System;
using System.Linq.Expressions;
struct S { }
class C { }
delegate int D(int x);
class Program : TestBase
{
static int M(int x) { Console.Write(x); return x+1; }
public static void Main(string[] args)
{
Check<bool, int, int, int>(
(x, y, z) => x ? y : z,
""Conditional(Parameter(x Type:System.Boolean) ? Parameter(y Type:System.Int32) : Parameter(z Type:System.Int32) Type:System.Int32)"");
Check<int>(
() => default(int),
""Constant(0 Type:System.Int32)"");
Main2<int>(""Constant(0 Type:System.Int32)"");
Check<C>(
() => default(C),
""Constant(null Type:C)"");
Main2<C>(""Constant(null Type:C)"");
Check<S>(
() => default(S),
""Constant(S Type:S)"");
Main2<S>(""Constant(S Type:S)"");
Check<Func<int>, int>(
x => x(),
""Invoke(Parameter(x Type:System.Func`1[System.Int32])() Type:System.Int32)"");
// // The precise form of a delegate creation depends on your platform version!
// Check<Func<int, int>>(
// () => M,
// ""Convert(Call(null.CreateDelegate(Constant(System.Func`2[System.Int32,System.Int32] Type:System.Type), Constant(null Type:System.Object), Constant(Int32 M(Int32) Type:MethodInfo)) Type:Delegate) Type:Func`2)"");
Expression<Func<Func<int, int>>> f = () => M;
f.Compile()()(1);
// Check<Func<int, int>>(
// () => new Func<int, int>(M),
// ""Convert(Call(null.CreateDelegate(Constant(System.Func`2[System.Int32,System.Int32] Type:System.Type), Constant(null Type:System.Object), Constant(Int32 M(Int32) Type:MethodInfo)) Type:Delegate) Type:Func`2)"");
f = () => new Func<int, int>(M);
f.Compile()()(2);
// Check<D, Func<int, int>>(
// d => new Func<int, int>(d),
// ""Convert(Call(null.CreateDelegate(Constant(System.Func`2[System.Int32,System.Int32] Type:System.Type), Convert(Parameter(d Type:D) Type:System.Object), Constant(Int32 Invoke(Int32) Type:MethodInfo)) Type:Delegate) Type:Func`2)"");
D q = M;
f = () => new Func<int, int>(q);
f.Compile()()(3);
Console.Write('k');
}
public static void Main2<T>(string expected)
{
Check<T>(() => default(T), expected);
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "123k");
}
[WorkItem(546147, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546147")]
[Fact]
public void DelegateInvoke()
{
var source =
@"using System;
using System.Linq.Expressions;
class P
{
static void Main()
{
Func<int, int> f = c => c + 1;
Expression<Func<int>> expr = () => f(12);
Console.WriteLine(expr.Dump());
Console.WriteLine(expr);
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput:
@"Invoke(MemberAccess(Constant(P+<>c__DisplayClass0_0 Type:P+<>c__DisplayClass0_0).f Type:System.Func`2[System.Int32,System.Int32])(Constant(12 Type:System.Int32)) Type:System.Int32)
() => Invoke(value(P+<>c__DisplayClass0_0).f, 12)");
}
[ConditionalFact(typeof(ClrOnly), Reason = "https://github.com/mono/mono/issues/10838")]
public void GrabBag02()
{
var source =
@"using System;
class Array
{
public int this[int x]
{
get
{
return 0;
}
}
}
struct S { }
class C
{
public static C operator &(C c1, C c2) { return c1; }
public static C operator |(C c1, C c2) { return c1; }
public static bool operator true(C c) { return false; }
public static bool operator false(C c) { return false; }
}
class D : C
{
public static D operator&(D d1, D d2) { return d1; }
public static D operator|(D d1, D d2) { return d1; }
}
class Program : TestBase
{
public event Action InstanceEvent;
public static event Action StaticEvent;
public static void Main2<T>(string expected) where T : new()
{
Check<T>(
() => new T(),
expected);
}
public static void Main(string[] args)
{
Check<Array, int, int>(
(a, i) => a[i],
""Call(Parameter(a Type:Array).[Int32 get_Item(Int32)](Parameter(i Type:System.Int32)) Type:System.Int32)"");
Check<object, bool>(
o => o is string,
""TypeIs(Parameter(o Type:System.Object) TypeOperand:System.String Type:System.Boolean)"");
Main2<int>(""New(<.ctor>() Type:System.Int32)"");
Main2<object>(""New([Void .ctor()]() Type:System.Object)"");
Check<string, object, object>(
(a, b) => a ?? b,
""Coalesce(Parameter(a Type:System.String) Parameter(b Type:System.Object) Type:System.Object)"");
Check<string, Exception>(
(s) => new Exception(s),
""New([Void .ctor(System.String)](Parameter(s Type:System.String)) Type:System.Exception)"");
Check<int>(
() => new int(),
""Constant(0 Type:System.Int32)"");
Check<S>(
() => new S(),
""New(<.ctor>() Type:S)"");
Check<Type>(
() => typeof(string),
""Constant(System.String Type:System.Type)"");
Check<C, C, C>(
(l, r) => l && r,
""AndAlso(Parameter(l Type:C) Parameter(r Type:C) Method:[C op_BitwiseAnd(C, C)] Type:C)"");
Check<C, C, C>(
(l, r) => l || r,
""OrElse(Parameter(l Type:C) Parameter(r Type:C) Method:[C op_BitwiseOr(C, C)] Type:C)"");
Check<D, D, D>(
(l, r) => l && r,
""AndAlso(Parameter(l Type:D) Parameter(r Type:D) Method:[D op_BitwiseAnd(D, D)] Type:D)"");
Check<D, D, D>(
(l, r) => l || r,
""OrElse(Parameter(l Type:D) Parameter(r Type:D) Method:[D op_BitwiseOr(D, D)] Type:D)"");
Check<int[]>(
() => new int[] { 1, 2, 3 },
""NewArrayInit([Constant(1 Type:System.Int32) Constant(2 Type:System.Int32) Constant(3 Type:System.Int32)] Type:System.Int32[])"");
Check<Program, Action>(
p => p.InstanceEvent,
""MemberAccess(Parameter(p Type:Program).InstanceEvent Type:System.Action)"");
Check<Action>(
() => Program.StaticEvent,
""MemberAccess(null.StaticEvent Type:System.Action)"");
Check<string, string, bool>(
(x, y) => x == y,
""Equal(Parameter(x Type:System.String) Parameter(y Type:System.String) Method:[Boolean op_Equality(System.String, System.String)] Type:System.Boolean)"");
DCheck<Action>(
() => Console.WriteLine((object)null),
""Call(null.[Void WriteLine(System.Object)](Constant(null Type:System.Object)) Type:System.Void)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[Fact]
public void UnsafeExprTree()
{
var source =
@"using System;
using System.Linq.Expressions;
struct S {}
class Program
{
public unsafe static void Main(string[] args)
{
int* p = null;
Expression<Func<int>> efi = () => *p;
Expression<Func<int>> efi2 = () => sizeof(S);
}
}";
var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.UnsafeReleaseDll);
c.VerifyDiagnostics(
// (9,43): error CS1944: An expression tree may not contain an unsafe pointer operation
// Expression<Func<int>> efi = () => *p;
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsPointerOp, "*p"),
// (10,44): error CS1944: An expression tree may not contain an unsafe pointer operation
// Expression<Func<int>> efi2 = () => sizeof(S);
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsPointerOp, "sizeof(S)")
);
}
[WorkItem(544044, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544044")]
[Fact]
public void CollectionInitialization()
{
var source =
@"using System;
class Program : TestBase
{
public static void Main(string[] args)
{
Check<System.Collections.Generic.List<int>>(
() => new System.Collections.Generic.List<int> { 1, 2, 3 },
""ListInit(New([Void .ctor()]() Type:System.Collections.Generic.List`1[System.Int32]){ElementInit(Void Add(Int32) Constant(1 Type:System.Int32)) ElementInit(Void Add(Int32) Constant(2 Type:System.Int32)) ElementInit(Void Add(Int32) Constant(3 Type:System.Int32))} Type:System.Collections.Generic.List`1[System.Int32])"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[WorkItem(544390, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544390")]
[Fact]
public void ObjectInitialization()
{
var source =
@"using System;
using System.Collections.Generic;
using System.Linq.Expressions;
public class Node
{
public Node A;
public Node B { set; get; }
public List<Node> C = new List<Node>();
public List<Node> D { set; get; }
public string S;
}
class Program : TestBase
{
public static void N(Expression<Func<Node, Node>> e) { Console.WriteLine(e.Dump()); }
public static void M<T>()
where T : Node, new()
{
N(x => new T { A = x });
N(x => new T { B = x });
N(x => new T { A = { A = { A = x } } });
N(x => new T { B = { B = { B = x } } });
N(x => new T { B = { B = { C = { x, x } } } });
N(x => new T { C = { x, x } });
N(x => new T { D = { x, x } });
N(x => new T { S = ""hello"" + x.ToString() });
}
public static void Main(string[] args)
{
N(x => new Node { A = x });
N(x => new Node { B = x });
N(x => new Node { A = { A = { A = x } } });
N(x => new Node { B = { B = { B = x } } });
N(x => new Node { B = { B = { C = { x, x } } } });
N(x => new Node { C = { x, x } });
N(x => new Node { D = { x, x } });
N(x => new Node { S = ""hello"" + x.ToString() });
M<Node>();
}
}";
var expectedOutput =
@"MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberAssignment(Member=Node A Expression=Parameter(x Type:Node))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberAssignment(Member=Node B Expression=Parameter(x Type:Node))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberMemberBinding(Member=Node A MemberMemberBinding(Member=Node A MemberAssignment(Member=Node A Expression=Parameter(x Type:Node))))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberMemberBinding(Member=Node B MemberMemberBinding(Member=Node B MemberAssignment(Member=Node B Expression=Parameter(x Type:Node))))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberMemberBinding(Member=Node B MemberMemberBinding(Member=Node B MemberListBinding(Member=System.Collections.Generic.List`1[Node] C ElementInit(Void Add(Node) Parameter(x Type:Node)) ElementInit(Void Add(Node) Parameter(x Type:Node)))))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberListBinding(Member=System.Collections.Generic.List`1[Node] C ElementInit(Void Add(Node) Parameter(x Type:Node)) ElementInit(Void Add(Node) Parameter(x Type:Node)))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberListBinding(Member=System.Collections.Generic.List`1[Node] D ElementInit(Void Add(Node) Parameter(x Type:Node)) ElementInit(Void Add(Node) Parameter(x Type:Node)))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberAssignment(Member=System.String S Expression=Add(Constant(hello Type:System.String) Call(Parameter(x Type:Node).[System.String ToString()]() Type:System.String) Method:[System.String Concat(System.String, System.String)] Type:System.String))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberAssignment(Member=Node A Expression=Parameter(x Type:Node))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberAssignment(Member=Node B Expression=Parameter(x Type:Node))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberMemberBinding(Member=Node A MemberMemberBinding(Member=Node A MemberAssignment(Member=Node A Expression=Parameter(x Type:Node))))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberMemberBinding(Member=Node B MemberMemberBinding(Member=Node B MemberAssignment(Member=Node B Expression=Parameter(x Type:Node))))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberMemberBinding(Member=Node B MemberMemberBinding(Member=Node B MemberListBinding(Member=System.Collections.Generic.List`1[Node] C ElementInit(Void Add(Node) Parameter(x Type:Node)) ElementInit(Void Add(Node) Parameter(x Type:Node)))))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberListBinding(Member=System.Collections.Generic.List`1[Node] C ElementInit(Void Add(Node) Parameter(x Type:Node)) ElementInit(Void Add(Node) Parameter(x Type:Node)))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberListBinding(Member=System.Collections.Generic.List`1[Node] D ElementInit(Void Add(Node) Parameter(x Type:Node)) ElementInit(Void Add(Node) Parameter(x Type:Node)))] Type:Node)
MemberInit(NewExpression: New([Void .ctor()]() Type:Node) Bindings:[MemberAssignment(Member=System.String S Expression=Add(Constant(hello Type:System.String) Call(Parameter(x Type:Node).[System.String ToString()]() Type:System.String) Method:[System.String Concat(System.String, System.String)] Type:System.String))] Type:Node)";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: expectedOutput);
}
[Fact]
public void Lambda()
{
var source =
@"using System;
using System.Linq.Expressions;
class L : TestBase
{
public L Select(Expression<Func<int, int>> f) {
Check(f, ""Parameter(y Type:System.Int32)"");
return this;
}
}
partial class Program
{
public static void Main(string[] args)
{
L el = new L();
var x = from y in el select y;
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[WorkItem(544218, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544218")]
[Fact]
public void Linq()
{
var source =
@"using System;
using System.Linq;
using System.Linq.Expressions;
class A
{
static void Main()
{
Expression<Func<string[], object>> e = s => from x in s
from y in s
orderby x descending
select x;
Console.WriteLine(e.ToString());
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source },
expectedOutput: "s => s.SelectMany(x => s, (x, y) => new <>f__AnonymousType0`2(x = x, y = y)).OrderByDescending(<>h__TransparentIdentifier0 => <>h__TransparentIdentifier0.x).Select(<>h__TransparentIdentifier0 => <>h__TransparentIdentifier0.x)");
}
[Fact]
public void Enum()
{
var source =
@"using System;
enum Color { Red }
partial class Program : TestBase
{
public static void Main(string[] args)
{
Check<Color, int, Color>(
(x, y) => x + y,
""Convert(Add(Convert(Parameter(x Type:Color) Type:System.Int32) Parameter(y Type:System.Int32) Type:System.Int32) Type:Color)"");
Check<int, Color, Color>(
(x, y) => x + y,
""Convert(Add(Parameter(x Type:System.Int32) Convert(Parameter(y Type:Color) Type:System.Int32) Type:System.Int32) Type:Color)"");
Check<Color?, int?, Color?>(
(x, y) => x + y,
""Convert(Add(Convert(Parameter(x Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Parameter(y Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[Color])"");
Check<int?, Color?, Color?>(
(x, y) => x + y,
""Convert(Add(Parameter(x Type:System.Nullable`1[System.Int32]) Convert(Parameter(y Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[Color])"");
Check<Color, Color, bool>(
(x, y) => x < y,
""LessThan(Convert(Parameter(x Type:Color) Type:System.Int32) Convert(Parameter(y Type:Color) Type:System.Int32) Type:System.Boolean)"");
Check<Color?, Color?, bool>(
(x, y) => x < y,
""LessThan(Convert(Parameter(x Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Convert(Parameter(y Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted Type:System.Boolean)"");
Console.Write('k');
}
}";
var compilation = CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: "k");
}
[Fact]
public void CoalesceAndConversions()
{
var text =
@"using System;
class D
{
public static implicit operator int(D d) { return 0; }
public static implicit operator D(int i) { return null; }
}
public struct S
{
public static implicit operator S(decimal d) { return new S(); }
}
partial class Program : TestBase
{
public static void Main(string[] args)
{
Check<D, D, D>(
(x, y) => x ?? y,
""Coalesce(Parameter(x Type:D) Parameter(y Type:D) Type:D)"");
Check<int?, int, int>(
(x, y) => x ?? y,
""Coalesce(Parameter(x Type:System.Nullable`1[System.Int32]) Parameter(y Type:System.Int32) Type:System.Int32)"");
Check<int?, int?, int?>(
(x, y) => x ?? y,
""Coalesce(Parameter(x Type:System.Nullable`1[System.Int32]) Parameter(y Type:System.Nullable`1[System.Int32]) Type:System.Nullable`1[System.Int32])"");
Check<D, int, int>(
(x, y) => x ?? y,
""Convert(Coalesce(Parameter(x Type:D) Convert(Parameter(y Type:System.Int32) Method:[D op_Implicit(Int32)] Type:D) Type:D) Method:[Int32 op_Implicit(D)] Type:System.Int32)"");
Check<D, int?, int?>(
(x, y) => x ?? y,
""Convert(Convert(Coalesce(Parameter(x Type:D) Convert(Parameter(y Type:System.Nullable`1[System.Int32]) Lifted Method:[D op_Implicit(Int32)] Type:D) Type:D) Method:[Int32 op_Implicit(D)] Type:System.Int32) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])"");
Check<int?, D, long?>(
(x, y) => x ?? y,
""Convert(Convert(Coalesce(Parameter(x Type:System.Nullable`1[System.Int32]) Convert(Parameter(y Type:D) Method:[Int32 op_Implicit(D)] Type:System.Int32) Type:System.Int32) Type:System.Int64) Lifted LiftedToNull Type:System.Nullable`1[System.Int64])"");
Check<short?, int, long?>(
(x, y) => x ?? y,
""Convert(Convert(Coalesce(Parameter(x Type:System.Nullable`1[System.Int16]) Parameter(y Type:System.Int32) Type:System.Int32) Type:System.Int64) Lifted LiftedToNull Type:System.Nullable`1[System.Int64])"");
Check<IntPtr, DayOfWeek>( // 12549
x => (DayOfWeek)x,
""Convert(Convert(Parameter(x Type:System.IntPtr) Method:[Int32 op_Explicit(IntPtr)] Type:System.Int32) Type:System.DayOfWeek)"");
Check<int, S?>(
x => x,
""Convert(Convert(Convert(Parameter(x Type:System.Int32) Method:[System.Decimal op_Implicit(Int32)] Type:System.Decimal) Method:[S op_Implicit(System.Decimal)] Type:S) Lifted LiftedToNull Type:System.Nullable`1[S])"");
// the native compiler gets the following wrong (thereby generating bad code!) We therefore handle the expression tree differently
Func<int?, S?> f = x => x;
Console.WriteLine(P(f(null)));
Console.WriteLine(P(f(1)));
}
static string P(S? s)
{
return (s == null) ? ""null"" : ""S"";
}
}";
var compilation = CompileAndVerifyUtil(
new[] { text, ExpressionTestLibrary },
expectedOutput: @"null
S");
}
#region Regression Tests
[WorkItem(544159, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544159")]
[Fact]
public void BinaryAddOperandTypesEnumAndInt()
{
var text = @"
using System;
using System.Linq.Expressions;
public enum color { Red, Green, Blue };
class Test
{
static void Main()
{
Expression<Func<color, int, color>> testExpr = (x, y) => x + y;
var result = testExpr.Compile()(color.Red, 1);
Console.WriteLine(result);
}
}";
CompileAndVerifyUtil(text, expectedOutput: "Green");
}
[WorkItem(544207, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544207")]
[Fact]
public void BinaryAddOperandTypesStringAndString()
{
var text = @"
using System;
using System.Linq;
using System.Linq.Expressions;
class Test
{
public static void Main()
{
Expression<Func<string, string, string>> testExpr = (x, y) => x + y;
var result = testExpr.Compile()(""Hello "", ""World!"");
Console.WriteLine(result);
}
}
";
CompileAndVerifyUtil(text, expectedOutput: "Hello World!");
}
[WorkItem(544226, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544226")]
[ConditionalFact(typeof(WindowsDesktopOnly), Reason = "https://github.com/dotnet/roslyn/issues/30160")]
public void BinaryAddOperandTypesDelegate()
{
var text = @"
using System;
using System.Linq;
using System.Linq.Expressions;
public delegate string Del(int i);
class Test
{
public static void Main()
{
Expression<Func<Del, Del, Del>> testExpr = (x, y) => x + y;
Console.WriteLine(testExpr);
}
}";
CompileAndVerifyUtil(text, expectedOutput: "(x, y) => Convert((x + y))");
}
[WorkItem(544187, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544187")]
[Fact]
public void EnumLogicalOperators()
{
var text = @"
using System;
using System.Linq;
using System.Linq.Expressions;
public enum color { Red, Green, Blue };
class Test
{
public static void Main()
{
Expression<Func<color, color, color>> testExpr1 = (x, y) => x & y;
var result1 = testExpr1.Compile()(color.Red, color.Green);
Expression<Func<color, color, color>> testExpr2 = (x, y) => x | y;
var result2 = testExpr2.Compile()(color.Red, color.Green);
Expression<Func<color, color, color>> testExpr3 = (x, y) => x ^ y;
var result3 = testExpr3.Compile()(color.Red, color.Green);
Console.WriteLine(""{0}, {1}, {2}"", result1, result2, result3);
}
}";
CompileAndVerifyUtil(text, expectedOutput: "Red, Green, Green");
}
[WorkItem(544171, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544171")]
[Fact]
public void GenericInterfacePropertyAccess()
{
var text = @"
using System.Linq.Expressions;
using System;
using System.Linq;
class Test
{
public interface ITest<T>
{
T Key { get; }
}
public static void Main()
{
Expression<Func<ITest<int>, int>> e = (var1) => var1.Key;
}
}";
CompileAndVerifyUtil(text, expectedOutput: "");
}
[WorkItem(544171, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544171")]
[Fact]
public void GenericFieldAccess()
{
var text = @"
using System.Linq.Expressions;
using System;
using System.Linq;
class Test
{
public class ITest<T>
{
public T Key;
}
public static void Main()
{
Expression<Func<ITest<int>, int>> e = (var1) => var1.Key;
}
}";
CompileAndVerifyUtil(text, expectedOutput: "");
}
[WorkItem(544185, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544185")]
[Fact]
public void UnaryPlusOperandNullableInt()
{
var text =
@"using System;
using System.Linq.Expressions;
class Test
{
public static void Main()
{
Expression<Func<int?, int?>> e = (x) => +x;
ExpressionVisitor ev = new ExpressionVisitor();
ev.Visit(e);
Console.Write(ev.toStr);
}
}";
string expectedOutput = @"
Lambda:
Type->System.Func`2[System.Nullable`1[System.Int32],System.Nullable`1[System.Int32]]
Parameters->
Parameter:
Type->System.Nullable`1[System.Int32]
Name->x
Body->
Parameter:
Type->System.Nullable`1[System.Int32]
Name->x
";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544213, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544213")]
[Fact]
public void DelegateInvocation()
{
var text =
@"using System;
using System.Linq.Expressions;
class Test
{
delegate int MultFunc(int a, int b);
public static void Main()
{
Expression<Func<MultFunc, int>> testExpr = (mf) => mf(3, 4);
ExpressionVisitor ev = new ExpressionVisitor();
ev.Visit(testExpr);
Console.Write(ev.toStr);
}
}";
string expectedOutput = @"
Lambda:
Type->System.Func`2[Test+MultFunc,System.Int32]
Parameters->
Parameter:
Type->Test+MultFunc
Name->mf
Body->
Invoke:
Type->System.Int32
Arguments->
Constant:
Type->System.Int32
Value->3
Constant:
Type->System.Int32
Value->4
Lambda->
Parameter:
Type->Test+MultFunc
Name->mf
";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544220, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544220")]
[Fact]
public void CoalesceWithLiftedImplicitUDC()
{
var text =
@"using System;
using System.Linq.Expressions;
public class SampClass1
{
public static implicit operator SampClass1(decimal d)
{
return new SampClass1();
}
}
class Test
{
public static void Main()
{
Expression<Func<SampClass1>> testExpr = () => new decimal?(5) ?? new SampClass1();
}
}";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: "");
}
[WorkItem(544222, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544222")]
[ConditionalFact(typeof(WindowsDesktopOnly), Reason = "https://github.com/dotnet/roslyn/issues/30160")]
public void CoalesceWithImplicitUDC()
{
var text =
@"using System;
using System.Linq.Expressions;
public class SampClass1
{
}
public class SampClass2
{
public static implicit operator SampClass1(SampClass2 sc1)
{
return new SampClass1();
}
}
class A
{
static void Main()
{
Expression<Func<SampClass1, SampClass2, SampClass1>> testExpr = (x, y) => x ?? y;
Console.WriteLine(testExpr);
}
}";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: "(x, y) => (x ?? Convert(y))");
}
[WorkItem(546156, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546156"), WorkItem(546157, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546157")]
[Fact]
public void CoalesceWithImplicitUDCFromNullable01()
{
var text =
@"using System;
using System.Linq.Expressions;
public struct CT0
{
}
public struct CT2
{
public static implicit operator CT0(CT2? c)
{
throw new Exception(""this conversion is not needed during execution of this test"");
}
}
public struct CT3
{
public static implicit operator CT0?(CT3? c)
{
return null;
}
}
public class Program
{
static void Main()
{
Func<CT2?, CT0, CT0> lambda1 = (c1, c2) => c1 ?? c2;
Expression<Func<CT2?, CT0, CT0>> e104 = (c1, c2) => c1 ?? c2;
Console.WriteLine(e104.Dump());
Func<CT2?, CT0, CT0> lambda2 = e104.Compile();
Console.WriteLine(lambda1(null, new CT0()));
Console.WriteLine(lambda2(null, new CT0()));
Expression<Func<CT3?, CT0?, CT0?>> e105 = (c1, c2) => c1 ?? c2;
Console.WriteLine(e105.Dump());
}
}";
CompileAndVerifyUtil(
new[] { text, ExpressionTestLibrary },
expectedOutput:
@"Coalesce(Parameter(c1 Type:System.Nullable`1[CT2]) Parameter(c2 Type:CT0) Conversion:Lambda((Parameter(p Type:CT2)) => Convert(Convert(Parameter(p Type:CT2) Lifted LiftedToNull Type:System.Nullable`1[CT2]) Method:[CT0 op_Implicit(System.Nullable`1[CT2])] Type:CT0) ReturnType:CT0 Type:System.Func`2[CT2,CT0]) Type:CT0)
CT0
CT0
Coalesce(Parameter(c1 Type:System.Nullable`1[CT3]) Parameter(c2 Type:System.Nullable`1[CT0]) Conversion:Lambda((Parameter(p Type:CT3)) => Convert(Convert(Parameter(p Type:CT3) Lifted LiftedToNull Type:System.Nullable`1[CT3]) Method:[System.Nullable`1[CT0] op_Implicit(System.Nullable`1[CT3])] Type:System.Nullable`1[CT0]) ReturnType:System.Nullable`1[CT0] Type:System.Func`2[CT3,System.Nullable`1[CT0]]) Type:System.Nullable`1[CT0])");
}
[WorkItem(544248, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544248")]
[Fact]
public void CoalesceWithImplicitUDC2()
{
var text =
@"using System;
using System.Linq.Expressions;
public struct SampStruct
{
public static implicit operator int(SampStruct ss1)
{
return 1;
}
}
public class Test
{
static void Main()
{
Expression<Func<SampStruct?, decimal, decimal>> testExpr = (x, y) => x ?? y;
Console.WriteLine(testExpr.Compile()(new SampStruct(), 5));
Console.WriteLine(testExpr.Dump());
}
}";
CompileAndVerifyUtil(
new[] { text, ExpressionTestLibrary },
expectedOutput:
@"1
Coalesce(Parameter(x Type:System.Nullable`1[SampStruct]) Parameter(y Type:System.Decimal) Conversion:Lambda((Parameter(p Type:SampStruct)) => Convert(Convert(Parameter(p Type:SampStruct) Method:[Int32 op_Implicit(SampStruct)] Type:System.Int32) Method:[System.Decimal op_Implicit(Int32)] Type:System.Decimal) ReturnType:System.Decimal Type:System.Func`2[SampStruct,System.Decimal]) Type:System.Decimal)"
);
}
[Fact, WorkItem(544223, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544223"), WorkItem(546146, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546146")]
public void CoalesceWithLiftedImplicitPDC()
{
var text =
@"using System;
class Test : TestBase
{
public static void Main()
{
Console.WriteLine(ToString<short?, int, long?>((x, y) => x ?? y));
Console.WriteLine(ToString<long?, int?>(x => (int?)x));
Console.WriteLine(ToString<long, int?>(x => (int?)x));
Console.WriteLine(ToString<long?, int>(x => (int)x));
Console.WriteLine(ToString<int, long?>(x => x));
checked
{
Console.WriteLine(ToString<short?, int, long?>((x, y) => x ?? y));
Console.WriteLine(ToString<long?, int?>(x => (int?)x));
Console.WriteLine(ToString<long, int?>(x => (int?)x));
Console.WriteLine(ToString<long?, int>(x => (int)x));
Console.WriteLine(ToString<int, long?>(x => x));
}
}
}";
var expectedOutput =
@"Convert(Convert(Coalesce(Parameter(x Type:System.Nullable`1[System.Int16]) Parameter(y Type:System.Int32) Type:System.Int32) Type:System.Int64) Lifted LiftedToNull Type:System.Nullable`1[System.Int64])
Convert(Parameter(x Type:System.Nullable`1[System.Int64]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])
Convert(Parameter(x Type:System.Int64) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])
Convert(Parameter(x Type:System.Nullable`1[System.Int64]) Lifted Type:System.Int32)
Convert(Convert(Parameter(x Type:System.Int32) Type:System.Int64) Lifted LiftedToNull Type:System.Nullable`1[System.Int64])
ConvertChecked(ConvertChecked(Coalesce(Parameter(x Type:System.Nullable`1[System.Int16]) Parameter(y Type:System.Int32) Type:System.Int32) Type:System.Int64) Lifted LiftedToNull Type:System.Nullable`1[System.Int64])
ConvertChecked(Parameter(x Type:System.Nullable`1[System.Int64]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])
ConvertChecked(Parameter(x Type:System.Int64) Lifted LiftedToNull Type:System.Nullable`1[System.Int32])
ConvertChecked(Parameter(x Type:System.Nullable`1[System.Int64]) Lifted Type:System.Int32)
ConvertChecked(ConvertChecked(Parameter(x Type:System.Int32) Type:System.Int64) Lifted LiftedToNull Type:System.Nullable`1[System.Int64])";
CompileAndVerifyUtil(
new[] { text, ExpressionTestLibrary },
expectedOutput: expectedOutput);
}
[WorkItem(544228, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544228")]
[Fact]
public void NewOfDecimal()
{
var text =
@"using System;
using System.Linq.Expressions;
class Test
{
public static void Main()
{
Expression<Func<decimal>> testExpr = () => new decimal();
ExpressionVisitor ev = new ExpressionVisitor();
ev.Visit(testExpr);
Console.Write(ev.toStr);
}
}";
string expectedOutput = @"
Lambda:
Type->System.Func`1[System.Decimal]
Parameters->
Body->
Constant:
Type->System.Decimal
Value->0
";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544241, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544241")]
[ConditionalFact(typeof(WindowsDesktopOnly), Reason = "https://github.com/dotnet/roslyn/issues/30160")]
public void ArrayIndexTypeLong()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
Expression<Func<string[], long, string>> testExpr = (str, i) => str[i];
Console.WriteLine(testExpr);
}
}";
string expectedOutput = @"(str, i) => str[ConvertChecked(i)]";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544240, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544240")]
[Fact]
public void EventAssignment()
{
var source =
@"using System.Linq.Expressions;
public delegate void A(D d);
public delegate void B();
public class C { public event B B1;}
public class D : C
{
public event B B2;
static void Main()
{
Expression<A> e = x => x.B2 += (B)null;
}
}";
CreateCompilationWithMscorlib40AndSystemCore(source)
.VerifyDiagnostics(
// (11,32): error CS0832: An expression tree may not contain an assignment operator
// Expression<A> e = x => x.B2 += (B)null;
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsAssignment, "x.B2 += (B)null"),
// (5,33): warning CS0067: The event 'C.B1' is never used
// public class C { public event B B1;}
Diagnostic(ErrorCode.WRN_UnreferencedEvent, "B1").WithArguments("C.B1"),
// (8,20): warning CS0067: The event 'D.B2' is never used
// public event B B2;
Diagnostic(ErrorCode.WRN_UnreferencedEvent, "B2").WithArguments("D.B2")
);
}
[WorkItem(544233, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544233")]
[Fact]
public void UnsafePointerAddition()
{
var source =
@"using System.Linq.Expressions;
class Program
{
unsafe delegate int* D1(int* i);
static void Main(string[] args)
{
unsafe
{
Expression<D1> testExpr = (x) => x + 1;
}
}
}";
var c = CreateCompilationWithMscorlib40AndSystemCore(source, options: TestOptions.UnsafeReleaseDll);
c.VerifyDiagnostics(
// (10,46): error CS1944: An expression tree may not contain an unsafe pointer operation
// Expression<D1> testExpr = (x) => x + 1;
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsPointerOp, "x"));
}
[WorkItem(544276, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544276")]
[ConditionalFact(typeof(WindowsDesktopOnly), Reason = "https://github.com/dotnet/roslyn/issues/30160")]
public void UnsafeParamTypeInDelegate()
{
var text = @"
using System;
using System.Linq;
using System.Linq.Expressions;
unsafe public class Test
{
delegate int* UnsafeFunc(int* x);
static int* G(int* x) { return x; }
static void Main()
{
Expression<UnsafeFunc> testExpr = (x) => G(x);
Console.WriteLine(testExpr);
}
}";
string expectedOutput = @"x => G(x)";
CompileAndVerifyUtil(text, options: TestOptions.UnsafeReleaseExe, expectedOutput: TrimExpectedOutput(expectedOutput), verify: Verification.Fails);
}
[WorkItem(544246, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544246")]
[Fact]
public void MethodCallWithParams()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
public static int ModAdd2(params int[] b) { return 0; }
public static int NoParams() { return 0; }
static void Main()
{
Expression<Func<int>> testExpr = () => ModAdd2();
Console.WriteLine(testExpr);
}
}";
// no Array.Empty in the expression tree !!!
// we should not lose the expressiveness of an empty array creation
string expectedOutput = @"() => ModAdd2(new [] {})";
// the IL, however can and should use Array.Empty when calling into ET APIs.
CompileAndVerifyUtil(
text,
expectedOutput: expectedOutput).
VerifyIL("Test.Main",
@"
{
// Code size 66 (0x42)
.maxstack 7
IL_0000: ldnull
IL_0001: ldtoken ""int Test.ModAdd2(params int[])""
IL_0006: call ""System.Reflection.MethodBase System.Reflection.MethodBase.GetMethodFromHandle(System.RuntimeMethodHandle)""
IL_000b: castclass ""System.Reflection.MethodInfo""
IL_0010: ldc.i4.1
IL_0011: newarr ""System.Linq.Expressions.Expression""
IL_0016: dup
IL_0017: ldc.i4.0
IL_0018: ldtoken ""int""
IL_001d: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)""
IL_0022: call ""System.Linq.Expressions.Expression[] System.Array.Empty<System.Linq.Expressions.Expression>()""
IL_0027: call ""System.Linq.Expressions.NewArrayExpression System.Linq.Expressions.Expression.NewArrayInit(System.Type, params System.Linq.Expressions.Expression[])""
IL_002c: stelem.ref
IL_002d: call ""System.Linq.Expressions.MethodCallExpression System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression, System.Reflection.MethodInfo, params System.Linq.Expressions.Expression[])""
IL_0032: call ""System.Linq.Expressions.ParameterExpression[] System.Array.Empty<System.Linq.Expressions.ParameterExpression>()""
IL_0037: call ""System.Linq.Expressions.Expression<System.Func<int>> System.Linq.Expressions.Expression.Lambda<System.Func<int>>(System.Linq.Expressions.Expression, params System.Linq.Expressions.ParameterExpression[])""
IL_003c: call ""void System.Console.WriteLine(object)""
IL_0041: ret
}
");
var comp45 = CreateCompilationWithMscorlib45(
new[] { text, ExpressionTestLibrary },
new[] { ExpressionAssemblyRef },
options: TestOptions.ReleaseExe);
// no use Array.Empty here since it is not available
CompileAndVerify(
comp45,
expectedOutput: expectedOutput).
VerifyIL("Test.Main",
@"
{
// Code size 68 (0x44)
.maxstack 7
IL_0000: ldnull
IL_0001: ldtoken ""int Test.ModAdd2(params int[])""
IL_0006: call ""System.Reflection.MethodBase System.Reflection.MethodBase.GetMethodFromHandle(System.RuntimeMethodHandle)""
IL_000b: castclass ""System.Reflection.MethodInfo""
IL_0010: ldc.i4.1
IL_0011: newarr ""System.Linq.Expressions.Expression""
IL_0016: dup
IL_0017: ldc.i4.0
IL_0018: ldtoken ""int""
IL_001d: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)""
IL_0022: ldc.i4.0
IL_0023: newarr ""System.Linq.Expressions.Expression""
IL_0028: call ""System.Linq.Expressions.NewArrayExpression System.Linq.Expressions.Expression.NewArrayInit(System.Type, params System.Linq.Expressions.Expression[])""
IL_002d: stelem.ref
IL_002e: call ""System.Linq.Expressions.MethodCallExpression System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression, System.Reflection.MethodInfo, params System.Linq.Expressions.Expression[])""
IL_0033: ldc.i4.0
IL_0034: newarr ""System.Linq.Expressions.ParameterExpression""
IL_0039: call ""System.Linq.Expressions.Expression<System.Func<int>> System.Linq.Expressions.Expression.Lambda<System.Func<int>>(System.Linq.Expressions.Expression, params System.Linq.Expressions.ParameterExpression[])""
IL_003e: call ""void System.Console.WriteLine(object)""
IL_0043: ret
}
");
}
[WorkItem(544270, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544270")]
[Fact]
public void MethodCallWithParams2()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
public static int ModAdd2(params int[] b) { return 0; }
static void Main()
{
Expression<Func<int>> testExpr = () => ModAdd2(0, 1);
Console.WriteLine(testExpr);
}
}";
string expectedOutput = @"() => ModAdd2(new [] {0, 1})";
CompileAndVerifyUtil(text, expectedOutput: TrimExpectedOutput(expectedOutput));
}
[Fact]
public void MethodCallWithParams3()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
public static int ModAdd2(int x = 3, int y = 4, params int[] b) { return 0; }
static void Main()
{
Expression<Func<int>> testExpr = () => ModAdd2();
Console.WriteLine(testExpr);
}
}";
CreateCompilationWithMscorlib40AndSystemCore(text)
.VerifyDiagnostics(
// (10,48): error CS0854: An expression tree may not contain a call or invocation that uses optional arguments
// Expression<Func<int>> testExpr = () => ModAdd2();
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsOptionalArgument, "ModAdd2()")
);
}
[WorkItem(544419, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544419")]
[Fact]
public void ExplicitUDC2()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
public static explicit operator int(Test x)
{
return 1;
}
static void Main()
{
Expression<Func<Test, long?>> testExpr = x => (long?)x;
ExpressionVisitor ev = new ExpressionVisitor();
ev.Visit(testExpr);
Console.Write(ev.toStr);
}
}";
var expectedOutput = @"
Lambda:
Type->System.Func`2[Test,System.Nullable`1[System.Int64]]
Parameters->
Parameter:
Type->Test
Name->x
Body->
Convert:
Type->System.Nullable`1[System.Int64]
Method->
IsLifted->True
IsLiftedToNull->True
Operand->
Convert:
Type->System.Int64
Method->
IsLifted->False
IsLiftedToNull->False
Operand->
Convert:
Type->System.Int32
Method->Int32 op_Explicit(Test)
IsLifted->False
IsLiftedToNull->False
Operand->
Parameter:
Type->Test
Name->x
";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544027, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544027")]
[Fact]
public void AnonTypes1()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
Expression<Func<int>> testExpr = () => new { Name = ""Bill"", Salary = 6950.85m, Age = 45 }.Age;
Console.WriteLine(testExpr.Compile()());
}
}";
CompileAndVerifyUtil(text, expectedOutput: "45");
}
[ConditionalFact(typeof(WindowsDesktopOnly), Reason = "https://github.com/dotnet/roslyn/issues/30160")]
public void AnonTypes2()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
Expression<Func<object>> testExpr = () => new { Name = ""Bill"", Salary = 6950.85m, Age = 45 };
Console.WriteLine(testExpr.Dump());
}
}";
CompileAndVerifyUtil(
new[] { text, ExpressionTestLibrary },
expectedOutput: "New([Void .ctor(System.String, System.Decimal, Int32)](Constant(Bill Type:System.String), Constant(6950.85 Type:System.Decimal), Constant(45 Type:System.Int32)){System.String Name System.Decimal Salary Int32 Age} Type:<>f__AnonymousType0`3[System.String,System.Decimal,System.Int32])");
}
[WorkItem(544252, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544252")]
[Fact]
public void EqualsWithOperandsNullableStructAndNull()
{
var text = @"
using System;
using System.Linq.Expressions;
public struct StructType { }
public class Test
{
static void Main()
{
Expression<Func<StructType?, bool>> testExpr = (x) => x == null;
Console.WriteLine(testExpr.Compile()(new StructType()));
}
}";
CompileAndVerifyUtil(text, expectedOutput: "False");
}
[WorkItem(544254, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544254")]
[Fact]
public void GreaterThanUD1()
{
var text = @"
using System;
using System.Linq.Expressions;
struct JoinRec
{
public static bool operator >(JoinRec a, JoinRec b)
{
return true;
}
public static bool operator <(JoinRec a, JoinRec b)
{
return false;
}
}
public class Test
{
static void Main()
{
Expression<Func<JoinRec, JoinRec, bool>> testExpr = (x, y) => x > y;
Console.WriteLine(testExpr.Compile()(new JoinRec(), new JoinRec()));
}
}";
CompileAndVerifyUtil(text, expectedOutput: "True");
}
[WorkItem(544255, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544255")]
[Fact]
public void ExpressionTreeAndOperatorOverloading()
{
var text = @"
using System;
using System.Linq;
using System.Linq.Expressions;
public class R
{
public static int value = 0;
static public R operator +(R r, Expression<Func<R, R>> e)
{
Func<R, R> fun = e.Compile();
return r;
}
static public R operator +(R r1, R r2)
{
return r1;
}
public static int Test2()
{
R.value = 0;
R r = new R();
r = r + ((R c) => (c + ((R d) => (d + d))));
return R.value;
}
}
public class Test
{
static void Main()
{
Console.WriteLine(R.Test2());
}
}";
CompileAndVerifyUtil(text, expectedOutput: "0");
}
[WorkItem(544269, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544269")]
[Fact]
public void CheckedImplicitConversion()
{
var text =
@"using System;
using System.Linq.Expressions;
class Test
{
public static void Main()
{
Expression<Func<int, long, long>> testExpr = (x, y) => checked(x + y);
ExpressionVisitor ev = new ExpressionVisitor();
ev.Visit(testExpr);
Console.Write(ev.toStr);
}
}";
string expectedOutput = @"
Lambda:
Type->System.Func`3[System.Int32,System.Int64,System.Int64]
Parameters->
Parameter:
Type->System.Int32
Name->x
Parameter:
Type->System.Int64
Name->y
Body->
AddChecked:
Type->System.Int64
Method->
IsLifted->False
IsLiftedToNull->False
Left->
ConvertChecked:
Type->System.Int64
Method->
IsLifted->False
IsLiftedToNull->False
Operand->
Parameter:
Type->System.Int32
Name->x
Right->
Parameter:
Type->System.Int64
Name->y
";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(3906, "https://github.com/dotnet/roslyn/issues/3906")]
[Fact]
public void GenericField01()
{
var text =
@"
using System;
public class M
{
public class S<T>
{
public T x;
}
public static object SomeFunc<A>(System.Linq.Expressions.Expression<Func<object, A>> selector)
{ return null; }
public static void CallIt<T>(T t)
{
Func<object, object> goodF = xs => SomeFunc<S<T>>(e => new S<T>());
var z1 = goodF(3);
Func<object, object> badF = xs => SomeFunc<S<T>>(e => new S<T> { x = t });
var z2 = badF(3);
}
public static void Main()
{
CallIt<int>(3);
}
}
";
CompileAndVerifyUtil(
new[] { text, ExpressionTestLibrary },
expectedOutput: "");
}
[WorkItem(3906, "https://github.com/dotnet/roslyn/issues/3906")]
[Fact]
public void GenericProperty01()
{
var text =
@"
using System;
public class M
{
public class S<T>
{
public T x{get; set;}
}
public static object SomeFunc<A>(System.Linq.Expressions.Expression<Func<object, A>> selector)
{ return null; }
public static void CallIt<T>(T t)
{
Func<object, object> goodF = xs => SomeFunc<S<T>>(e => new S<T>());
var z1 = goodF(3);
Func<object, object> badF = xs => SomeFunc<S<T>>(e => new S<T> { x = t });
var z2 = badF(3);
}
public static void Main()
{
CallIt<int>(3);
}
}
";
CompileAndVerifyUtil(
new[] { text, ExpressionTestLibrary },
expectedOutput: "");
}
[WorkItem(544304, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544304")]
[Fact]
public void CheckedEnumAddition()
{
var text =
@"using System;
class Test : TestBase
{
public enum color { Red, Blue, Green };
public static void Main()
{
Check<color, int, color>(
(x, y) => checked(x + y),
""ConvertChecked(AddChecked(ConvertChecked(Parameter(x Type:Test+color) Type:System.Int32) Parameter(y Type:System.Int32) Type:System.Int32) Type:Test+color)"");
}
}";
CompileAndVerifyUtil(
new[] { text, ExpressionTestLibrary },
expectedOutput: "");
}
[WorkItem(544275, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544275")]
[Fact]
public void SizeOf()
{
var text = @"
using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
Expression<Func<int>> testExpr = () => sizeof(int);
Console.WriteLine(testExpr);
}
}";
CompileAndVerifyUtil(text, expectedOutput: "() => 4");
}
[WorkItem(544285, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544285")]
[Fact]
public void ImplicitReferenceConversion()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
Expression<Func<string, object>> testExpr = x => x;
ExpressionVisitor ev = new ExpressionVisitor();
ev.Visit(testExpr);
Console.Write(ev.toStr);
}
}";
string expectedOutput = @"
Lambda:
Type->System.Func`2[System.String,System.Object]
Parameters->
Parameter:
Type->System.String
Name->x
Body->
Parameter:
Type->System.String
Name->x
";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544287, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544287")]
[Fact]
public void ExplicitIdentityConversion()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
Expression<Func<int, int>> testExpr = (num1) => (int)num1;
ExpressionVisitor ev = new ExpressionVisitor();
ev.Visit(testExpr);
Console.Write(ev.toStr);
}
}";
string expectedOutput = @"
Lambda:
Type->System.Func`2[System.Int32,System.Int32]
Parameters->
Parameter:
Type->System.Int32
Name->num1
Body->
Convert:
Type->System.Int32
Method->
IsLifted->False
IsLiftedToNull->False
Operand->
Parameter:
Type->System.Int32
Name->num1
";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544411, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544411")]
[Fact]
public void ExplicitConvIntToNullableInt()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
Expression<Func<int, int?>> testExpr = (num1) => (int?)num1;
ExpressionVisitor ev = new ExpressionVisitor();
ev.Visit(testExpr);
Console.Write(ev.toStr);
}
}";
string expectedOutput = @"
Lambda:
Type->System.Func`2[System.Int32,System.Nullable`1[System.Int32]]
Parameters->
Parameter:
Type->System.Int32
Name->num1
Body->
Convert:
Type->System.Nullable`1[System.Int32]
Method->
IsLifted->True
IsLiftedToNull->True
Operand->
Parameter:
Type->System.Int32
Name->num1
";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544277, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544277")]
[Fact]
public void ConvertExtensionMethodToDelegate()
{
var text =
@"using System;
using System.Linq;
using System.Linq.Expressions;
class A
{
static void Main()
{
Expression<Func<Func<bool>>> x = () => ""ABC"".Any;
Console.WriteLine(x.Compile()()());
}
}";
string expectedOutput = @"True";
CompileAndVerifyUtil(text, expectedOutput: expectedOutput);
}
[WorkItem(544306, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544306")]
[Fact]
public void ExplicitConversionNullToNullableType()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
Expression<Func<short?>> testExpr = () => (short?)null;
ExpressionVisitor ev = new ExpressionVisitor();
ev.Visit(testExpr);
Console.Write(ev.toStr);
}
}";
string expectedOutput = @"
Lambda:
Type->System.Func`1[System.Nullable`1[System.Int16]]
Parameters->
Body->
Convert:
Type->System.Nullable`1[System.Int16]
Method->
IsLifted->True
IsLiftedToNull->True
Operand->
Constant:
Type->System.Object
Value->
";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544295, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544295")]
[Fact]
public void LiftedEquality()
{
var text =
@"using System;
using System.Linq.Expressions;
class Program
{
static void Main()
{
Expression<Action> e = () => Console.WriteLine(default(DateTime) == null);
e.Compile()();
}
}";
string expectedOutput = @"False";
CompileAndVerifyUtil(text, expectedOutput: expectedOutput);
}
[WorkItem(544396, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544396")]
[Fact]
public void UserDefinedOperatorWithPointerType()
{
var text =
@"using System;
using System.Linq.Expressions;
unsafe class Test
{
struct PtrRec
{
public static int operator +(PtrRec a, int* b)
{
return 10;
}
}
public static void Main()
{
int* ptr = null;
Expression<Func<PtrRec, int>> testExpr = (x) => x + ptr;
}
}";
var c = CompileAndVerifyUtil(text,
options: TestOptions.UnsafeReleaseDll,
verify: Verification.Fails);
c.VerifyDiagnostics();
}
[WorkItem(544398, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544398")]
[Fact]
public void BitwiseComplementOnNullableShort()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
Expression<Func<short?, int?>> testExpr = (x) => ~x;
ExpressionVisitor ev = new ExpressionVisitor();
ev.Visit(testExpr);
Console.Write(ev.toStr);
}
}";
string expectedOutput = @"
Lambda:
Type->System.Func`2[System.Nullable`1[System.Int16],System.Nullable`1[System.Int32]]
Parameters->
Parameter:
Type->System.Nullable`1[System.Int16]
Name->x
Body->
Not:
Type->System.Nullable`1[System.Int32]
Method->
IsLifted->True
IsLiftedToNull->True
Operand->
Convert:
Type->System.Nullable`1[System.Int32]
Method->
IsLifted->True
IsLiftedToNull->True
Operand->
Parameter:
Type->System.Nullable`1[System.Int16]
Name->x
";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544400, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544400")]
[Fact]
public void ExpressionTreeWithIterators()
{
var text =
@"using System;
using System.Collections.Generic;
using System.Linq.Expressions;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
IEnumerable<int> enumerable = Generate<object>(5);
IEnumerator<int> enumerator = enumerable.GetEnumerator();
enumerator.MoveNext();
}
public static IEnumerable<int> Generate<T>(int count)
{
Expression<Func<int>> f = () => count;
for (var i = 1; i <= count; i++)
yield return i;
}
}
}";
string expectedOutput = @"";
CompileAndVerifyUtil(text, expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544401, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544401")]
[Fact]
public void AnonMethodInsideExprTree()
{
var text =
@"using System;
using System.Linq.Expressions;
public delegate void D();
public class A
{
static void Main()
{
Expression<Func<D>> f = () => delegate() { };
}
}";
CreateCompilationWithMscorlib40AndSystemCore(text)
.VerifyDiagnostics(
// (9,39): error CS1945: An expression tree may not contain an anonymous method expression
// Expression<Func<D>> f = () => delegate() { };
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsAnonymousMethod, "delegate() { }")
);
}
[WorkItem(544403, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544403")]
[ConditionalFact(typeof(WindowsDesktopOnly), Reason = "https://github.com/dotnet/roslyn/issues/30160")]
public void ConditionalWithOperandTypesObjectArrAndStringArr()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
Expression<Func<bool, object[]>> testExpr = (x) => x ? new object[] { ""Test"" } : new string[] { ""Test"" };
Console.WriteLine(testExpr);
}
}";
string expectedOutput = @"x => IIF(x, new [] {""Test""}, Convert(new [] {""Test""}))";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[Fact, WorkItem(17756, "https://github.com/dotnet/roslyn/issues/17756")]
public void ConditionalWithTrivialCondition()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
S1 v = default(S1);
Expression<Func<int>> testExpr = () => (true ? v : default(S1)).Increment();
Console.WriteLine(testExpr);
}
struct S1
{
public int field;
public int Increment() => field++;
}
}";
string expectedOutput = @"() => value(Test+<>c__DisplayClass0_0).v.Increment()";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544413, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544413")]
[Fact]
public void ExplicitConversionLambdaToExprTree()
{
var text =
@"using System;
using System.Linq.Expressions;
public class Test
{
static void Main()
{
Expression<Func<int, Expression<Func<int, int>>>> testExpr = (y => (Expression<Func<int, int>>)(x => 2 * x));
ExpressionVisitor ev = new ExpressionVisitor();
ev.Visit(testExpr);
Console.Write(ev.toStr);
}
}";
string expectedOutput = @"
Lambda:
Type->System.Func`2[System.Int32,System.Linq.Expressions.Expression`1[System.Func`2[System.Int32,System.Int32]]]
Parameters->
Parameter:
Type->System.Int32
Name->y
Body->
Convert:
Type->System.Linq.Expressions.Expression`1[System.Func`2[System.Int32,System.Int32]]
Method->
IsLifted->False
IsLiftedToNull->False
Operand->
Quote:
Type->System.Linq.Expressions.Expression`1[System.Func`2[System.Int32,System.Int32]]
Method->
IsLifted->False
IsLiftedToNull->False
Operand->
Lambda:
Type->System.Func`2[System.Int32,System.Int32]
Parameters->
Parameter:
Type->System.Int32
Name->x
Body->
Multiply:
Type->System.Int32
Method->
IsLifted->False
IsLiftedToNull->False
Left->
Constant:
Type->System.Int32
Value->2
Right->
Parameter:
Type->System.Int32
Name->x
";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(4593, "https://github.com/dotnet/roslyn/issues/4593")]
[Fact]
public void ExprTreeConvertedNullOnLHS()
{
var text =
@"using System;
using System.Linq.Expressions;
class Program
{
Expression<Func<object>> testExpr = () => null ?? ""hello"";
}";
CreateCompilationWithMscorlib40AndSystemCore(text).VerifyDiagnostics(
// (6,47): error CS0845: An expression tree lambda may not contain a coalescing operator with a null literal left-hand side
// Expression<Func<object>> testExpr = () => null ?? new object();
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsBadCoalesce, "null").WithLocation(6, 47));
}
[WorkItem(4593, "https://github.com/dotnet/roslyn/issues/4593")]
[Fact]
public void ExprTreeNullableInt()
{
var text =
@"using System;
using System.Linq.Expressions;
class Program
{
static void Main()
{
Expression<Func<int?>> testExpr = () => (int?)null ?? (int?)5;
ExpressionVisitor ev = new ExpressionVisitor();
ev.Visit(testExpr);
Console.Write(ev.toStr);
}
}";
var expectedOutput = @"
Lambda:
Type->System.Func`1[System.Nullable`1[System.Int32]]
Parameters->
Body->
Coalesce:
Type->System.Nullable`1[System.Int32]
Method->
IsLifted->False
IsLiftedToNull->False
Left->
Convert:
Type->System.Nullable`1[System.Int32]
Method->
IsLifted->True
IsLiftedToNull->True
Operand->
Constant:
Type->System.Object
Value->
Right->
Convert:
Type->System.Nullable`1[System.Int32]
Method->
IsLifted->True
IsLiftedToNull->True
Operand->
Constant:
Type->System.Int32
Value->5
Conversion->
";
//CreateCompilationWithMscorlibAndSystemCore(text).VerifyDiagnostics();
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544442, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544442")]
[WorkItem(4593, "https://github.com/dotnet/roslyn/issues/4593")]
[Fact]
public void ExprTreeFieldInitCoalesceWithNullOnLHS()
{
var text =
@"using System;
using System.Linq.Expressions;
class Program
{
Expression<Func<object>> testExpr = () => null ?? new object();
}";
CreateCompilationWithMscorlib40AndSystemCore(text).VerifyDiagnostics(
// (6,47): error CS0845: An expression tree lambda may not contain a coalescing operator with a null literal left-hand side
// Expression<Func<object>> testExpr = () => null ?? new object();
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsBadCoalesce, "null"));
}
[Fact]
public void ExprTreePropertyInitCoalesceWithNullOnLHS()
{
var text =
@"using System;
using System.Linq.Expressions;
class C
{
object P { get; } = ((Expression<Func<object>>)(() => null ?? new object())).Compile();
}";
CreateCompilationWithMscorlib40AndSystemCore(text).VerifyDiagnostics(
// (6,47): error CS0845: An expression tree lambda may not contain a coalescing operator with a null literal left-hand side
// Expression<Func<object>> testExpr = () => null ?? new object();
Diagnostic(ErrorCode.ERR_ExpressionTreeContainsBadCoalesce, "null"));
}
[WorkItem(544429, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544429")]
[Fact]
public void ExtraConversionInDelegateCreation()
{
string source = @"using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Collections.Generic;
public class TestClass1
{
public int Func1(string a) { return 2; }
public int Func1(int b) { return 9; }
}
public delegate int Del(string a);
class Program
{
static void Main(string[] args)
{
Expression<Func<TestClass1, Del>> test2 = (tc1) => tc1.Func1;
Console.WriteLine(test2.Dump());
}
}";
string expectedOutput = @"Convert(Call(null.[System.Delegate CreateDelegate(System.Type, System.Object, System.Reflection.MethodInfo)](Constant(Del Type:System.Type), Parameter(tc1 Type:TestClass1), Constant(Int32 Func1(System.String) Type:System.Reflection.MethodInfo)) Type:System.Delegate) Type:Del)";
var comp = CreateEmptyCompilation(
new[] { source, ExpressionTestLibrary },
new[] { MscorlibRef, SystemCoreRef },
TestOptions.ReleaseExe);
CompileAndVerify(comp, expectedOutput: expectedOutput);
//NOTE: different shape of delegate creation in 45+ is bydesign and matches behavior of the with old compiler.
string expectedOutput45 = @"Convert(Call(Constant(Int32 Func1(System.String) Type:System.Reflection.MethodInfo).[System.Delegate CreateDelegate(System.Type, System.Object)](Constant(Del Type:System.Type), Parameter(tc1 Type:TestClass1)) Type:System.Delegate) Type:Del)";
var comp45 = CreateCompilationWithMscorlib45(
new[] { source, ExpressionTestLibrary },
new[] { ExpressionAssemblyRef },
TestOptions.ReleaseExe);
CompileAndVerify(comp45, expectedOutput: expectedOutput45);
}
[WorkItem(544430, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544430")]
[Fact]
public void ExtraConversionInLiftedUserDefined()
{
string source =
@"using System;
using System.Linq.Expressions;
struct RomanNumeral
{
static public implicit operator RomanNumeral(BinaryNumeral binary)
{
return new RomanNumeral();
}
}
struct BinaryNumeral
{
}
class Program
{
static void Main(string[] args)
{
Expression<Func<BinaryNumeral?, RomanNumeral?>> test4 = (expr1) => expr1;
Console.WriteLine(test4.Dump());
}
}";
string expectedOutput = @"Convert(Parameter(expr1 Type:System.Nullable`1[BinaryNumeral]) Lifted LiftedToNull Method:[RomanNumeral op_Implicit(BinaryNumeral)] Type:System.Nullable`1[RomanNumeral])";
CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: expectedOutput);
}
[WorkItem(529420, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/529420")]
[Fact]
public void HalfLiftedLeftShift()
{
string source =
@"using System;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
class Program
{
public static void Main(string[] args)
{
Expression<Func<long?, short, long?>> e = (x, y) => x << y;
Console.WriteLine(e.Dump());
}
}";
string expectedOutput = @"LeftShift(Parameter(x Type:System.Nullable`1[System.Int64]) Convert(Convert(Parameter(y Type:System.Int16) Type:System.Int32) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int64])";
CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: expectedOutput);
}
[WorkItem(544451, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544451")]
[Fact]
public void BinaryOnLiftedByteEnum()
{
string source =
@"using System;
using System.Linq.Expressions;
enum Color : byte { Red, Blue, Green }
class Program : TestBase
{
public static void Main(string[] args)
{
// See comments in 12781 regarding these two cases
// Check<Color?, byte, Color?>((a, b) => a + b,
// ""Convert(Add(Convert(Parameter(a Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Convert(Parameter(b Type:System.Byte) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[Color])"");
// Check<Color, byte?, Color?>((a, b) => a + b,
// ""Convert(Add(Convert(Parameter(a Type:Color) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Convert(Parameter(b Type:System.Nullable`1[System.Byte]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[Color])"");
Check<Color, byte, Color>((a, b) => a + b,
""Convert(Add(Convert(Parameter(a Type:Color) Type:System.Int32) Convert(Parameter(b Type:System.Byte) Type:System.Int32) Type:System.Int32) Type:Color)"");
Check<Color?, byte?, Color?>((a, b) => a + b,
""Convert(Add(Convert(Parameter(a Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Convert(Parameter(b Type:System.Nullable`1[System.Byte]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[Color])"");
Check<byte, Color, Color>((a, b) => a + b,
""Convert(Add(Convert(Parameter(a Type:System.Byte) Type:System.Int32) Convert(Parameter(b Type:Color) Type:System.Int32) Type:System.Int32) Type:Color)"");
Check<byte?, Color?, Color?>((a, b) => a + b,
""Convert(Add(Convert(Parameter(a Type:System.Nullable`1[System.Byte]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Convert(Parameter(b Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[Color])"");
Check<Color, Color, byte>((a, b) => a - b,
""Convert(Subtract(Convert(Parameter(a Type:Color) Type:System.Int32) Convert(Parameter(b Type:Color) Type:System.Int32) Type:System.Int32) Type:System.Byte)"");
Check<Color?, Color?, byte?>((a, b) => a - b,
""Convert(Subtract(Convert(Parameter(a Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Convert(Parameter(b Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Byte])"");
Check<Color, byte, Color>((a, b) => a - b,
""Convert(Subtract(Convert(Parameter(a Type:Color) Type:System.Int32) Convert(Parameter(b Type:System.Byte) Type:System.Int32) Type:System.Int32) Type:Color)"");
Check<Color?, byte?, Color?>((a, b) => a - b,
""Convert(Subtract(Convert(Parameter(a Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Convert(Parameter(b Type:System.Nullable`1[System.Byte]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted LiftedToNull Type:System.Nullable`1[Color])"");
Check<Color, Color, bool>((a, b) => a == b,
""Equal(Convert(Parameter(a Type:Color) Type:System.Int32) Convert(Parameter(b Type:Color) Type:System.Int32) Type:System.Boolean)"");
Check<Color?, Color?, bool>((a, b) => a == b,
""Equal(Convert(Parameter(a Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Convert(Parameter(b Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted Type:System.Boolean)"");
Check<Color, Color, bool>((a, b) => a < b,
""LessThan(Convert(Parameter(a Type:Color) Type:System.Int32) Convert(Parameter(b Type:Color) Type:System.Int32) Type:System.Boolean)"");
Check<Color?, Color?, bool>((a, b) => a < b,
""LessThan(Convert(Parameter(a Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Convert(Parameter(b Type:System.Nullable`1[Color]) Lifted LiftedToNull Type:System.Nullable`1[System.Int32]) Lifted Type:System.Boolean)"");
}
}";
string expectedOutput = "";
CompileAndVerifyUtil(
new[] { source, ExpressionTestLibrary },
expectedOutput: expectedOutput);
}
[WorkItem(544458, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544458")]
[Fact]
public void EmptyCollectionInit()
{
var text =
@"using System;
using System.Collections.Generic;
using System.Linq.Expressions;
public class Parent
{
static void Main()
{
Expression<Func<List<int>>> testExpr = () => new List<int> { };
Console.WriteLine(testExpr.Dump());
}
}";
string expectedOutput =
@"MemberInit(NewExpression: New([Void .ctor()]() Type:System.Collections.Generic.List`1[System.Int32]) Bindings:[] Type:System.Collections.Generic.List`1[System.Int32])";
CompileAndVerifyUtil(
new[] { text, ExpressionTestLibrary },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544485, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544485")]
[Fact]
public void EmptyObjectInitForPredefinedType()
{
var text =
@"using System;
using System.Collections.Generic;
using System.Linq.Expressions;
public class Parent
{
static void Main()
{
Expression<Func<int>> testExpr = () => new int { };
ExpressionVisitor ev = new ExpressionVisitor();
ev.Visit(testExpr);
Console.Write(ev.toStr);
}
}";
string expectedOutput = @"
Lambda:
Type->System.Func`1[System.Int32]
Parameters->
Body->
MemberInit:
Type->System.Int32
NewExpression->
New:
Type->System.Int32
Constructor->
Arguments->
Bindings->
";
CompileAndVerifyUtil(
new[] { text, TreeWalkerLib },
expectedOutput: TrimExpectedOutput(expectedOutput));
}
[WorkItem(544546, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544546")]
[Fact]
public void BadExprTreeLambdaInNSDecl()
{
string source = @"
namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
";
CreateCompilation(source, parseOptions: TestOptions.Regular).VerifyDiagnostics(
// (2,11): error CS7000: Unexpected use of an aliased name
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_UnexpectedAliasedName, "global::").WithLocation(2, 11),
// (2,19): error CS1001: Identifier expected
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_IdentifierExpected, "(").WithLocation(2, 19),
// (2,71): error CS8124: Tuple must contain at least two elements.
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_TupleTooFewElements, ")").WithLocation(2, 71),
// (2,76): error CS1026: ) expected
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_CloseParenExpected, "=>").WithLocation(2, 76),
// (2,79): error CS0116: A namespace cannot directly contain members such as fields or methods
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_NamespaceUnexpected, "B").WithLocation(2, 79),
// (2,19): error CS1514: { expected
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_LbraceExpected, "(").WithLocation(2, 19),
// (2,76): error CS1022: Type or namespace definition, or end-of-file expected
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_EOFExpected, "=>").WithLocation(2, 76),
// (2,81): error CS1022: Type or namespace definition, or end-of-file expected
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_EOFExpected, ")").WithLocation(2, 81),
// (2,93): error CS1002: ; expected
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_SemicolonExpected, "(").WithLocation(2, 93),
// (2,94): error CS8124: Tuple must contain at least two elements.
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_TupleTooFewElements, ")").WithLocation(2, 94),
// (2,95): error CS1022: Type or namespace definition, or end-of-file expected
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_EOFExpected, "{").WithLocation(2, 95),
// (2,84): error CS1520: Method must have a return type
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_MemberNeedsType, "Compile").WithLocation(2, 84),
// (2,84): error CS0501: '<invalid-global-code>.<invalid-global-code>()' must declare a body because it is not marked abstract, extern, or partial
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "Compile").WithArguments(".<invalid-global-code>.<invalid-global-code>()").WithLocation(2, 84)
);
}
[WorkItem(544546, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544546")]
[Fact]
public void BadExprTreeLambdaInNSDeclWithCSharp6()
{
string source = @"
namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
";
CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)).VerifyDiagnostics(
// (2,11): error CS7000: Unexpected use of an aliased name
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_UnexpectedAliasedName, "global::").WithLocation(2, 11),
// (2,19): error CS1001: Identifier expected
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}
Diagnostic(ErrorCode.ERR_IdentifierExpected, "(").WithLocation(2, 19),
// (2,20): error CS8059: Feature 'tuples' is not available in C# 6. Please use language version 7.0 or greater.
// namespace global::((System.Linq.Expressions.Expression<System.Func<B>>)(() => B )).Compile()(){}