From 8963779ed97b48b13139e11e3932848121f16f61 Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Fri, 11 Oct 2024 14:48:05 -0700 Subject: [PATCH 1/2] VB: Do not use overload resolution for expression tree conversion Related to #74275. --- .../ExpressionLambdaRewriter.cs | 2 +- .../Core/Portable/WellKnownMember.cs | 5 +- .../Core/Portable/WellKnownMembers.cs | 34 ++- src/Compilers/Core/Portable/WellKnownTypes.cs | 2 + .../BoundUserDefinedBinaryOperator.vb | 2 + .../ExpressionLambdaRewriter.vb | 182 ++++++------ ...ExpressionLambdaRewriter_BinaryOperator.vb | 259 ++++++++++++------ ...sionLambdaRewriter_ConditionalExpresion.vb | 13 +- .../ExpressionLambdaRewriter_Conversion.vb | 40 ++- .../ExpressionLambdaRewriter_UnaryOperator.vb | 51 ++-- .../Emit/ExpressionTrees/CodeGenExprLambda.vb | 107 +++++++- 11 files changed, 456 insertions(+), 241 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ExpressionLambdaRewriter.cs b/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ExpressionLambdaRewriter.cs index e5dd561f3b80f..63117b59389ff 100644 --- a/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ExpressionLambdaRewriter.cs +++ b/src/Compilers/CSharp/Portable/Lowering/ClosureConversion/ExpressionLambdaRewriter.cs @@ -1075,7 +1075,7 @@ private BoundExpression VisitObjectCreationExpressionInternal(BoundObjectCreatio } else { - return _bound.StaticCall(WellKnownMember.System_Linq_Expressions_Expression__New_ConstructorInfo_Expressions, ctor, args); + return _bound.StaticCall(WellKnownMember.System_Linq_Expressions_Expression__New_ConstructorInfo_IEnumerableExpressions, ctor, args); } } diff --git a/src/Compilers/Core/Portable/WellKnownMember.cs b/src/Compilers/Core/Portable/WellKnownMember.cs index 09ad7a3ab9216..8970c644528ed 100644 --- a/src/Compilers/Core/Portable/WellKnownMember.cs +++ b/src/Compilers/Core/Portable/WellKnownMember.cs @@ -637,7 +637,8 @@ internal enum WellKnownMember System_Linq_Expressions_Expression__Not_Expression, System_Linq_Expressions_Expression__Not_Expression_MethodInfo, System_Linq_Expressions_Expression__New_Type, - System_Linq_Expressions_Expression__New_ConstructorInfo_Expressions, + System_Linq_Expressions_Expression__New_ConstructorInfo_IEnumerableExpressions, + System_Linq_Expressions_Expression__New_ConstructorInfo_ArrayExpressions, System_Linq_Expressions_Expression__New_ConstructorInfo_Expressions_MemberInfos, System_Linq_Expressions_Expression__Property, System_Linq_Expressions_Expression__MemberBind_MemberInfo, @@ -710,6 +711,8 @@ internal enum WellKnownMember System_Linq_Expressions_Expression__GreaterThan_MethodInfo, System_Linq_Expressions_Expression__GreaterThanOrEqual, System_Linq_Expressions_Expression__GreaterThanOrEqual_MethodInfo, + System_Linq_Expressions_Expression__Default, + System_Linq_Expressions_Expression__Power_MethodInfo, Count, diff --git a/src/Compilers/Core/Portable/WellKnownMembers.cs b/src/Compilers/Core/Portable/WellKnownMembers.cs index 567bb484d2876..4bf9c0c9905f6 100644 --- a/src/Compilers/Core/Portable/WellKnownMembers.cs +++ b/src/Compilers/Core/Portable/WellKnownMembers.cs @@ -4447,7 +4447,7 @@ static WellKnownMembers() (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Linq_Expressions_NewExpression - WellKnownType.ExtSentinel), // Return Type (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Type, - // System_Linq_Expressions_Expression__New_ConstructorInfo_Expressions, + // System_Linq_Expressions_Expression__New_ConstructorInfo_IEnumerableExpressions, (byte)(MemberFlags.Method | MemberFlags.Static), // Flags (byte)WellKnownType.System_Linq_Expressions_Expression, // DeclaringTypeId 0, // Arity @@ -4459,6 +4459,15 @@ static WellKnownMembers() 1, (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Linq_Expressions_Expression, + // System_Linq_Expressions_Expression__New_ConstructorInfo_ArrayExpressions, + (byte)(MemberFlags.Method | MemberFlags.Static), // Flags + (byte)WellKnownType.System_Linq_Expressions_Expression, // DeclaringTypeId + 0, // Arity + 2, // Method Signature + (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Linq_Expressions_NewExpression - WellKnownType.ExtSentinel), // Return Type + (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Reflection_ConstructorInfo, + (byte)SignatureTypeCode.SZArray, (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Linq_Expressions_Expression, + // System_Linq_Expressions_Expression__New_ConstructorInfo_Expressions_MemberInfos, (byte)(MemberFlags.Method | MemberFlags.Static), // Flags (byte)WellKnownType.System_Linq_Expressions_Expression, // DeclaringTypeId @@ -5143,6 +5152,24 @@ static WellKnownMembers() (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Linq_Expressions_Expression, (byte)SignatureTypeCode.TypeHandle, (byte)SpecialType.System_Boolean, (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Reflection_MethodInfo, + + // System_Linq_Expressions_Expression__Default + (byte)(MemberFlags.Method | MemberFlags.Static), // Flags + (byte)WellKnownType.System_Linq_Expressions_Expression, // DeclaringTypeId + 0, // Arity + 1, // Method Signature + (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Linq_Expressions_DefaultExpression - WellKnownType.ExtSentinel), // Return Type + (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Type, + + // System_Linq_Expressions_Expression__Power_MethodInfo, + (byte)(MemberFlags.Method | MemberFlags.Static), // Flags + (byte)WellKnownType.System_Linq_Expressions_Expression, // DeclaringTypeId + 0, // Arity + 3, // Method Signature + (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.ExtSentinel, (byte)(WellKnownType.System_Linq_Expressions_BinaryExpression - WellKnownType.ExtSentinel), // Return Type + (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Linq_Expressions_Expression, + (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Linq_Expressions_Expression, + (byte)SignatureTypeCode.TypeHandle, (byte)WellKnownType.System_Reflection_MethodInfo, }; string[] allNames = new string[(int)WellKnownMember.Count] @@ -5690,7 +5717,8 @@ static WellKnownMembers() "Not", // System_Linq_Expressions_Expression__Not_Expression "Not", // System_Linq_Expressions_Expression__Not_Expression_MethodInfo "New", // System_Linq_Expressions_Expression__New_Type - "New", // System_Linq_Expressions_Expression__New_ConstructorInfo_Expressions + "New", // System_Linq_Expressions_Expression__New_ConstructorInfo_IEnumerableExpressions + "New", // System_Linq_Expressions_Expression__New_ConstructorInfo_ArrayExpressions "New", // System_Linq_Expressions_Expression__New_ConstructorInfo_Expressions_MemberInfos "Property", // System_Linq_Expressions_Expression__Property "MemberBind", // System_Linq_Expressions_Expression__MemberBind_MemberInfo @@ -5763,6 +5791,8 @@ static WellKnownMembers() "GreaterThan", // System_Linq_Expressions_Expression__GreaterThan_MethodInfo, "GreaterThanOrEqual", // System_Linq_Expressions_Expression__GreaterThanOrEqual, "GreaterThanOrEqual", // System_Linq_Expressions_Expression__GreaterThanOrEqual_MethodInfo, + "Default", // System_Linq_Expressions_Expression__Default + "Power", // System_Linq_Expressions_Expression__Power_MethodInfo, }; s_descriptors = MemberDescriptor.InitializeFromStream(new System.IO.MemoryStream(initializationBytes, writable: false), allNames); diff --git a/src/Compilers/Core/Portable/WellKnownTypes.cs b/src/Compilers/Core/Portable/WellKnownTypes.cs index 85298129ff45a..7c3f4f5fc301c 100644 --- a/src/Compilers/Core/Portable/WellKnownTypes.cs +++ b/src/Compilers/Core/Portable/WellKnownTypes.cs @@ -353,6 +353,7 @@ internal enum WellKnownType System_Linq_Expressions_ConditionalExpression, System_Linq_Expressions_InvocationExpression, System_Linq_Expressions_NewArrayExpression, + System_Linq_Expressions_DefaultExpression, NextAvailable, // Remember to update the AllWellKnownTypes tests when making changes here @@ -693,6 +694,7 @@ internal static class WellKnownTypes "System.Linq.Expressions.ConditionalExpression", "System.Linq.Expressions.InvocationExpression", "System.Linq.Expressions.NewArrayExpression", + "System.Linq.Expressions.DefaultExpression", }; private static readonly Dictionary s_nameToTypeIdMap = new Dictionary((int)Count); diff --git a/src/Compilers/VisualBasic/Portable/BoundTree/BoundUserDefinedBinaryOperator.vb b/src/Compilers/VisualBasic/Portable/BoundTree/BoundUserDefinedBinaryOperator.vb index 0de446ef64ee5..a89f70e088e04 100644 --- a/src/Compilers/VisualBasic/Portable/BoundTree/BoundUserDefinedBinaryOperator.vb +++ b/src/Compilers/VisualBasic/Portable/BoundTree/BoundUserDefinedBinaryOperator.vb @@ -33,6 +33,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Debug.Assert(Type.Equals(UnderlyingExpression.Type)) Debug.Assert((OperatorKind And BinaryOperatorKind.UserDefined) <> 0) Debug.Assert(UnderlyingExpression.Kind = BoundKind.BadExpression OrElse UnderlyingExpression.Kind = BoundKind.Call) + Debug.Assert((OperatorKind And BinaryOperatorKind.OpMask) <> BinaryOperatorKind.AndAlso) + Debug.Assert((OperatorKind And BinaryOperatorKind.OpMask) <> BinaryOperatorKind.OrElse) If UnderlyingExpression.Kind = BoundKind.Call Then Dim underlyingCall = DirectCast(UnderlyingExpression, BoundCall) diff --git a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter.vb b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter.vb index 4cbdb9822001b..369d907d0cab2 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter.vb @@ -194,6 +194,11 @@ lSelect: _factory.Syntax = node.Syntax Dim result = VisitInternal(node) _factory.Syntax = old + + If result.Type Is _expressionType Then + Return result + End If + Return _factory.Convert(_expressionType, result) End Function @@ -333,7 +338,7 @@ lSelect: parameters.Add(parameterReference) _parameterMap(p) = parameterReference - Dim parameter As BoundExpression = ConvertRuntimeHelperToExpressionTree("Parameter", + Dim parameter As BoundExpression = ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__Parameter, _factory.[Typeof]( p.Type.InternalSubstituteTypeParameters(_typeMap).Type, _factory.WellKnownType(WellKnownType.System_Type)), @@ -352,7 +357,7 @@ lSelect: Dim result = _factory.Sequence(locals.ToImmutableAndFree(), initializers.ToImmutableAndFree(), ConvertRuntimeHelperToExpressionTree( - "Lambda", + WellKnownMember.System_Linq_Expressions_Expression__Lambda_OfTDelegate, ImmutableArray.Create(Of TypeSymbol)(delegateType), translatedBody, _factory.Array(parameterExpressionType, parameters.ToImmutableAndFree()))) @@ -384,11 +389,11 @@ lSelect: End If If method.MethodKind = MethodKind.DelegateInvoke Then - Return ConvertRuntimeHelperToExpressionTree("Invoke", + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__Invoke, receiverOpt, ConvertArgumentsIntoArray(node.Arguments)) Else - Return ConvertRuntimeHelperToExpressionTree("Call", + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__Call, If(method.IsShared, _factory.Null(_expressionType), receiverOpt), _factory.MethodInfo(method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo)), ConvertArgumentsIntoArray(node.Arguments)) End If @@ -402,7 +407,7 @@ lSelect: Dim rewrittenReceiver As BoundExpression = Nothing If fieldIsShared Then - rewrittenReceiver = _factory.Null() + rewrittenReceiver = _factory.Null(_expressionType) Else Debug.Assert(origReceiverOpt IsNot Nothing) If origReceiverOpt.Kind = BoundKind.MyBaseReference Then @@ -415,7 +420,10 @@ lSelect: End If End If - Return ConvertRuntimeHelperToExpressionTree("Field", rewrittenReceiver, _factory.FieldInfo(field)) + Return ConvertRuntimeHelperToExpressionTree( + WellKnownMember.System_Linq_Expressions_Expression__Field, + rewrittenReceiver, + _factory.FieldInfo(field)) End Function Private Function VisitPropertyAccess(node As BoundPropertyAccess) As BoundExpression @@ -426,7 +434,7 @@ lSelect: Dim rewrittenReceiver As BoundExpression = Nothing If propertyIsShared Then - rewrittenReceiver = _factory.Null() + rewrittenReceiver = _factory.Null(_expressionType) Else Debug.Assert(origReceiverOpt IsNot Nothing) Debug.Assert(origReceiverOpt.Kind <> BoundKind.MyBaseReference AndAlso origReceiverOpt.Kind <> BoundKind.MyClassReference) @@ -434,7 +442,10 @@ lSelect: End If Dim getMethod As MethodSymbol = [property].GetMostDerivedGetMethod() - Return ConvertRuntimeHelperToExpressionTree("Property", rewrittenReceiver, _factory.MethodInfo(getMethod, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) + Return ConvertRuntimeHelperToExpressionTree( + WellKnownMember.System_Linq_Expressions_Expression__Property, + rewrittenReceiver, + _factory.MethodInfo(getMethod, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) End Function Private Function VisitLambda(node As BoundLambda) As BoundExpression @@ -519,9 +530,9 @@ lSelect: Dim arg = node.Indices(0) Dim index = Visit(arg) Debug.Assert(arg.Type Is Me.Int32Type) - Return ConvertRuntimeHelperToExpressionTree("ArrayIndex", array, index) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__ArrayIndex_Expression_Expression, array, index) Else - Return ConvertRuntimeHelperToExpressionTree("ArrayIndex", array, BuildIndices(node.Indices)) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__ArrayIndex_Expression_Expressions, array, BuildIndices(node.Indices)) End If End Function @@ -545,7 +556,10 @@ lSelect: End Function Private Function VisitNewT(node As BoundNewT) As BoundExpression - Return VisitObjectCreationContinued(ConvertRuntimeHelperToExpressionTree("New", _factory.[Typeof](node.Type, _factory.WellKnownType(WellKnownType.System_Type))), node.InitializerOpt) + Return VisitObjectCreationContinued( + ConvertRuntimeHelperToExpressionTree( + WellKnownMember.System_Linq_Expressions_Expression__New_Type, + _factory.[Typeof](node.Type, _factory.WellKnownType(WellKnownType.System_Type))), node.InitializerOpt) End Function Private Function VisitObjectCreationContinued(creation As BoundExpression, initializerOpt As BoundExpression) As BoundExpression @@ -555,11 +569,11 @@ lSelect: Select Case initializerOpt.Kind Case BoundKind.ObjectInitializerExpression - Return ConvertRuntimeHelperToExpressionTree("MemberInit", creation, + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__MemberInit, creation, VisitObjectInitializer(DirectCast(initializerOpt, BoundObjectInitializerExpression))) Case BoundKind.CollectionInitializerExpression - Return ConvertRuntimeHelperToExpressionTree("ListInit", creation, + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__ListInit, creation, VisitCollectionInitializer(DirectCast(initializerOpt, BoundCollectionInitializerExpression))) Case Else @@ -603,10 +617,17 @@ lSelect: Debug.Assert(leftSymbol.Kind = SymbolKind.Field OrElse leftSymbol.Kind = SymbolKind.Property) Dim memberRef As BoundExpression = If(leftSymbol.Kind = SymbolKind.Field, - Me._factory.FieldInfo(DirectCast(leftSymbol, FieldSymbol)), + _factory.Convert(MemberInfoType, Me._factory.FieldInfo(DirectCast(leftSymbol, FieldSymbol))), Me._factory.MethodInfo((DirectCast(leftSymbol, PropertySymbol)).SetMethod, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) - newInitializers(i) = _factory.Convert(MemberBindingType, ConvertRuntimeHelperToExpressionTree("Bind", memberRef, Visit(right))) + newInitializers(i) = _factory.Convert( + MemberBindingType, + ConvertRuntimeHelperToExpressionTree( + If(leftSymbol.Kind = SymbolKind.Field, + WellKnownMember.System_Linq_Expressions_Expression__Bind_MemberInfo, + WellKnownMember.System_Linq_Expressions_Expression__Bind_MethodInfo), + memberRef, + Visit(right))) Next Return _factory.Array(MemberBindingType, newInitializers.AsImmutableOrNull()) @@ -630,7 +651,7 @@ lSelect: newInitializers(i) = _factory.Convert( ElementInitType, ConvertRuntimeHelperToExpressionTree( - "ElementInit", + WellKnownMember.System_Linq_Expressions_Expression__ElementInit, _factory.MethodInfo([call].Method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo)), ConvertArgumentsIntoArray(If([call].Method.IsShared AndAlso [call].Method.IsExtensionMethod, [call].Arguments.RemoveAt(0), @@ -649,7 +670,8 @@ lSelect: (node.Arguments.Length = 0 AndAlso Not node.Type.IsStructureType() OrElse node.ConstructorOpt.IsDefaultValueTypeConstructor()) Then - Return ConvertRuntimeHelperToExpressionTree("New", _factory.[Typeof](node.Type, _factory.WellKnownType(WellKnownType.System_Type))) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__New_Type, + _factory.[Typeof](node.Type, _factory.WellKnownType(WellKnownType.System_Type))) End If Dim ctor = _factory.ConstructorInfo(node.ConstructorOpt) @@ -665,9 +687,13 @@ lSelect: methodInfos(i) = Me._factory.Convert(Me.MemberInfoType, Me._factory.MethodInfo(properties(i).GetMethod, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) Next - Return ConvertRuntimeHelperToExpressionTree("New", ctor, args, Me._factory.Array(Me.MemberInfoType, methodInfos.AsImmutableOrNull())) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__New_ConstructorInfo_Expressions_MemberInfos, + ctor, + _factory.Convert(_factory.SpecialType(SpecialType.System_Collections_Generic_IEnumerable_T).Construct(_expressionType), + args), + Me._factory.Array(Me.MemberInfoType, methodInfos.AsImmutableOrNull())) Else - Return ConvertRuntimeHelperToExpressionTree("New", ctor, args) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__New_ConstructorInfo_ArrayExpressions, ctor, args) End If End Function @@ -701,7 +727,7 @@ lSelect: suppressObjectClone:=True, type:=resultType)) Else - Return ConvertRuntimeHelperToExpressionTree("ArrayLength", Visit(node.Expression)) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__ArrayLength, Visit(node.Expression)) End If End Function @@ -711,9 +737,9 @@ lSelect: Dim initializer As BoundArrayInitialization = node.InitializerOpt If initializer IsNot Nothing AndAlso Not initializer.Initializers.IsEmpty Then Debug.Assert(arrayType.IsSZArray, "Not SZArray should be addressed in DiagnosticsPass") - Return ConvertRuntimeHelperToExpressionTree("NewArrayInit", boundType, ConvertArgumentsIntoArray(node.InitializerOpt.Initializers)) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__NewArrayInit, boundType, ConvertArgumentsIntoArray(node.InitializerOpt.Initializers)) Else - Return ConvertRuntimeHelperToExpressionTree("NewArrayBounds", boundType, ConvertArgumentsIntoArray(node.Bounds)) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__NewArrayBounds, boundType, ConvertArgumentsIntoArray(node.Bounds)) End If End Function @@ -726,7 +752,7 @@ lSelect: End Function Private Function VisitTypeOf(node As BoundTypeOf) As BoundExpression - Return ConvertRuntimeHelperToExpressionTree("TypeIs", Visit(node.Operand), _factory.[Typeof](node.TargetType, _factory.WellKnownType(WellKnownType.System_Type))) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__TypeIs, Visit(node.Operand), _factory.[Typeof](node.TargetType, _factory.WellKnownType(WellKnownType.System_Type))) End Function #End Region @@ -735,32 +761,40 @@ lSelect: ' Emit a call node Private Function [Call](receiver As BoundExpression, method As MethodSymbol, ParamArray params As BoundExpression()) As BoundExpression - Dim factoryArgs(0 To params.Length + 1) As BoundExpression - factoryArgs(0) = receiver - factoryArgs(1) = _factory.MethodInfo(method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo)) - Array.Copy(params, 0, factoryArgs, 2, params.Length) - Return ConvertRuntimeHelperToExpressionTree("Call", factoryArgs) + Return _factory.Convert( + _expressionType, + ConvertRuntimeHelperToExpressionTree( + WellKnownMember.System_Linq_Expressions_Expression__Call, + receiver, + _factory.MethodInfo(method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo)), + _factory.Array(_expressionType, params))) End Function ' Emit a Default node for a specific type Private Function [Default](type As TypeSymbol) As BoundExpression - Return ConvertRuntimeHelperToExpressionTree("Default", _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type))) + Return _factory.Convert( + _expressionType, + ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__Default, _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type)))) End Function ' Emit a New node to a specific type with a helper constructor and one argument Private Function [New](helper As SpecialMember, argument As BoundExpression) As BoundExpression - Return ConvertRuntimeHelperToExpressionTree("New", _factory.ConstructorInfo(helper), argument) + Return _factory.Convert( + _expressionType, + ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__New_ConstructorInfo_ArrayExpressions, + _factory.ConstructorInfo(helper), + _factory.Array(_expressionType, argument))) End Function ' Emit a negate node Private Function Negate(expr As BoundExpression) As BoundExpression - Return ConvertRuntimeHelperToExpressionTree("Negate", expr) + Return _factory.Convert(_expressionType, ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__Negate_Expression, expr)) End Function Private Function InitWithParameterlessValueTypeConstructor(type As TypeSymbol) As BoundExpression ' The "New" overload without a methodInfo automatically generates the parameterless constructor for us. Debug.Assert(type.IsValueType) - Return ConvertRuntimeHelperToExpressionTree("New", _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type))) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__New_Type, _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type))) End Function Private Function IsIntegralType(type As TypeSymbol) As Boolean @@ -776,91 +810,41 @@ lSelect: End Function Private Function CreateLiteralExpression(node As BoundExpression, type As TypeSymbol) As BoundExpression - Return ConvertRuntimeHelperToExpressionTree("Constant", _factory.Convert(Me.ObjectType, node), _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type))) + Return _factory.Convert( + _expressionType, + ConvertRuntimeHelperToExpressionTree( + WellKnownMember.System_Linq_Expressions_Expression__Constant, + _factory.Convert(Me.ObjectType, node), _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type)))) End Function ''' ''' Create an Expression Tree Node with the given name and arguments ''' - Private Function ConvertRuntimeHelperToExpressionTree(helperMethodName As String, + Private Function ConvertRuntimeHelperToExpressionTree(helperMethod As WellKnownMember, ParamArray arguments As BoundExpression()) As BoundExpression - - Return ConvertRuntimeHelperToExpressionTree(helperMethodName, ImmutableArray(Of TypeSymbol).Empty, arguments) + Return ConvertRuntimeHelperToExpressionTree(helperMethod, ImmutableArray(Of TypeSymbol).Empty, arguments) End Function ''' ''' Create an Expression node with the given name, type arguments, and arguments. ''' - Private Function ConvertRuntimeHelperToExpressionTree(helperMethodName As String, + Private Function ConvertRuntimeHelperToExpressionTree(helperMethod As WellKnownMember, typeArgs As ImmutableArray(Of TypeSymbol), ParamArray arguments As BoundExpression()) As BoundExpression - Dim anyArgumentsWithErrors = False - - ' Check if we have any bad arguments. - For Each a In arguments - If a.HasErrors Then - anyArgumentsWithErrors = True - End If - Next - - ' Get the method group - Dim methodGroup = GetExprFactoryMethodGroup(helperMethodName, typeArgs) + Dim helper As MethodSymbol = _factory.WellKnownMember(Of MethodSymbol)(helperMethod) - If methodGroup Is Nothing OrElse anyArgumentsWithErrors Then - Return _factory.BadExpression(arguments) - End If - - ' Do overload resolution and bind an invocation of the method. - Dim result = _binder.BindInvocationExpression(_factory.Syntax, - _factory.Syntax, - TypeCharacter.None, - methodGroup, - ImmutableArray.Create(Of BoundExpression)(arguments), - argumentNames:=Nothing, - diagnostics:=Diagnostics, - callerInfoOpt:=Nothing) - - Return result - End Function - - ''' - ''' Gets the method group for a given method name. Returns Nothing if no methods found. - ''' - Private Function GetExprFactoryMethodGroup(methodName As String, typeArgs As ImmutableArray(Of TypeSymbol)) As BoundMethodGroup - Dim group As BoundMethodGroup = Nothing - Dim result = LookupResult.GetInstance() - - Dim useSiteInfo = _binder.GetNewCompoundUseSiteInfo(Me.Diagnostics) - _binder.LookupMember(result, - Me._expressionType, - methodName, - arity:=0, - options:=LookupOptions.AllMethodsOfAnyArity Or LookupOptions.IgnoreExtensionMethods, - useSiteInfo:=useSiteInfo) - Me.Diagnostics.Add(Me._factory.Syntax, useSiteInfo) - - If result.IsGood Then - Debug.Assert(result.Symbols.Count > 0) - Dim symbol0 = result.Symbols(0) - If result.Symbols(0).Kind = SymbolKind.Method Then - group = New BoundMethodGroup(Me._factory.Syntax, - Me._factory.TypeArguments(typeArgs), - result.Symbols.ToDowncastedImmutable(Of MethodSymbol), - result.Kind, - Nothing, - QualificationKind.QualifiedViaTypeName) + If helper IsNot Nothing Then + If Not typeArgs.IsEmpty Then + helper = helper.Construct(typeArgs) End If - End If - If group Is Nothing Then - Diagnostics.Add(If(result.HasDiagnostic, - result.Diagnostic, - ErrorFactory.ErrorInfo(ERRID.ERR_NameNotMember2, methodName, Me._expressionType)), - Me._factory.Syntax.GetLocation()) + Return New BoundCall(_factory.Syntax, helper, methodGroupOpt:=Nothing, receiverOpt:=Nothing, + arguments:=ImmutableArray.Create(Of BoundExpression)(arguments), + constantValueOpt:=Nothing, isLValue:=False, suppressObjectClone:=True, + helper.ReturnType) End If - result.Free() - Return group + Return _factory.BadExpression(arguments) End Function #End Region diff --git a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_BinaryOperator.vb b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_BinaryOperator.vb index 02725586c2922..aac8679e21f88 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_BinaryOperator.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_BinaryOperator.vb @@ -2,18 +2,8 @@ ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. -Imports System -Imports System.Collections.Generic Imports System.Collections.Immutable -Imports System.Diagnostics -Imports System.Linq -Imports System.Runtime.InteropServices -Imports System.Text -Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Symbols -Imports Microsoft.CodeAnalysis.VisualBasic.Syntax -Imports Roslyn.Utilities -Imports TypeKind = Microsoft.CodeAnalysis.TypeKind Namespace Microsoft.CodeAnalysis.VisualBasic Partial Friend Class ExpressionLambdaRewriter @@ -32,7 +22,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic BinaryOperatorKind.Divide, BinaryOperatorKind.Modulo, BinaryOperatorKind.IntegerDivide, - BinaryOperatorKind.Concatenate, BinaryOperatorKind.LeftShift, BinaryOperatorKind.RightShift Return ConvertBinaryOperator(node) @@ -83,7 +72,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' DiagnosticsPass.VisitUserDefinedBinaryOperator Debug.Assert(Not isLifted OrElse Not node.Call.Method.ReturnType.IsNullableType) - Return ConvertRuntimeHelperToExpressionTree(GetBinaryOperatorMethodName(opKind, isChecked), + Return ConvertRuntimeHelperToExpressionTree(GetComparisonBinaryOperatorFactoryWithMethodInfo(opKind), Visit(node.Left), Visit(node.Right), Me._factory.Literal(isLifted), _factory.MethodInfo(node.Call.Method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) @@ -93,12 +82,86 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' DiagnosticsPass.VisitUserDefinedBinaryOperator Debug.Assert(Not isLifted OrElse Not node.Call.Method.ReturnType.IsNullableType) - Return ConvertRuntimeHelperToExpressionTree(GetBinaryOperatorMethodName(opKind, isChecked), + Return ConvertRuntimeHelperToExpressionTree(GetNonComparisonBinaryOperatorFactoryWithMethodInfo(opKind, isChecked), Visit(node.Left), Visit(node.Right), _factory.MethodInfo(node.Call.Method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) End Select End Function + Private Shared Function GetComparisonBinaryOperatorFactoryWithMethodInfo(opKind As BinaryOperatorKind) As WellKnownMember + Select Case opKind And BinaryOperatorKind.OpMask + Case BinaryOperatorKind.Is, + BinaryOperatorKind.Equals + Return WellKnownMember.System_Linq_Expressions_Expression__Equal_MethodInfo + + Case BinaryOperatorKind.IsNot, + BinaryOperatorKind.NotEquals + Return WellKnownMember.System_Linq_Expressions_Expression__NotEqual_MethodInfo + + Case BinaryOperatorKind.LessThanOrEqual + Return WellKnownMember.System_Linq_Expressions_Expression__LessThanOrEqual_MethodInfo + + Case BinaryOperatorKind.GreaterThanOrEqual + Return WellKnownMember.System_Linq_Expressions_Expression__GreaterThanOrEqual_MethodInfo + + Case BinaryOperatorKind.LessThan + Return WellKnownMember.System_Linq_Expressions_Expression__LessThan_MethodInfo + + Case BinaryOperatorKind.GreaterThan + Return WellKnownMember.System_Linq_Expressions_Expression__GreaterThan_MethodInfo + + Case Else + Throw ExceptionUtilities.UnexpectedValue(opKind) + End Select + End Function + + Private Shared Function GetNonComparisonBinaryOperatorFactoryWithMethodInfo(opKind As BinaryOperatorKind, isChecked As Boolean) As WellKnownMember + Select Case opKind And BinaryOperatorKind.OpMask + Case BinaryOperatorKind.Add + Return If(isChecked, + WellKnownMember.System_Linq_Expressions_Expression__AddChecked_MethodInfo, + WellKnownMember.System_Linq_Expressions_Expression__Add_MethodInfo) + + Case BinaryOperatorKind.Subtract + Return If(isChecked, + WellKnownMember.System_Linq_Expressions_Expression__SubtractChecked_MethodInfo, + WellKnownMember.System_Linq_Expressions_Expression__Subtract_MethodInfo) + + Case BinaryOperatorKind.Multiply + Return If(isChecked, + WellKnownMember.System_Linq_Expressions_Expression__MultiplyChecked_MethodInfo, + WellKnownMember.System_Linq_Expressions_Expression__Multiply_MethodInfo) + + Case BinaryOperatorKind.IntegerDivide, + BinaryOperatorKind.Divide + Return WellKnownMember.System_Linq_Expressions_Expression__Divide_MethodInfo + + Case BinaryOperatorKind.Modulo + Return WellKnownMember.System_Linq_Expressions_Expression__Modulo_MethodInfo + + Case BinaryOperatorKind.Power + Return WellKnownMember.System_Linq_Expressions_Expression__Power_MethodInfo + + Case BinaryOperatorKind.And + Return WellKnownMember.System_Linq_Expressions_Expression__And_MethodInfo + + Case BinaryOperatorKind.Or + Return WellKnownMember.System_Linq_Expressions_Expression__Or_MethodInfo + + Case BinaryOperatorKind.Xor + Return WellKnownMember.System_Linq_Expressions_Expression__ExclusiveOr_MethodInfo + + Case BinaryOperatorKind.LeftShift + Return WellKnownMember.System_Linq_Expressions_Expression__LeftShift_MethodInfo + + Case BinaryOperatorKind.RightShift + Return WellKnownMember.System_Linq_Expressions_Expression__RightShift_MethodInfo + + Case Else + Throw ExceptionUtilities.UnexpectedValue(opKind) + End Select + End Function + Private Function VisitUserDefinedShortCircuitingOperator(node As BoundUserDefinedShortCircuitingOperator) As BoundExpression Dim operand As BoundUserDefinedBinaryOperator = node.BitwiseOperator Dim opKind As BinaryOperatorKind = operand.OperatorKind And BinaryOperatorKind.OpMask @@ -107,9 +170,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Debug.Assert(operand.Call.Method.ReturnType.IsSameTypeIgnoringAll(operand.Call.Method.Parameters(0).Type) AndAlso operand.Call.Method.ReturnType.IsSameTypeIgnoringAll(operand.Call.Method.Parameters(1).Type)) - opKind = If(opKind = BinaryOperatorKind.And, BinaryOperatorKind.AndAlso, BinaryOperatorKind.OrElse) - - Return ConvertRuntimeHelperToExpressionTree(GetBinaryOperatorMethodName(opKind, False), + Return ConvertRuntimeHelperToExpressionTree(If(opKind = BinaryOperatorKind.And, + WellKnownMember.System_Linq_Expressions_Expression__AndAlso_MethodInfo, + WellKnownMember.System_Linq_Expressions_Expression__OrElse_MethodInfo), Visit(operand.Left), Visit(operand.Right), _factory.MethodInfo(operand.Call.Method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) End Function @@ -202,12 +265,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic helper = GetHelperForDateTimeBinaryOperation(opKind) End If - Dim isChecked As Boolean = node.Checked AndAlso IsIntegralType(resultUnderlyingType) - Dim opMethod As String = GetBinaryOperatorMethodName(opKind, isChecked) - If helper IsNot Nothing Then Debug.Assert(helper.MethodKind = MethodKind.Ordinary OrElse helper.MethodKind = MethodKind.UserDefinedOperator) - Return ConvertRuntimeHelperToExpressionTree(opMethod, left, right, Me._factory.Literal(resultType.IsNullableType), _factory.MethodInfo(helper, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) + + Return ConvertRuntimeHelperToExpressionTree(GetComparisonBinaryOperatorFactoryWithMethodInfo(opKind), + left, right, Me._factory.Literal(resultType.IsNullableType), _factory.MethodInfo(helper, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) End If ' No helpers starting from here @@ -220,19 +282,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' Because True is -1, we need to switch the comparisons in these cases. Select Case opKind Case BinaryOperatorKind.LessThan - opMethod = GetBinaryOperatorMethodName(BinaryOperatorKind.GreaterThan, isChecked) + opKind = BinaryOperatorKind.GreaterThan convertOperandsToInteger = True Case BinaryOperatorKind.LessThanOrEqual - opMethod = GetBinaryOperatorMethodName(BinaryOperatorKind.GreaterThanOrEqual, isChecked) + opKind = BinaryOperatorKind.GreaterThanOrEqual convertOperandsToInteger = True Case BinaryOperatorKind.GreaterThan - opMethod = GetBinaryOperatorMethodName(BinaryOperatorKind.LessThan, isChecked) + opKind = BinaryOperatorKind.LessThan convertOperandsToInteger = True Case BinaryOperatorKind.GreaterThanOrEqual - opMethod = GetBinaryOperatorMethodName(BinaryOperatorKind.LessThanOrEqual, isChecked) + opKind = BinaryOperatorKind.LessThanOrEqual convertOperandsToInteger = True End Select End If @@ -258,7 +320,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic operandActiveType = newType End If - Return ConvertRuntimeHelperToExpressionTree(opMethod, left, right, Me._factory.Literal(resultType.IsNullableType), Me._factory.Null) + Return ConvertRuntimeHelperToExpressionTree(GetComparisonBinaryOperatorFactoryWithMethodInfo(opKind), + left, right, Me._factory.Literal(resultType.IsNullableType), + Me._factory.Null(_factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) End Function #End Region @@ -290,9 +354,18 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If Dim isChecked As Boolean = node.Checked AndAlso IsIntegralType(resultUnderlyingType) - Dim opMethod As String = GetBinaryOperatorMethodName(opKind, isChecked) + Dim opFactory As WellKnownMember + + Select Case opKind + Case BinaryOperatorKind.AndAlso + opFactory = WellKnownMember.System_Linq_Expressions_Expression__AndAlso + Case BinaryOperatorKind.OrElse + opFactory = WellKnownMember.System_Linq_Expressions_Expression__OrElse + Case Else + Throw ExceptionUtilities.UnexpectedValue(opKind) + End Select - Dim result As BoundExpression = ConvertRuntimeHelperToExpressionTree(opMethod, left, right) + Dim result As BoundExpression = ConvertRuntimeHelperToExpressionTree(opFactory, left, right) If resultUnderlyingType.IsObjectType Then result = Convert(result, resultType, isChecked) @@ -303,7 +376,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic #End Region -#Region "And, Or, Xor, ^, *, +, -, /, \, Mod, &, <<, >>" +#Region "And, Or, Xor, ^, *, +, -, /, \, Mod, <<, >>" Private Function ConvertBinaryOperator(node As BoundBinaryOperator) As BoundExpression Dim resultType As TypeSymbol = node.Type @@ -317,7 +390,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic opKind = BinaryOperatorKind.Power OrElse opKind = BinaryOperatorKind.Multiply OrElse opKind = BinaryOperatorKind.Add OrElse opKind = BinaryOperatorKind.Subtract OrElse opKind = BinaryOperatorKind.Divide OrElse opKind = BinaryOperatorKind.IntegerDivide OrElse - opKind = BinaryOperatorKind.Modulo OrElse opKind = BinaryOperatorKind.Concatenate OrElse + opKind = BinaryOperatorKind.Modulo OrElse opKind = BinaryOperatorKind.LeftShift OrElse opKind = BinaryOperatorKind.RightShift) Debug.Assert((node.OperatorKind And BinaryOperatorKind.UserDefined) = 0) @@ -325,26 +398,32 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim helper As MethodSymbol = Nothing If resultUnderlyingSpecialType = SpecialType.System_Object Then helper = GetHelperForObjectBinaryOperation(opKind) - + If helper Is Nothing Then ' Don't know how to do 'BinaryOperatorKind.Power' without the method + Return _factory.BadExpression(Visit(node.Left), Visit(node.Right)) + End If ElseIf resultUnderlyingSpecialType = SpecialType.System_Decimal Then helper = GetHelperForDecimalBinaryOperation(opKind) - - ElseIf opKind = BinaryOperatorKind.Concatenate Then - helper = DirectCast(_factory.SpecialMember(SpecialMember.System_String__ConcatStringString), MethodSymbol) - + If helper Is Nothing Then ' Don't know how to do 'BinaryOperatorKind.Power' without the method + Return _factory.BadExpression(Visit(node.Left), Visit(node.Right)) + End If ElseIf opKind = BinaryOperatorKind.Power Then helper = Me._factory.WellKnownMember(Of MethodSymbol)(WellKnownMember.System_Math__PowDoubleDouble) + If helper Is Nothing Then ' Don't know how to do 'BinaryOperatorKind.Power' without the method + Return _factory.BadExpression(Visit(node.Left), Visit(node.Right)) + End If End If + Debug.Assert(opKind <> BinaryOperatorKind.Power OrElse helper IsNot Nothing) + Dim isChecked As Boolean = node.Checked AndAlso IsIntegralType(resultUnderlyingType) - Dim opMethod As String = GetBinaryOperatorMethodName(opKind, isChecked) Dim left As BoundExpression = Visit(node.Left) Dim right As BoundExpression If helper IsNot Nothing Then right = Visit(node.Right) - Return ConvertRuntimeHelperToExpressionTree(opMethod, left, right, _factory.MethodInfo(helper, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) + Return ConvertRuntimeHelperToExpressionTree(GetNonComparisonBinaryOperatorFactoryWithMethodInfo(opKind, isChecked), + left, right, _factory.MethodInfo(helper, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) End If ' No special helper @@ -372,7 +451,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic needToCastBackToByteOrSByte) End If - Dim result As BoundExpression = ConvertRuntimeHelperToExpressionTree(opMethod, left, right) + Dim result As BoundExpression = ConvertRuntimeHelperToExpressionTree(GetNonComparisonBinaryOperatorFactoryWithoutMethodInfo(opKind, isChecked), left, right) If needToCastBackToByteOrSByte Then Debug.Assert(resultUnderlyingSpecialType = SpecialType.System_Byte OrElse resultUnderlyingSpecialType = SpecialType.System_SByte) @@ -386,6 +465,50 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return result End Function + Private Shared Function GetNonComparisonBinaryOperatorFactoryWithoutMethodInfo(opKind As BinaryOperatorKind, isChecked As Boolean) As WellKnownMember + Select Case opKind And BinaryOperatorKind.OpMask + Case BinaryOperatorKind.Add + Return If(isChecked, + WellKnownMember.System_Linq_Expressions_Expression__AddChecked, + WellKnownMember.System_Linq_Expressions_Expression__Add) + + Case BinaryOperatorKind.Subtract + Return If(isChecked, + WellKnownMember.System_Linq_Expressions_Expression__SubtractChecked, + WellKnownMember.System_Linq_Expressions_Expression__Subtract) + + Case BinaryOperatorKind.Multiply + Return If(isChecked, + WellKnownMember.System_Linq_Expressions_Expression__MultiplyChecked, + WellKnownMember.System_Linq_Expressions_Expression__Multiply) + + Case BinaryOperatorKind.IntegerDivide, + BinaryOperatorKind.Divide + Return WellKnownMember.System_Linq_Expressions_Expression__Divide + + Case BinaryOperatorKind.Modulo + Return WellKnownMember.System_Linq_Expressions_Expression__Modulo + + Case BinaryOperatorKind.And + Return WellKnownMember.System_Linq_Expressions_Expression__And + + Case BinaryOperatorKind.Or + Return WellKnownMember.System_Linq_Expressions_Expression__Or + + Case BinaryOperatorKind.Xor + Return WellKnownMember.System_Linq_Expressions_Expression__ExclusiveOr + + Case BinaryOperatorKind.LeftShift + Return WellKnownMember.System_Linq_Expressions_Expression__LeftShift + + Case BinaryOperatorKind.RightShift + Return WellKnownMember.System_Linq_Expressions_Expression__RightShift + + Case Else + Throw ExceptionUtilities.UnexpectedValue(opKind) + End Select + End Function + Private Function GenerateCastsForBinaryAndUnaryOperator(loweredOperand As BoundExpression, isNullable As Boolean, notNullableType As TypeSymbol, @@ -463,9 +586,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Private Function MaskShiftCountOperand(loweredOperand As BoundExpression, shiftedType As TypeSymbol, shiftMask As Integer, shiftConst As ConstantValue, isChecked As Boolean) As BoundExpression If shiftConst Is Nothing OrElse shiftConst.UInt32Value > shiftMask Then Dim constantOperand As BoundExpression = - ConvertRuntimeHelperToExpressionTree("Constant", - Me._factory.Convert(Me.ObjectType, Me._factory.Literal(shiftMask)), - Me._factory.Typeof(Me.Int32Type, _factory.WellKnownType(WellKnownType.System_Type))) + _factory.Convert(_expressionType, + ConvertRuntimeHelperToExpressionTree( + WellKnownMember.System_Linq_Expressions_Expression__Constant, + Me._factory.Convert(Me.ObjectType, Me._factory.Literal(shiftMask)), + Me._factory.Typeof(Me.Int32Type, _factory.WellKnownType(WellKnownType.System_Type)))) Dim isNullable As Boolean = shiftedType.IsNullableType Dim isInt32 As Boolean = shiftedType.GetNullableUnderlyingTypeOrSelf.SpecialType = SpecialType.System_Int32 @@ -476,7 +601,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic constantOperand = Convert(constantOperand, int32Nullable, isChecked) End If - loweredOperand = ConvertRuntimeHelperToExpressionTree("And", loweredOperand, constantOperand) + loweredOperand = _factory.Convert(_expressionType, + ConvertRuntimeHelperToExpressionTree( + WellKnownMember.System_Linq_Expressions_Expression__And, + loweredOperand, + constantOperand)) End If Return loweredOperand @@ -589,54 +718,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return Me._factory.WellKnownMember(Of MethodSymbol)(wellKnownHelper) End Function - Private Shared Function GetBinaryOperatorMethodName(opKind As BinaryOperatorKind, isChecked As Boolean) As String - Select Case (opKind And BinaryOperatorKind.OpMask) - Case BinaryOperatorKind.Add - Return If(isChecked, "AddChecked", "Add") - Case BinaryOperatorKind.Subtract - Return If(isChecked, "SubtractChecked", "Subtract") - Case BinaryOperatorKind.Multiply - Return If(isChecked, "MultiplyChecked", "Multiply") - Case BinaryOperatorKind.IntegerDivide, - BinaryOperatorKind.Divide - Return "Divide" - Case BinaryOperatorKind.Modulo - Return "Modulo" - Case BinaryOperatorKind.Power - Return "Power" - Case BinaryOperatorKind.And - Return "And" - Case BinaryOperatorKind.Or - Return "Or" - Case BinaryOperatorKind.Xor - Return "ExclusiveOr" - Case BinaryOperatorKind.LeftShift - Return "LeftShift" - Case BinaryOperatorKind.RightShift - Return "RightShift" - Case BinaryOperatorKind.Is, - BinaryOperatorKind.Equals - Return "Equal" - Case BinaryOperatorKind.IsNot, - BinaryOperatorKind.NotEquals - Return "NotEqual" - Case BinaryOperatorKind.LessThan - Return "LessThan" - Case BinaryOperatorKind.LessThanOrEqual - Return "LessThanOrEqual" - Case BinaryOperatorKind.GreaterThan - Return "GreaterThan" - Case BinaryOperatorKind.GreaterThanOrEqual - Return "GreaterThanOrEqual" - Case BinaryOperatorKind.AndAlso - Return "AndAlso" - Case BinaryOperatorKind.OrElse - Return "OrElse" - Case Else - Throw ExceptionUtilities.UnexpectedValue(opKind) - End Select - End Function - Private Shared Function AdjustCallArgumentForLiftedOperator(oldArg As BoundExpression, parameterType As TypeSymbol) As BoundExpression Debug.Assert(oldArg.Type.IsNullableType) Debug.Assert(Not parameterType.IsNullableType) diff --git a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_ConditionalExpresion.vb b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_ConditionalExpresion.vb index 282ac3fa5aebe..551f9ae1158af 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_ConditionalExpresion.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_ConditionalExpresion.vb @@ -24,7 +24,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim condition As BoundExpression = Visit(node.Condition) Dim whenTrue As BoundExpression = Visit(node.WhenTrue) Dim whenFalse As BoundExpression = Visit(node.WhenFalse) - Return ConvertRuntimeHelperToExpressionTree("Condition", condition, whenTrue, whenFalse) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__Condition, condition, whenTrue, whenFalse) End Function Private Function VisitBinaryConditionalExpression(node As BoundBinaryConditionalExpression) As BoundExpression @@ -45,7 +45,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic If convTestExpr Is Nothing OrElse resultType.IsSameTypeIgnoringAll(testExpressionType) OrElse (testExpressionType.IsNullableType AndAlso resultType.IsSameTypeIgnoringAll(testExpressionType.GetNullableUnderlyingType)) Then - Return ConvertRuntimeHelperToExpressionTree("Coalesce", rewrittenTestExpression, rewrittenElseExpression) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__Coalesce, rewrittenTestExpression, rewrittenElseExpression) End If Select Case convTestExpr.Kind @@ -54,7 +54,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim paramSymbol As ParameterSymbol = CreateCoalesceLambdaParameterSymbol(testExpressionType) Dim lambdaBody As BoundExpression = BuildLambdaBodyForCoalesce(conversion, resultType, paramSymbol, conversion.Checked) Dim coalesceLambda As BoundExpression = BuildLambdaForCoalesceCall(resultType, paramSymbol, lambdaBody) - Return ConvertRuntimeHelperToExpressionTree("Coalesce", rewrittenTestExpression, rewrittenElseExpression, coalesceLambda) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__Coalesce_Lambda, rewrittenTestExpression, rewrittenElseExpression, coalesceLambda) Case Else Throw ExceptionUtilities.UnexpectedValue(convTestExpr.Kind) @@ -74,7 +74,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim paramLocalSymbol As LocalSymbol = Me._factory.SynthesizedLocal(parameterExpressionType) Dim parameterReference As BoundLocal = Me._factory.Local(paramLocalSymbol, True) - Dim parameter As BoundExpression = ConvertRuntimeHelperToExpressionTree("Parameter", _factory.[Typeof](lambdaParameter.Type, _factory.WellKnownType(WellKnownType.System_Type)), _factory.Literal(s_coalesceLambdaParameterName)) + Dim parameter As BoundExpression = ConvertRuntimeHelperToExpressionTree( + WellKnownMember.System_Linq_Expressions_Expression__Parameter, + _factory.[Typeof](lambdaParameter.Type, _factory.WellKnownType(WellKnownType.System_Type)), + _factory.Literal(s_coalesceLambdaParameterName)) Me._parameterMap(lambdaParameter) = parameterReference.MakeRValue Dim convertedValue As BoundExpression = Visit(body) @@ -86,7 +89,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ImmutableArray.Create(Of BoundExpression)( Me._factory.AssignmentExpression(parameterReference, parameter)), ConvertRuntimeHelperToExpressionTree( - "Lambda", + WellKnownMember.System_Linq_Expressions_Expression__Lambda, convertedValue, Me._factory.Array( parameterExpressionType, diff --git a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_Conversion.vb b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_Conversion.vb index 0acd1414fceb6..e0bf0de50a651 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_Conversion.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_Conversion.vb @@ -70,7 +70,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic If notNullableTo.IsTypeParameter() Then If toIsNullable Then - Return Convert(VisitInternal(Me._factory.Null(Me.ObjectType)), typeTo, False) + Return Convert(Visit(Me._factory.Null(Me.ObjectType)), typeTo, False) Else Return [Default](typeTo) End If @@ -111,8 +111,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Private Function ConvertLambda(node As BoundLambda, type As TypeSymbol) As BoundExpression If type.IsExpressionTree(Me._binder) Then type = type.ExpressionTargetDelegate(Me._factory.Compilation) - Dim result = VisitLambdaInternal(node, DirectCast(type, NamedTypeSymbol)) - Return ConvertRuntimeHelperToExpressionTree("Quote", result) + Dim result = _factory.Convert(_expressionType, VisitLambdaInternal(node, DirectCast(type, NamedTypeSymbol))) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__Quote, result) Else Return VisitLambdaInternal(node, DirectCast(type, NamedTypeSymbol)) End If @@ -233,7 +233,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Case Else Dim helper As MethodSymbol = Me._factory.WellKnownMember(Of MethodSymbol)(WellKnownMember.Microsoft_VisualBasic_CompilerServices_Conversions__ToGenericParameter_T_Object) - Return [Call](_factory.Null(), helper.Construct(typeTo), rewrittenOperand) + Return [Call](_factory.Null(_expressionType), helper.Construct(typeTo), rewrittenOperand) End Select ElseIf underlyingFrom.IsTypeParameter() Then @@ -399,7 +399,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Function Private Function CreateTypeAs(expr As BoundExpression, type As TypeSymbol) As BoundExpression - Return ConvertRuntimeHelperToExpressionTree("TypeAs", expr, _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type))) + Return _factory.Convert( + _expressionType, + ConvertRuntimeHelperToExpressionTree( + WellKnownMember.System_Linq_Expressions_Expression__TypeAs, + expr, + _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type)))) End Function Private Function CreateTypeAsIfNeeded(operand As BoundExpression, oldType As TypeSymbol, newType As TypeSymbol) As BoundExpression @@ -408,16 +413,29 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' Emit a Convert node to a specific type with no helper method. Private Function Convert(expr As BoundExpression, type As TypeSymbol, isChecked As Boolean) As BoundExpression - Return ConvertRuntimeHelperToExpressionTree(If(isChecked, "ConvertChecked", "Convert"), expr, _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type))) + If expr.Type IsNot _expressionType Then + expr = _factory.Convert(_expressionType, expr) + End If + + Return _factory.Convert( + _expressionType, + ConvertRuntimeHelperToExpressionTree( + If(isChecked, + WellKnownMember.System_Linq_Expressions_Expression__ConvertChecked, + WellKnownMember.System_Linq_Expressions_Expression__Convert), + expr, + _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type)))) End Function ' Emit a Convert node to a specific type with a helper method. Private Function Convert(expr As BoundExpression, type As TypeSymbol, helper As MethodSymbol, isChecked As Boolean) As BoundExpression - Return ConvertRuntimeHelperToExpressionTree( - If(isChecked, "ConvertChecked", "Convert"), - expr, - _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type)), - _factory.MethodInfo(helper, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) + Return _factory.Convert( + _expressionType, + ConvertRuntimeHelperToExpressionTree( + If(isChecked, WellKnownMember.System_Linq_Expressions_Expression__ConvertChecked_MethodInfo, WellKnownMember.System_Linq_Expressions_Expression__Convert_MethodInfo), + expr, + _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type)), + _factory.MethodInfo(helper, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo)))) End Function ' Emit a convert node if types are different. diff --git a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_UnaryOperator.vb b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_UnaryOperator.vb index 27fb30fe19d7d..9488d970123c7 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_UnaryOperator.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_UnaryOperator.vb @@ -30,7 +30,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim opKind As UnaryOperatorKind = node.OperatorKind And UnaryOperatorKind.OpMask Dim isChecked As Boolean = node.Checked AndAlso origArgUnderlyingType.IsIntegralType - Dim helperName As String = Nothing Debug.Assert((node.OperatorKind And UnaryOperatorKind.UserDefined) = 0) @@ -44,16 +43,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End If Dim method As MethodSymbol = GetHelperForObjectUnaryOperation(opKind) - Return If(method Is Nothing, argument, ConvertRuntimeHelperToExpressionTree("UnaryPlus", argument, Me._factory.MethodInfo(method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo)))) + Return If(method Is Nothing, + argument, + ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__UnaryPlus, + argument, Me._factory.MethodInfo(method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo)))) - Case UnaryOperatorKind.Minus - helperName = If(isChecked, "NegateChecked", "Negate") - GoTo lNotAndMinus - - Case UnaryOperatorKind.Not - helperName = "Not" - -lNotAndMinus: + Case UnaryOperatorKind.Minus, + UnaryOperatorKind.Not ' NOTE: Both '-' and 'Not' processed by the code below Dim method As MethodSymbol = Nothing @@ -63,11 +59,28 @@ lNotAndMinus: method = GetHelperForDecimalUnaryOperation(opKind) End If + Dim helper As WellKnownMember + If method IsNot Nothing Then - Return ConvertRuntimeHelperToExpressionTree(helperName, argument, Me._factory.MethodInfo(method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) + If opKind = UnaryOperatorKind.Minus Then + helper = If(isChecked, + WellKnownMember.System_Linq_Expressions_Expression__NegateChecked_Expression_MethodInfo, + WellKnownMember.System_Linq_Expressions_Expression__Negate_Expression_MethodInfo) + Else + helper = WellKnownMember.System_Linq_Expressions_Expression__Not_Expression_MethodInfo + End If + + Return ConvertRuntimeHelperToExpressionTree(helper, argument, Me._factory.MethodInfo(method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) End If ' No standard method + If opKind = UnaryOperatorKind.Minus Then + helper = If(isChecked, + WellKnownMember.System_Linq_Expressions_Expression__NegateChecked_Expression, + WellKnownMember.System_Linq_Expressions_Expression__Negate_Expression) + Else + helper = WellKnownMember.System_Linq_Expressions_Expression__Not_Expression + End If ' convert i1, u1 to i4 if needed Dim needToCastBackToByteOrSByte As Boolean = origArgUnderlyingSpecialType = SpecialType.System_Byte OrElse @@ -81,7 +94,7 @@ lNotAndMinus: isChecked AndAlso IsIntegralType(origArgUnderlyingType), needToCastBackToByteOrSByte) - Dim result As BoundExpression = ConvertRuntimeHelperToExpressionTree(helperName, argument) + Dim result As BoundExpression = ConvertRuntimeHelperToExpressionTree(helper, argument) ' convert i4 back to i1, u1 If needToCastBackToByteOrSByte Then @@ -124,7 +137,7 @@ lNotAndMinus: Dim paramSymbol As ParameterSymbol = CreateCoalesceLambdaParameterSymbol(udoOperandType) Dim lambdaBody As BoundExpression = BuildLambdaBodyForCoalesce(userDefinedOperator.OperatorKind, [call], node.Type, paramSymbol) Dim coalesceLambda As BoundExpression = BuildLambdaForCoalesceCall(node.Type, paramSymbol, lambdaBody) - Return ConvertRuntimeHelperToExpressionTree("Coalesce", Visit(userDefinedOperator.Operand), Visit(Me._factory.Literal(False)), coalesceLambda) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__Coalesce_Lambda, Visit(userDefinedOperator.Operand), Visit(Me._factory.Literal(False)), coalesceLambda) End Select If operand.Kind = BoundKind.ObjectCreationExpression Then @@ -135,7 +148,7 @@ lNotAndMinus: End If End If - Return ConvertRuntimeHelperToExpressionTree("Coalesce", Visit(operand), Visit(Me._factory.Literal(False))) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__Coalesce, Visit(operand), Visit(Me._factory.Literal(False))) End Function Private Function BuildLambdaBodyForCoalesce(opKind As UnaryOperatorKind, [call] As BoundCall, resultType As TypeSymbol, lambdaParameter As ParameterSymbol) As BoundExpression @@ -175,7 +188,7 @@ lNotAndMinus: ' See description in DiagnosticsPass.VisitUserDefinedUnaryOperator Debug.Assert(Not isLifted OrElse Not node.Call.Method.ReturnType.IsNullableType) - Return ConvertRuntimeHelperToExpressionTree(GetUnaryOperatorMethodName(opKind, False), + Return ConvertRuntimeHelperToExpressionTree(GetUnaryOperatorFactoryMethod(opKind), Visit(node.Operand), _factory.MethodInfo(node.Call.Method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo))) @@ -237,14 +250,14 @@ lNotAndMinus: ''' ''' Get the name of the expression tree function for a particular unary operator ''' - Private Shared Function GetUnaryOperatorMethodName(opKind As UnaryOperatorKind, isChecked As Boolean) As String + Private Shared Function GetUnaryOperatorFactoryMethod(opKind As UnaryOperatorKind) As WellKnownMember Select Case (opKind And UnaryOperatorKind.OpMask) Case UnaryOperatorKind.Not - Return "Not" + Return WellKnownMember.System_Linq_Expressions_Expression__Not_Expression_MethodInfo Case UnaryOperatorKind.Plus - Return "UnaryPlus" + Return WellKnownMember.System_Linq_Expressions_Expression__UnaryPlus Case UnaryOperatorKind.Minus - Return If(isChecked, "NegateChecked", "Negate") + Return WellKnownMember.System_Linq_Expressions_Expression__Negate_Expression_MethodInfo Case Else Throw ExceptionUtilities.UnexpectedValue(opKind) End Select diff --git a/src/Compilers/VisualBasic/Test/Emit/ExpressionTrees/CodeGenExprLambda.vb b/src/Compilers/VisualBasic/Test/Emit/ExpressionTrees/CodeGenExprLambda.vb index a9c796b99cf61..d75635d656bb7 100644 --- a/src/Compilers/VisualBasic/Test/Emit/ExpressionTrees/CodeGenExprLambda.vb +++ b/src/Compilers/VisualBasic/Test/Emit/ExpressionTrees/CodeGenExprLambda.vb @@ -1183,6 +1183,67 @@ Lambda( ]]>) End Sub + + Public Sub CharArrayToStringConversion() + + Dim source = + <%= _exprTesting %> + + + + Dim expected = + + CompileAndVerify(source, + references:={Net40.References.SystemCore}, + options:=TestOptions.ReleaseExe.WithOverflowChecks(True), + expectedOutput:=expected + ) + + CompileAndVerify(source, + references:={Net40.References.SystemCore}, + options:=TestOptions.ReleaseExe.WithOverflowChecks(False), + expectedOutput:=expected + ) + + End Sub + #Region "Conversions: User Defined Types" Public Sub TestConversion_UserDefinedTypes_Narrowing(checked As Boolean, result As String) @@ -6588,19 +6649,19 @@ End Namespace Dim emitResult = compilation.Emit(stream) Assert.False(emitResult.Success) CompilationUtils.AssertTheseDiagnostics(emitResult.Diagnostics, -BC30456: 'Lambda' is not a member of 'Expression'. +BC35000: Requested operation is not available because the runtime library function 'System.Linq.Expressions.Expression.Lambda' is not defined. Dim exprTree As Expression(Of Func(Of Integer, Integer, Integer)) = Function(x, y) x + y ~~~~~~~~~~~~~~~~~~~~ -BC30456: 'Parameter' is not a member of 'Expression'. +BC35000: Requested operation is not available because the runtime library function 'System.Linq.Expressions.Expression.Parameter' is not defined. Dim exprTree As Expression(Of Func(Of Integer, Integer, Integer)) = Function(x, y) x + y ~~~~~~~~~~~~~~~~~~~~ -BC30456: 'Parameter' is not a member of 'Expression'. +BC35000: Requested operation is not available because the runtime library function 'System.Linq.Expressions.Expression.Parameter' is not defined. Dim exprTree As Expression(Of Func(Of Integer, Integer, Integer)) = Function(x, y) x + y ~~~~~~~~~~~~~~~~~~~~ -BC30456: 'AddChecked' is not a member of 'Expression'. +BC35000: Requested operation is not available because the runtime library function 'System.Linq.Expressions.Expression.AddChecked' is not defined. Dim exprTree As Expression(Of Func(Of Integer, Integer, Integer)) = Function(x, y) x + y ~~~~~ - ) + ) End Using End Sub @@ -8038,10 +8099,10 @@ Namespace System.Collections.Generic End Namespace Namespace System.Linq.Expressions Public Class Expression - Public Shared Function [New](t As Type) As Expression + Public Shared Function [New](t As Type) As NewExpression Return Nothing End Function - Public Shared Function Lambda(Of T)(e As Expression, args As Expression()) As Expression(Of T) + Public Shared Function Lambda(Of T)(e As Expression, args As ParameterExpression()) As Expression(Of T) Return Nothing End Function End Class @@ -8050,6 +8111,9 @@ Namespace System.Linq.Expressions Public Class ParameterExpression Inherits Expression End Class + Public Class NewExpression + Inherits Expression + End Class End Namespace Delegate Function D() As C Class C @@ -8103,10 +8167,10 @@ Namespace System.Collections.Generic End Namespace Namespace System.Linq.Expressions Public Class Expression - Public Shared Function Field(e As Expression, f As FieldInfo) As Expression + Public Shared Function Field(e As Expression, f As FieldInfo) As MemberExpression Return Nothing End Function - Public Shared Function Lambda(Of T)(e As Expression, args As Expression()) As Expression(Of T) + Public Shared Function Lambda(Of T)(e As Expression, args As ParameterExpression()) As Expression(Of T) Return Nothing End Function End Class @@ -8115,6 +8179,9 @@ Namespace System.Linq.Expressions Public Class ParameterExpression Inherits Expression End Class + Public Class MemberExpression + Inherits Expression + End Class End Namespace Namespace System.Reflection Public Class FieldInfo @@ -8186,19 +8253,19 @@ Namespace System.Collections.Generic End Namespace Namespace System.Linq.Expressions Public Class Expression - Public Shared Function [Call](e As Expression, m As MethodInfo, args As Expression()) As Expression + Public Shared Function [Call](e As Expression, m As MethodInfo, args As Expression()) As MethodCallExpression Return Nothing End Function - Public Shared Function Constant(o As Object, t As Type) As Expression + Public Shared Function Constant(o As Object, t As Type) As ConstantExpression Return Nothing End Function - Public Shared Function Convert(e As Expression, t As Type) As Expression + Public Shared Function Convert(e As Expression, t As Type) As UnaryExpression Return Nothing End Function - Public Shared Function Lambda(Of T)(e As Expression, args As Expression()) As Expression(Of T) + Public Shared Function Lambda(Of T)(e As Expression, args As ParameterExpression()) As Expression(Of T) Return Nothing End Function - Public Shared Function [New](c As ConstructorInfo, args As IEnumerable(Of Expression)) As Expression + Public Shared Function [New](c As ConstructorInfo, args As Expression()) As NewExpression Return Nothing End Function End Class @@ -8207,6 +8274,18 @@ Namespace System.Linq.Expressions Public Class ParameterExpression Inherits Expression End Class + Public Class UnaryExpression + Inherits Expression + End Class + Public Class ConstantExpression + Inherits Expression + End Class + Public Class NewExpression + Inherits Expression + End Class + Public Class MethodCallExpression + Inherits Expression + End Class End Namespace Namespace System.Reflection Public Class ConstructorInfo From 8e7c4949880ee54ecd856cfda2ca16a6e13010ec Mon Sep 17 00:00:00 2001 From: AlekseyTs Date: Mon, 14 Oct 2024 17:53:02 -0700 Subject: [PATCH 2/2] PR feedback --- .../ExpressionLambdaRewriter.vb | 24 +++++++------------ ...ExpressionLambdaRewriter_BinaryOperator.vb | 5 ++-- .../ExpressionLambdaRewriter_Conversion.vb | 10 ++++---- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter.vb b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter.vb index 369d907d0cab2..61e12e486be3f 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter.vb @@ -761,29 +761,23 @@ lSelect: ' Emit a call node Private Function [Call](receiver As BoundExpression, method As MethodSymbol, ParamArray params As BoundExpression()) As BoundExpression - Return _factory.Convert( - _expressionType, - ConvertRuntimeHelperToExpressionTree( - WellKnownMember.System_Linq_Expressions_Expression__Call, - receiver, - _factory.MethodInfo(method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo)), - _factory.Array(_expressionType, params))) + Return ConvertRuntimeHelperToExpressionTree( + WellKnownMember.System_Linq_Expressions_Expression__Call, + receiver, + _factory.MethodInfo(method, _factory.WellKnownType(WellKnownType.System_Reflection_MethodInfo)), + _factory.Array(_expressionType, params)) End Function ' Emit a Default node for a specific type Private Function [Default](type As TypeSymbol) As BoundExpression - Return _factory.Convert( - _expressionType, - ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__Default, _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type)))) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__Default, _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type))) End Function ' Emit a New node to a specific type with a helper constructor and one argument Private Function [New](helper As SpecialMember, argument As BoundExpression) As BoundExpression - Return _factory.Convert( - _expressionType, - ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__New_ConstructorInfo_ArrayExpressions, - _factory.ConstructorInfo(helper), - _factory.Array(_expressionType, argument))) + Return ConvertRuntimeHelperToExpressionTree(WellKnownMember.System_Linq_Expressions_Expression__New_ConstructorInfo_ArrayExpressions, + _factory.ConstructorInfo(helper), + _factory.Array(_expressionType, argument)) End Function ' Emit a negate node diff --git a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_BinaryOperator.vb b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_BinaryOperator.vb index aac8679e21f88..e0d1d81e26616 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_BinaryOperator.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_BinaryOperator.vb @@ -40,8 +40,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic BinaryOperatorKind.AndAlso Return ConvertShortCircuitedBooleanOperator(node) - Case BinaryOperatorKind.Like - ' Like operator should already be rewritten by this time + Case BinaryOperatorKind.Like, + BinaryOperatorKind.Concatenate + ' Should already be rewritten by this time Throw ExceptionUtilities.UnexpectedValue(node.OperatorKind) Case Else diff --git a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_Conversion.vb b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_Conversion.vb index e0bf0de50a651..93952be32567e 100644 --- a/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_Conversion.vb +++ b/src/Compilers/VisualBasic/Portable/Lowering/ExpressionLambdaRewriter/ExpressionLambdaRewriter_Conversion.vb @@ -399,12 +399,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Function Private Function CreateTypeAs(expr As BoundExpression, type As TypeSymbol) As BoundExpression - Return _factory.Convert( - _expressionType, - ConvertRuntimeHelperToExpressionTree( - WellKnownMember.System_Linq_Expressions_Expression__TypeAs, - expr, - _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type)))) + Return ConvertRuntimeHelperToExpressionTree( + WellKnownMember.System_Linq_Expressions_Expression__TypeAs, + expr, + _factory.[Typeof](type, _factory.WellKnownType(WellKnownType.System_Type))) End Function Private Function CreateTypeAsIfNeeded(operand As BoundExpression, oldType As TypeSymbol, newType As TypeSymbol) As BoundExpression