diff --git a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs
index 82efcc15fda5e..cd84eff58bdf7 100644
--- a/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/TypeSymbolExtensions.cs
@@ -383,34 +383,58 @@ public static bool IsPointerOrFunctionPointer(this TypeSymbol type)
}
///
- /// return true if the type is constructed from System.Linq.Expressions.Expression`1
+ /// Returns true if the type is constructed from a generic type named "System.Linq.Expressions.Expression"
+ /// with one type parameter.
///
public static bool IsExpressionTree(this TypeSymbol type)
{
return type.IsGenericOrNonGenericExpressionType(out bool isGenericType) && isGenericType;
}
+ ///
+ /// Returns true if the type is a non-generic type named "System.Linq.Expressions.Expression"
+ /// or "System.Linq.Expressions.LambdaExpression".
+ ///
public static bool IsNonGenericExpressionType(this TypeSymbol type)
{
return type.IsGenericOrNonGenericExpressionType(out bool isGenericType) && !isGenericType;
}
+ ///
+ /// Returns true if the type is constructed from a generic type named "System.Linq.Expressions.Expression"
+ /// with one type parameter, or if the type is a non-generic type named "System.Linq.Expressions.Expression"
+ /// or "System.Linq.Expressions.LambdaExpression".
+ ///
public static bool IsGenericOrNonGenericExpressionType(this TypeSymbol _type, out bool isGenericType)
{
- if (_type.OriginalDefinition is NamedTypeSymbol type &&
- type.Name == "Expression" &&
- CheckFullName(type.ContainingSymbol, s_expressionsNamespaceName))
+ if (_type.OriginalDefinition is NamedTypeSymbol type)
{
- if (type.Arity == 0)
- {
- isGenericType = false;
- return true;
- }
- if (type.Arity == 1 &&
- type.MangleName)
+ switch (type.Name)
{
- isGenericType = true;
- return true;
+ case "Expression":
+ if (IsNamespaceName(type.ContainingSymbol, s_expressionsNamespaceName))
+ {
+ if (type.Arity == 0)
+ {
+ isGenericType = false;
+ return true;
+ }
+ if (type.Arity == 1 &&
+ type.MangleName)
+ {
+ isGenericType = true;
+ return true;
+ }
+ }
+ break;
+ case "LambdaExpression":
+ if (IsNamespaceName(type.ContainingSymbol, s_expressionsNamespaceName) &&
+ type.Arity == 0)
+ {
+ isGenericType = false;
+ return true;
+ }
+ break;
}
}
isGenericType = false;
@@ -446,8 +470,13 @@ public static bool IsPossibleArrayGenericInterface(this TypeSymbol type)
private static readonly string[] s_expressionsNamespaceName = { "Expressions", "Linq", MetadataHelpers.SystemString, "" };
- private static bool CheckFullName(Symbol symbol, string[] names)
+ private static bool IsNamespaceName(Symbol symbol, string[] names)
{
+ if (symbol.Kind != SymbolKind.Namespace)
+ {
+ return false;
+ }
+
for (int i = 0; i < names.Length; i++)
{
if ((object)symbol == null || symbol.Name != names[i]) return false;
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/DelegateTypeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/DelegateTypeTests.cs
index c203090dab768..6d9e60dc0d7cf 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/DelegateTypeTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/DelegateTypeTests.cs
@@ -192,6 +192,8 @@ static void Main()
{
System.Linq.Expressions.Expression e = F;
e = (System.Linq.Expressions.Expression)F;
+ System.Linq.Expressions.LambdaExpression l = F;
+ l = (System.Linq.Expressions.LambdaExpression)F;
}
static int F() => 1;
}";
@@ -203,7 +205,13 @@ static void Main()
Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "F").WithArguments("F", "System.Linq.Expressions.Expression").WithLocation(5, 48),
// (6,13): error CS0030: Cannot convert type 'method' to 'Expression'
// e = (System.Linq.Expressions.Expression)F;
- Diagnostic(ErrorCode.ERR_NoExplicitConv, "(System.Linq.Expressions.Expression)F").WithArguments("method", "System.Linq.Expressions.Expression").WithLocation(6, 13));
+ Diagnostic(ErrorCode.ERR_NoExplicitConv, "(System.Linq.Expressions.Expression)F").WithArguments("method", "System.Linq.Expressions.Expression").WithLocation(6, 13),
+ // (7,54): error CS0428: Cannot convert method group 'F' to non-delegate type 'LambdaExpression'. Did you intend to invoke the method?
+ // System.Linq.Expressions.LambdaExpression l = F;
+ Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "F").WithArguments("F", "System.Linq.Expressions.LambdaExpression").WithLocation(7, 54),
+ // (8,13): error CS0030: Cannot convert type 'method' to 'LambdaExpression'
+ // l = (System.Linq.Expressions.LambdaExpression)F;
+ Diagnostic(ErrorCode.ERR_NoExplicitConv, "(System.Linq.Expressions.LambdaExpression)F").WithArguments("method", "System.Linq.Expressions.LambdaExpression").WithLocation(8, 13));
comp = CreateCompilation(source);
comp.VerifyDiagnostics(
@@ -212,7 +220,13 @@ static void Main()
Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "F").WithArguments("F", "System.Linq.Expressions.Expression").WithLocation(5, 48),
// (6,13): error CS0428: Cannot convert method group 'F' to non-delegate type 'Expression'. Did you intend to invoke the method?
// e = (System.Linq.Expressions.Expression)F;
- Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "(System.Linq.Expressions.Expression)F").WithArguments("F", "System.Linq.Expressions.Expression").WithLocation(6, 13));
+ Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "(System.Linq.Expressions.Expression)F").WithArguments("F", "System.Linq.Expressions.Expression").WithLocation(6, 13),
+ // (7,54): error CS0428: Cannot convert method group 'F' to non-delegate type 'LambdaExpression'. Did you intend to invoke the method?
+ // System.Linq.Expressions.LambdaExpression l = F;
+ Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "F").WithArguments("F", "System.Linq.Expressions.LambdaExpression").WithLocation(7, 54),
+ // (8,13): error CS0428: Cannot convert method group 'F' to non-delegate type 'LambdaExpression'. Did you intend to invoke the method?
+ // l = (System.Linq.Expressions.LambdaExpression)F;
+ Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "(System.Linq.Expressions.LambdaExpression)F").WithArguments("F", "System.Linq.Expressions.LambdaExpression").WithLocation(8, 13));
}
[Fact]
@@ -382,6 +396,39 @@ public void LambdaConversions_04()
@"using System;
using System.Linq.Expressions;
class Program
+{
+ static void Main()
+ {
+ LambdaExpression e = () => 1;
+ Report(e);
+ e = (LambdaExpression)(() => 2);
+ Report(e);
+ }
+ static void Report(object obj) => Console.WriteLine(obj.GetType());
+}";
+
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9);
+ comp.VerifyDiagnostics(
+ // (7,30): error CS1660: Cannot convert lambda expression to type 'LambdaExpression' because it is not a delegate type
+ // LambdaExpression e = () => 1;
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "() => 1").WithArguments("lambda expression", "System.Linq.Expressions.LambdaExpression").WithLocation(7, 30),
+ // (9,32): error CS1660: Cannot convert lambda expression to type 'LambdaExpression' because it is not a delegate type
+ // e = (LambdaExpression)(() => 2);
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "() => 2").WithArguments("lambda expression", "System.Linq.Expressions.LambdaExpression").WithLocation(9, 32));
+
+ CompileAndVerify(source, options: TestOptions.ReleaseExe, expectedOutput:
+$@"{s_expressionOfTDelegateTypeName}[System.Func`1[System.Int32]]
+{s_expressionOfTDelegateTypeName}[System.Func`1[System.Int32]]
+");
+ }
+
+ [Fact]
+ public void LambdaConversions_05()
+ {
+ var source =
+@"using System;
+using System.Linq.Expressions;
+class Program
{
static void Main()
{
@@ -389,6 +436,8 @@ static void Main()
object o = (object)(x => x);
Expression e = x => x;
e = (Expression)(x => x);
+ LambdaExpression l = x => x;
+ l = (LambdaExpression)(x => x);
}
}";
@@ -405,7 +454,13 @@ static void Main()
Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "x => x").WithArguments("lambda expression", "System.Linq.Expressions.Expression").WithLocation(9, 24),
// (10,26): error CS1660: Cannot convert lambda expression to type 'Expression' because it is not a delegate type
// e = (Expression)(x => x);
- Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "x => x").WithArguments("lambda expression", "System.Linq.Expressions.Expression").WithLocation(10, 26));
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "x => x").WithArguments("lambda expression", "System.Linq.Expressions.Expression").WithLocation(10, 26),
+ // (11,30): error CS1660: Cannot convert lambda expression to type 'LambdaExpression' because it is not a delegate type
+ // LambdaExpression l = x => x;
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "x => x").WithArguments("lambda expression", "System.Linq.Expressions.LambdaExpression").WithLocation(11, 30),
+ // (12,32): error CS1660: Cannot convert lambda expression to type 'LambdaExpression' because it is not a delegate type
+ // l = (LambdaExpression)(x => x);
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "x => x").WithArguments("lambda expression", "System.Linq.Expressions.LambdaExpression").WithLocation(12, 32));
comp = CreateCompilation(source);
comp.VerifyDiagnostics(
@@ -420,11 +475,56 @@ static void Main()
Diagnostic(ErrorCode.ERR_CannotInferDelegateType, "x => x").WithLocation(9, 24),
// (10,26): error CS8917: The delegate type could not be inferred.
// e = (Expression)(x => x);
- Diagnostic(ErrorCode.ERR_CannotInferDelegateType, "x => x").WithLocation(10, 26));
+ Diagnostic(ErrorCode.ERR_CannotInferDelegateType, "x => x").WithLocation(10, 26),
+ // (11,30): error CS8917: The delegate type could not be inferred.
+ // LambdaExpression l = x => x;
+ Diagnostic(ErrorCode.ERR_CannotInferDelegateType, "x => x").WithLocation(11, 30),
+ // (12,32): error CS8917: The delegate type could not be inferred.
+ // l = (LambdaExpression)(x => x);
+ Diagnostic(ErrorCode.ERR_CannotInferDelegateType, "x => x").WithLocation(12, 32));
}
[Fact]
- public void LambdaConversions_05()
+ public void LambdaConversions_06()
+ {
+ var sourceA =
+@"namespace System.Linq.Expressions
+{
+ public class LambdaExpression
+ {
+ }
+}";
+ var sourceB =
+@"using System;
+using System.Linq.Expressions;
+class Program
+{
+ static void Main()
+ {
+ LambdaExpression> l = () => 1;
+ l = (LambdaExpression>)(() => 2);
+ }
+}";
+
+ var expectedDiagnostics = new[]
+ {
+ // (7,41): error CS1660: Cannot convert lambda expression to type 'LambdaExpression>' because it is not a delegate type
+ // LambdaExpression> l = () => 1;
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "() => 1").WithArguments("lambda expression", "System.Linq.Expressions.LambdaExpression>").WithLocation(7, 41),
+ // (8,43): error CS1660: Cannot convert lambda expression to type 'LambdaExpression>' because it is not a delegate type
+ // l = (LambdaExpression>)(() => 2);
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "() => 2").WithArguments("lambda expression", "System.Linq.Expressions.LambdaExpression>").WithLocation(8, 43)
+ };
+
+ var comp = CreateCompilation(new[] { sourceA, sourceB }, parseOptions: TestOptions.Regular9);
+ comp.VerifyDiagnostics(expectedDiagnostics);
+
+ comp = CreateCompilation(new[] { sourceA, sourceB });
+ comp.VerifyDiagnostics(expectedDiagnostics);
+ }
+
+ [Fact]
+ public void LambdaConversions_07()
{
var source =
@"using System;
@@ -489,6 +589,53 @@ static void Main()
");
}
+ [Fact]
+ public void AnonymousMethod_02()
+ {
+ var source =
+@"using System.Linq.Expressions;
+class Program
+{
+ static void Main()
+ {
+ System.Linq.Expressions.Expression e = delegate () { return 1; };
+ e = (Expression)delegate () { return 2; };
+ LambdaExpression l = delegate () { return 3; };
+ l = (LambdaExpression)delegate () { return 4; };
+ }
+}";
+
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9);
+ comp.VerifyDiagnostics(
+ // (6,48): error CS1660: Cannot convert anonymous method to type 'Expression' because it is not a delegate type
+ // System.Linq.Expressions.Expression e = delegate () { return 1; };
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "delegate () { return 1; }").WithArguments("anonymous method", "System.Linq.Expressions.Expression").WithLocation(6, 48),
+ // (7,25): error CS1660: Cannot convert anonymous method to type 'Expression' because it is not a delegate type
+ // e = (Expression)delegate () { return 2; };
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "delegate () { return 2; }").WithArguments("anonymous method", "System.Linq.Expressions.Expression").WithLocation(7, 25),
+ // (8,30): error CS1660: Cannot convert anonymous method to type 'LambdaExpression' because it is not a delegate type
+ // LambdaExpression l = delegate () { return 3; };
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "delegate () { return 3; }").WithArguments("anonymous method", "System.Linq.Expressions.LambdaExpression").WithLocation(8, 30),
+ // (9,31): error CS1660: Cannot convert anonymous method to type 'LambdaExpression' because it is not a delegate type
+ // l = (LambdaExpression)delegate () { return 4; };
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "delegate () { return 4; }").WithArguments("anonymous method", "System.Linq.Expressions.LambdaExpression").WithLocation(9, 31));
+
+ comp = CreateCompilation(source);
+ comp.VerifyDiagnostics(
+ // (6,48): error CS1946: An anonymous method expression cannot be converted to an expression tree
+ // System.Linq.Expressions.Expression e = delegate () { return 1; };
+ Diagnostic(ErrorCode.ERR_AnonymousMethodToExpressionTree, "delegate () { return 1; }").WithLocation(6, 48),
+ // (7,13): error CS1946: An anonymous method expression cannot be converted to an expression tree
+ // e = (Expression)delegate () { return 2; };
+ Diagnostic(ErrorCode.ERR_AnonymousMethodToExpressionTree, "(Expression)delegate () { return 2; }").WithLocation(7, 13),
+ // (8,30): error CS1946: An anonymous method expression cannot be converted to an expression tree
+ // LambdaExpression l = delegate () { return 3; };
+ Diagnostic(ErrorCode.ERR_AnonymousMethodToExpressionTree, "delegate () { return 3; }").WithLocation(8, 30),
+ // (9,13): error CS1946: An anonymous method expression cannot be converted to an expression tree
+ // l = (LambdaExpression)delegate () { return 4; };
+ Diagnostic(ErrorCode.ERR_AnonymousMethodToExpressionTree, "(LambdaExpression)delegate () { return 4; }").WithLocation(9, 13));
+ }
+
[Fact]
public void DynamicConversion()
{
@@ -2313,6 +2460,111 @@ static void Main()
Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "F").WithArguments("Program.F(T)", "System.Linq.Expressions.Expression", "T", "System.Linq.Expressions.Expression>").WithLocation(6, 17));
}
+ ///
+ /// System.Linq.Expressions as a type rather than a namespace.
+ ///
+ [Fact]
+ public void SystemLinqExpressions_IsType()
+ {
+ var sourceA =
+@"namespace System
+{
+ public class Object { }
+ public abstract class ValueType { }
+ public class String { }
+ public class Type { }
+ public struct Void { }
+ public struct Boolean { }
+ public struct Int32 { }
+ public struct IntPtr { }
+ public abstract class Delegate { }
+ public abstract class MulticastDelegate : Delegate { }
+ public delegate T Func();
+}
+namespace System.Linq
+{
+ public class Expressions
+ {
+ public abstract class Expression { }
+ public abstract class LambdaExpression : Expression { }
+ public sealed class Expression : LambdaExpression { }
+ }
+}";
+ var sourceB =
+@"class Program
+{
+ static void Main()
+ {
+ System.Linq.Expressions.Expression e1 = () => 1;
+ System.Linq.Expressions.LambdaExpression e2 = () => 2;
+ System.Linq.Expressions.Expression> e3 = () => 3;
+ }
+}";
+ var comp = CreateEmptyCompilation(new[] { sourceA, sourceB });
+ comp.VerifyDiagnostics(
+ // (5,49): error CS1660: Cannot convert lambda expression to type 'Expressions.Expression' because it is not a delegate type
+ // System.Linq.Expressions.Expression e1 = () => 1;
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "() => 1").WithArguments("lambda expression", "System.Linq.Expressions.Expression").WithLocation(5, 49),
+ // (6,55): error CS1660: Cannot convert lambda expression to type 'Expressions.LambdaExpression' because it is not a delegate type
+ // System.Linq.Expressions.LambdaExpression e2 = () => 2;
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "() => 2").WithArguments("lambda expression", "System.Linq.Expressions.LambdaExpression").WithLocation(6, 55),
+ // (7,67): error CS1660: Cannot convert lambda expression to type 'Expressions.Expression>' because it is not a delegate type
+ // System.Linq.Expressions.Expression> e3 = () => 3;
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "() => 3").WithArguments("lambda expression", "System.Linq.Expressions.Expression>").WithLocation(7, 67));
+ }
+
+ ///
+ /// System.Linq.Expressions as a nested namespace.
+ ///
+ [Fact]
+ public void SystemLinqExpressions_IsNestedNamespace()
+ {
+ var sourceA =
+@"namespace System
+{
+ public class Object { }
+ public abstract class ValueType { }
+ public class String { }
+ public class Type { }
+ public struct Void { }
+ public struct Boolean { }
+ public struct Int32 { }
+ public struct IntPtr { }
+ public abstract class Delegate { }
+ public abstract class MulticastDelegate : Delegate { }
+ public delegate T Func();
+}
+namespace Root.System.Linq.Expressions
+{
+ public abstract class Expression { }
+ public abstract class LambdaExpression : Expression { }
+ public sealed class Expression : LambdaExpression { }
+}";
+ var sourceB =
+@"using System;
+using Root.System.Linq.Expressions;
+class Program
+{
+ static void Main()
+ {
+ Expression e1 = () => 1;
+ LambdaExpression e2 = () => 2;
+ Expression> e3 = () => 3;
+ }
+}";
+ var comp = CreateEmptyCompilation(new[] { sourceA, sourceB });
+ comp.VerifyDiagnostics(
+ // (7,25): error CS1660: Cannot convert lambda expression to type 'Expression' because it is not a delegate type
+ // Expression e1 = () => 1;
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "() => 1").WithArguments("lambda expression", "Root.System.Linq.Expressions.Expression").WithLocation(7, 25),
+ // (8,31): error CS1660: Cannot convert lambda expression to type 'LambdaExpression' because it is not a delegate type
+ // LambdaExpression e2 = () => 2;
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "() => 2").WithArguments("lambda expression", "Root.System.Linq.Expressions.LambdaExpression").WithLocation(8, 31),
+ // (9,36): error CS1660: Cannot convert lambda expression to type 'Expression>' because it is not a delegate type
+ // Expression> e3 = () => 3;
+ Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "() => 3").WithArguments("lambda expression", "Root.System.Linq.Expressions.Expression>").WithLocation(9, 36));
+ }
+
[WorkItem(4674, "https://github.com/dotnet/csharplang/issues/4674")]
[Fact]
public void OverloadResolution_01()