From 0c0aaf367b4a13bb1f16e6557c94b5599088cbfd Mon Sep 17 00:00:00 2001 From: VSadov Date: Tue, 10 Mar 2015 19:05:19 -0700 Subject: [PATCH] Made use of extension Add methods in Expression lambdas a compiler error. Expression Trees specifically require that element initializer methods are instance methods. Fixes #310 --- .../Portable/CSharpResources.Designer.cs | 9 +++++ .../CSharp/Portable/CSharpResources.resx | 3 ++ .../CSharp/Portable/Errors/ErrorCode.cs | 2 +- .../DiagnosticsPass_ExpressionTrees.cs | 5 +++ ...ObjectOrCollectionInitializerExpression.cs | 6 +-- .../Semantic/Semantics/SemanticErrorTests.cs | 40 +++++++++++++++++++ 6 files changed, 60 insertions(+), 5 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 401c0d1fc31..4aabd42eb6f 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -3922,6 +3922,15 @@ internal class CSharpResources { } } + /// + /// Looks up a localized string similar to An expression tree lambda may not contain an extension collection element initializer.. + /// + internal static string ERR_ExtensionCollectionElementInitializerInExpressionTree { + get { + return ResourceManager.GetString("ERR_ExtensionCollectionElementInitializerInExpressionTree", resourceCulture); + } + } + /// /// Looks up a localized string similar to Extension methods must be defined in a top level static class; {0} is a nested class. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 3c9f16b7fd3..2cc6059eeca 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -4544,6 +4544,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ An expression tree lambda may not contain a dictionary initializer. + + An expression tree lambda may not contain an extension collection element initializer. + nameof operator diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 6d08d05c749..0cef1e4f715 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1289,7 +1289,7 @@ internal enum ErrorCode ERR_NullPropagatingOpInExpressionTree = 8072, WRN_NubExprIsConstBool2 = 8073, ERR_DictionaryInitializerInExpressionTree = 8074, - // available: 8075, + ERR_ExtensionCollectionElementInitializerInExpressionTree = 8075, ERR_UnclosedExpressionHole = 8076, ERR_SingleLineCommentInExpressionHole = 8077, ERR_InsufficientStack = 8078, diff --git a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs index 0aa25828a94..761857b6783 100644 --- a/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs +++ b/src/Compilers/CSharp/Portable/Lowering/DiagnosticsPass_ExpressionTrees.cs @@ -289,6 +289,11 @@ public override BoundNode VisitCall(BoundCall node) public override BoundNode VisitCollectionElementInitializer(BoundCollectionElementInitializer node) { + if (_inExpressionLambda && node.AddMethod.IsStatic) + { + Error(ErrorCode.ERR_ExtensionCollectionElementInitializerInExpressionTree, node); + } + VisitCall(node.AddMethod, null, node.Arguments, default(ImmutableArray), default(ImmutableArray), node.Expanded, node); return base.VisitCollectionElementInitializer(node); } diff --git a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ObjectOrCollectionInitializerExpression.cs b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ObjectOrCollectionInitializerExpression.cs index 53079e07674..e48afaf507e 100644 --- a/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ObjectOrCollectionInitializerExpression.cs +++ b/src/Compilers/CSharp/Portable/Lowering/LocalRewriter/LocalRewriter_ObjectOrCollectionInitializerExpression.cs @@ -163,10 +163,8 @@ private BoundExpression MakeCollectionInitializer(BoundExpression rewrittenRecei // the add method was found as an extension method. Replace the implicit receiver (first argument) with the rewritten receiver. Debug.Assert(addMethod.IsStatic && addMethod.IsExtensionMethod); Debug.Assert(rewrittenArguments[0].Kind == BoundKind.ImplicitReceiver); - var newArgs = ArrayBuilder.GetInstance(); - newArgs.AddRange(rewrittenArguments); - newArgs[0] = rewrittenReceiver; - rewrittenArguments = newArgs.ToImmutableAndFree(); + Debug.Assert(!_inExpressionLambda, "Expression trees do not support extension Add"); + rewrittenArguments = rewrittenArguments.SetItem(0, rewrittenReceiver); rewrittenReceiver = null; } diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs index 41c75052e86..730e350d810 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs @@ -22237,6 +22237,46 @@ public void DictionaryInitializerInExprLambda1() { var text = @" using System; +using System.Collections.Generic; +using System.Linq.Expressions; + +namespace ConsoleApplication31 +{ + class Program + { + static void Main(string[] args) + { + var o = new Foo(); + var x = o.E.Compile()().Pop(); + System.Console.WriteLine(x); + } + } + + static class StackExtensions + { + public static void Add(this Stack s, T x) => s.Push(x); + } + + class Foo + { + public Expression>> E = () => new Stack { 42 }; + } +} + +"; + CreateCompilationWithMscorlib45(text, new[] { SystemRef_v4_0_30319_17929, SystemCoreRef_v4_0_30319_17929, CSharpRef }).VerifyDiagnostics( + // (25,72): error CS8075: An expression tree lambda may not contain an extension collection element initializer. + // public Expression>> E = () => new Stack { 42 }; + Diagnostic(ErrorCode.ERR_ExtensionCollectionElementInitializerInExpressionTree, "42").WithLocation(25, 72) + ); + } + + [WorkItem(310, "https://github.com/dotnet/roslyn/issues/310")] + [Fact] + public void ExtensionElementInitializerInExpressionLambda() + { + var text = @" +using System; using System.Collections; using System.Linq.Expressions; class C -- GitLab