diff --git a/src/libraries/System.Linq.Expressions/src/ILLink/ILLink.Suppressions.xml b/src/libraries/System.Linq.Expressions/src/ILLink/ILLink.Suppressions.xml index 5d2ce5eca2aed5cb845e55a16626fdb6b347f870..ea80eae650ff3d7d40f8667a26acd4b36ecba5ef 100644 --- a/src/libraries/System.Linq.Expressions/src/ILLink/ILLink.Suppressions.xml +++ b/src/libraries/System.Linq.Expressions/src/ILLink/ILLink.Suppressions.xml @@ -19,36 +19,6 @@ member M:System.Dynamic.Utils.TypeExtensions.GetAnyStaticMethodValidated(System.Type,System.String,System.Type[]) - - ILLink - IL2070 - member - M:System.Linq.Expressions.Compiler.LambdaCompiler.EmitGetArrayElement(System.Type) - - - ILLink - IL2070 - member - M:System.Linq.Expressions.Compiler.LambdaCompiler.EmitLift(System.Linq.Expressions.ExpressionType,System.Type,System.Linq.Expressions.MethodCallExpression,System.Linq.Expressions.ParameterExpression[],System.Linq.Expressions.Expression[]) - - - ILLink - IL2070 - member - M:System.Linq.Expressions.Compiler.LambdaCompiler.EmitLiftedBinaryArithmetic(System.Linq.Expressions.ExpressionType,System.Type,System.Type,System.Type) - - - ILLink - IL2070 - member - M:System.Linq.Expressions.Compiler.LambdaCompiler.EmitSetArrayElement(System.Type) - - - ILLink - IL2070 - member - M:System.Linq.Expressions.Compiler.LambdaCompiler.EmitUnaryOperator(System.Linq.Expressions.ExpressionType,System.Type,System.Type) - ILLink IL2072 @@ -79,36 +49,6 @@ member M:System.Dynamic.Utils.TypeUtils.GetUserDefinedCoercionMethod(System.Type,System.Type) - - ILLink - IL2075 - member - M:System.Linq.Expressions.Compiler.LambdaCompiler.AddressOf(System.Linq.Expressions.IndexExpression,System.Type) - - - ILLink - IL2075 - member - M:System.Linq.Expressions.Compiler.LambdaCompiler.AddressOf(System.Linq.Expressions.MethodCallExpression,System.Type) - - - ILLink - IL2075 - member - M:System.Linq.Expressions.Compiler.LambdaCompiler.EmitDynamicExpression(System.Linq.Expressions.Expression) - - - ILLink - IL2075 - member - M:System.Linq.Expressions.Compiler.LambdaCompiler.EmitInvocationExpression(System.Linq.Expressions.Expression,System.Linq.Expressions.Compiler.LambdaCompiler.CompilationFlags) - - - ILLink - IL2075 - member - M:System.Linq.Expressions.Compiler.LambdaCompiler.EmitUnary(System.Linq.Expressions.UnaryExpression,System.Linq.Expressions.Compiler.LambdaCompiler.CompilationFlags) - ILLink IL2075 @@ -139,65 +79,5 @@ member M:System.Linq.Expressions.Expression.PropertyOrField(System.Linq.Expressions.Expression,System.String) - - ILLink - IL2075 - member - M:System.Linq.Expressions.ExpressionStringBuilder.VisitExtension(System.Linq.Expressions.Expression) - - - ILLink - IL2075 - member - M:System.Linq.Expressions.Interpreter.LightCompiler.CompileAddress(System.Linq.Expressions.Expression,System.Int32) - - - ILLink - IL2075 - member - M:System.Linq.Expressions.Interpreter.LightCompiler.CompileIndexAssignment(System.Linq.Expressions.BinaryExpression,System.Boolean) - - - ILLink - IL2075 - member - M:System.Linq.Expressions.Interpreter.LightCompiler.CompileInvocationExpression(System.Linq.Expressions.Expression) - - - ILLink - IL2075 - member - M:System.Linq.Expressions.Interpreter.LightCompiler.CompileMultiDimArrayAccess(System.Linq.Expressions.Expression,System.Linq.Expressions.IArgumentProvider,System.Int32) - - - ILLink - IL2075 - member - M:System.Linq.Expressions.Interpreter.LightCompiler.EmitIndexGet(System.Linq.Expressions.IndexExpression) - - - ILLink - IL2077 - member - M:System.Linq.Expressions.Interpreter.DefaultValueInstruction.Run(System.Linq.Expressions.Interpreter.InterpretedFrame) - - - ILLink - IL2077 - member - M:System.Linq.Expressions.Interpreter.InitializeLocalInstruction.MutableBox.Run(System.Linq.Expressions.Interpreter.InterpretedFrame) - - - ILLink - IL2077 - member - M:System.Linq.Expressions.Interpreter.InitializeLocalInstruction.MutableValue.Run(System.Linq.Expressions.Interpreter.InterpretedFrame) - - - ILLink - IL2080 - member - M:System.Linq.Expressions.Compiler.CompilerScope.ElementBoxStorage.#ctor(System.Linq.Expressions.Compiler.CompilerScope.Storage,System.Int32,System.Linq.Expressions.ParameterExpression) - diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeUtils.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeUtils.cs index e6cb75d8ba03c9ee77d23069c66fe3513fd58fe1..e7296b530fb99df2b84ca24991df4d0bcf2d47fb 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeUtils.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeUtils.cs @@ -29,6 +29,17 @@ public static Type GetNullableType(this Type type) return type; } + [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(Nullable<>))] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", + Justification = "The Nullable ctor will be preserved by the DynamicDependency.")] + public static ConstructorInfo GetNullableConstructor(Type nullableType, Type nonNullableType) + { + Debug.Assert(nullableType.IsNullableType()); + Debug.Assert(!nonNullableType.IsNullableType() && nonNullableType.IsValueType); + + return nullableType.GetConstructor(new Type[] { nonNullableType })!; + } + public static bool IsNullableType(this Type type) => type.IsConstructedGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>); public static bool IsNullableOrReferenceType(this Type type) => !type.IsValueType || IsNullableType(type); @@ -934,5 +945,29 @@ internal static bool IsFloatingPoint(this TypeCode typeCode) } #endif + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", + Justification = "The Array 'Get' method is dynamically constructed and is not included in IL. It is not subject to trimming.")] + public static MethodInfo GetArrayGetMethod(Type arrayType) + { + Debug.Assert(arrayType.IsArray); + return arrayType.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance)!; + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", + Justification = "The Array 'Set' method is dynamically constructed and is not included in IL. It is not subject to trimming.")] + public static MethodInfo GetArraySetMethod(Type arrayType) + { + Debug.Assert(arrayType.IsArray); + return arrayType.GetMethod("Set", BindingFlags.Public | BindingFlags.Instance)!; + } + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", + Justification = "The Array 'Address' method is dynamically constructed and is not included in IL. It is not subject to trimming.")] + public static MethodInfo GetArrayAddressMethod(Type arrayType) + { + Debug.Assert(arrayType.IsArray); + return arrayType.GetMethod("Address", BindingFlags.Public | BindingFlags.Instance)!; + } } } diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/CompilerScope.Storage.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/CompilerScope.Storage.cs index 67ae2e4a5ca319c20c1cfaaaf6425415b359c3e5..e60561d19b28a5fb8b1275116965957c8bf02d6a 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/CompilerScope.Storage.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/CompilerScope.Storage.cs @@ -110,8 +110,9 @@ internal ElementBoxStorage(Storage array, int index, ParameterExpression variabl { _array = array; _index = index; - _boxType = typeof(StrongBox<>).MakeGenericType(variable.Type); - _boxValueField = _boxType.GetField("Value")!; + Type boxType = typeof(StrongBox<>).MakeGenericType(variable.Type); + _boxValueField = boxType.GetField("Value")!; + _boxType = boxType; } internal override void EmitLoad() diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/ILGen.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/ILGen.cs index e1bb52cb908e81491f7d68bee7197d05300157d4..673e213432a725110c0c856d40e96b278028ec42 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/ILGen.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/ILGen.cs @@ -485,7 +485,7 @@ private static bool TryEmitILConstant(this ILGenerator il, object value, Type ty if (TryEmitILConstant(il, value, nonNullType)) { - il.Emit(OpCodes.Newobj, GetNullableConstructor(type, nonNullType)); + il.Emit(OpCodes.Newobj, TypeUtils.GetNullableConstructor(type, nonNullType)); return true; } @@ -826,7 +826,7 @@ private static void EmitNullableToNullableConversion(this ILGenerator il, Type t Type nnTypeTo = typeTo.GetNonNullableType(); il.EmitConvertToType(nnTypeFrom, nnTypeTo, isChecked, locals); // construct result type - ConstructorInfo ci = GetNullableConstructor(typeTo, nnTypeTo); + ConstructorInfo ci = TypeUtils.GetNullableConstructor(typeTo, nnTypeTo); il.Emit(OpCodes.Newobj, ci); labEnd = il.DefineLabel(); il.Emit(OpCodes.Br_S, labEnd); @@ -846,21 +846,10 @@ private static void EmitNonNullableToNullableConversion(this ILGenerator il, Typ Debug.Assert(typeTo.IsNullableType()); Type nnTypeTo = typeTo.GetNonNullableType(); il.EmitConvertToType(typeFrom, nnTypeTo, isChecked, locals); - ConstructorInfo ci = GetNullableConstructor(typeTo, nnTypeTo); + ConstructorInfo ci = TypeUtils.GetNullableConstructor(typeTo, nnTypeTo); il.Emit(OpCodes.Newobj, ci); } - [DynamicDependency(DynamicallyAccessedMemberTypes.PublicConstructors, typeof(Nullable<>))] - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", - Justification = "The Nullable ctor will be preserved by the DynamicDependency.")] - private static ConstructorInfo GetNullableConstructor(Type nullableType, Type nonNullableType) - { - Debug.Assert(nullableType.IsNullableType()); - Debug.Assert(!nonNullableType.IsNullableType() && nonNullableType.IsValueType); - - return nullableType.GetConstructor(new Type[] { nonNullableType })!; - } - private static void EmitNullableToNonNullableConversion(this ILGenerator il, Type typeFrom, Type typeTo, bool isChecked, ILocalCache locals) { Debug.Assert(typeFrom.IsNullableType()); diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Address.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Address.cs index 29b5b83228662160d13107d62fe1821056e7d0b1..f0587cfd6df5138d86a4e8751202761c9165a712 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Address.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Address.cs @@ -162,7 +162,6 @@ private void EmitMemberAddress(MemberInfo member, Type? objectType) _ilg.Emit(OpCodes.Ldloca, temp); } - private void AddressOf(MethodCallExpression node, Type type) { // An array index of a multi-dimensional array is represented by a call to Array.Get, @@ -172,9 +171,9 @@ private void AddressOf(MethodCallExpression node, Type type) // this situation and replace it with a call to the Address method. if (!node.Method.IsStatic && node.Object!.Type.IsArray && - node.Method == node.Object.Type.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance)) + node.Method == TypeUtils.GetArrayGetMethod(node.Object.Type)) { - MethodInfo mi = node.Object.Type.GetMethod("Address", BindingFlags.Public | BindingFlags.Instance)!; + MethodInfo mi = TypeUtils.GetArrayAddressMethod(node.Object.Type); EmitMethodCall(node.Object, mi, node); } @@ -200,7 +199,7 @@ private void AddressOf(IndexExpression node, Type type) } else { - MethodInfo address = node.Object!.Type.GetMethod("Address", BindingFlags.Public | BindingFlags.Instance)!; + MethodInfo address = TypeUtils.GetArrayAddressMethod(node.Object!.Type); EmitMethodCall(node.Object, address, node); } } diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Binary.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Binary.cs index c28f740d7f91369332c096d5b39bfe95e0b637f7..5101d8dbdeded9ccff3bc9cc7a59c95810992eed 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Binary.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Binary.cs @@ -475,10 +475,12 @@ private void EmitLiftedBinaryArithmetic(ExpressionType op, Type leftType, Type r FreeLocal(locLeft); FreeLocal(locRight); - EmitBinaryOperator(op, leftType.GetNonNullableType(), rightType.GetNonNullableType(), resultType.GetNonNullableType(), liftedToNull: false); + Type resultNonNullableType = resultType.GetNonNullableType(); + + EmitBinaryOperator(op, leftType.GetNonNullableType(), rightType.GetNonNullableType(), resultNonNullableType, liftedToNull: false); // construct result type - ConstructorInfo ci = resultType.GetConstructor(new Type[] { resultType.GetNonNullableType() })!; + ConstructorInfo ci = TypeUtils.GetNullableConstructor(resultType, resultNonNullableType); _ilg.Emit(OpCodes.Newobj, ci); _ilg.Emit(OpCodes.Stloc, locResult); _ilg.Emit(OpCodes.Br_S, labEnd); diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Expressions.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Expressions.cs index ce0cb7eb032750e07e2eaf6fe4d52fcc1d503cd0..3a1e236cc0e6e6a98168d3aa13bd615805e73d15 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Expressions.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Expressions.cs @@ -4,9 +4,11 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Dynamic.Utils; using System.Reflection; using System.Reflection.Emit; +using System.Runtime.CompilerServices; namespace System.Linq.Expressions.Compiler { @@ -183,7 +185,7 @@ private void EmitInvocationExpression(Expression expr, CompilationFlags flags) if (typeof(LambdaExpression).IsAssignableFrom(expr.Type)) { // if the invoke target is a lambda expression tree, first compile it into a delegate - expr = Expression.Call(expr, expr.Type.GetMethod("Compile", Type.EmptyTypes)!); + expr = Expression.Call(expr, LambdaExpression.GetCompileMethod(expr.Type)); } EmitMethodCall(expr, expr.Type.GetInvokeMethod(), node, CompilationFlags.EmitAsNoTail | CompilationFlags.EmitExpressionStart); @@ -311,7 +313,7 @@ private void EmitGetArrayElement(Type arrayType) else { // Multidimensional arrays, call get - _ilg.Emit(OpCodes.Call, arrayType.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance)!); + _ilg.Emit(OpCodes.Call, TypeUtils.GetArrayGetMethod(arrayType)); } } @@ -339,7 +341,7 @@ private void EmitSetArrayElement(Type arrayType) else { // Multidimensional arrays, call set - _ilg.Emit(OpCodes.Call, arrayType.GetMethod("Set", BindingFlags.Public | BindingFlags.Instance)!); + _ilg.Emit(OpCodes.Call, TypeUtils.GetArraySetMethod(arrayType)); } } @@ -602,7 +604,7 @@ private void EmitDynamicExpression(Expression expr) _ilg.Emit(OpCodes.Dup); LocalBuilder siteTemp = GetLocal(siteType); _ilg.Emit(OpCodes.Stloc, siteTemp); - _ilg.Emit(OpCodes.Ldfld, siteType.GetField("Target")!); + _ilg.Emit(OpCodes.Ldfld, GetCallSiteTargetField(siteType)); _ilg.Emit(OpCodes.Ldloc, siteTemp); FreeLocal(siteTemp); @@ -611,6 +613,15 @@ private void EmitDynamicExpression(Expression expr) EmitWriteBack(wb); } + [DynamicDependency("Target", typeof(CallSite<>))] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", + Justification = "The 'Target' field will be preserved by the DynamicDependency.")] + private static FieldInfo GetCallSiteTargetField(Type siteType) + { + Debug.Assert(siteType.IsGenericType && siteType.GetGenericTypeDefinition() == typeof(CallSite<>)); + return siteType.GetField("Target")!; + } + private void EmitNewExpression(Expression expr) { NewExpression node = (NewExpression)expr; @@ -1160,7 +1171,7 @@ private void EmitLift(ExpressionType nodeType, Type resultType, MethodCallExpres EmitMethodCallExpression(mc); if (resultType.IsNullableType() && !TypeUtils.AreEquivalent(resultType, mc.Type)) { - ConstructorInfo ci = resultType.GetConstructor(new Type[] { mc.Type })!; + ConstructorInfo ci = TypeUtils.GetNullableConstructor(resultType, mc.Type); _ilg.Emit(OpCodes.Newobj, ci); } _ilg.Emit(OpCodes.Br_S, exit); @@ -1264,7 +1275,7 @@ private void EmitLift(ExpressionType nodeType, Type resultType, MethodCallExpres EmitMethodCallExpression(mc); if (resultType.IsNullableType() && !TypeUtils.AreEquivalent(resultType, mc.Type)) { - ConstructorInfo ci = resultType.GetConstructor(new Type[] { mc.Type })!; + ConstructorInfo ci = TypeUtils.GetNullableConstructor(resultType, mc.Type); _ilg.Emit(OpCodes.Newobj, ci); } _ilg.Emit(OpCodes.Br_S, exit); diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Unary.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Unary.cs index c764b7827609b9ffb4d17edc50e4197ded1dae12..e84391a7414992dcd3ef52c3d32215abb9e9e050 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Unary.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/LambdaCompiler.Unary.cs @@ -94,7 +94,7 @@ private void EmitUnary(UnaryExpression node, CompilationFlags flags) EmitBinaryOperator(ExpressionType.SubtractChecked, nnType, nnType, nnType, liftedToNull: false); // construct result - _ilg.Emit(OpCodes.Newobj, type.GetConstructor(new Type[] { nnType })!); + _ilg.Emit(OpCodes.Newobj, TypeUtils.GetNullableConstructor(type, nnType)); _ilg.Emit(OpCodes.Br_S, end); // if null then push back on stack @@ -164,7 +164,7 @@ private void EmitUnaryOperator(ExpressionType op, Type operandType, Type resultT EmitUnaryOperator(op, nnOperandType, nnOperandType); // construct result - ConstructorInfo ci = resultType.GetConstructor(new Type[] { nnOperandType })!; + ConstructorInfo ci = TypeUtils.GetNullableConstructor(resultType, nnOperandType); _ilg.Emit(OpCodes.Newobj, ci); _ilg.Emit(OpCodes.Br_S, labEnd); diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/ExpressionStringBuilder.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/ExpressionStringBuilder.cs index 2fd6089db5c51324c7331643787863c4755f1f08..a4c704b6f81853ee5963c2043b432f1c0a1f92da 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/ExpressionStringBuilder.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/ExpressionStringBuilder.cs @@ -4,6 +4,7 @@ using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Globalization; using System.Reflection; using System.Runtime.CompilerServices; @@ -786,6 +787,8 @@ protected internal override Expression VisitIndex(IndexExpression node) return node; } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", + Justification = "The 'ToString' method cannot be trimmed on any Expression type because we are calling Expression.ToString() in this method.")] protected internal override Expression VisitExtension(Expression node) { // Prefer an overridden ToString, if available. diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DefaultValueInstruction.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DefaultValueInstruction.cs index 0eb0332753bf3b5c8b7d7e0d6136a0d62dfe16a7..fa243f2834b551009913823879bc239043424d3e 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DefaultValueInstruction.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/DefaultValueInstruction.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Dynamic.Utils; namespace System.Linq.Expressions.Interpreter @@ -21,6 +22,8 @@ internal DefaultValueInstruction(Type type) public override string InstructionName => "DefaultValue"; + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2077:UnrecognizedReflectionPattern", + Justification = "_type is a ValueType. You can always create an instance of a ValueType.")] public override int Run(InterpretedFrame frame) { frame.Push(Activator.CreateInstance(_type)); diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightCompiler.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightCompiler.cs index 6f9f915169e4d31a2098244948165207095119cb..b4238cd4711d1d33d8578a1d606caa6f83a702a7 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightCompiler.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LightCompiler.cs @@ -593,7 +593,7 @@ private void EmitIndexGet(IndexExpression index) } else if (index.ArgumentCount != 1) { - _instructions.EmitCall(index.Object!.Type.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance)!); + _instructions.EmitCall(TypeUtils.GetArrayGetMethod(index.Object!.Type)); } else { @@ -632,7 +632,7 @@ private void CompileIndexAssignment(BinaryExpression node, bool asVoid) } else if (index.ArgumentCount != 1) { - _instructions.EmitCall(index.Object!.Type.GetMethod("Set", BindingFlags.Public | BindingFlags.Instance)!); + _instructions.EmitCall(TypeUtils.GetArraySetMethod(index.Object!.Type)); } else { @@ -2343,7 +2343,7 @@ private static bool ShouldWritebackNode(Expression node) var call = (MethodCallExpression)node; if (!call.Method.IsStatic && call.Object!.Type.IsArray && - call.Method == call.Object.Type.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance)) + call.Method == TypeUtils.GetArrayGetMethod(call.Object.Type)) { return CompileMultiDimArrayAccess( call.Object, @@ -2380,9 +2380,9 @@ private ByRefUpdater CompileMultiDimArrayAccess(Expression array, IArgumentProvi indexLocals[i] = argTmp; } - _instructions.EmitCall(array.Type.GetMethod("Get", BindingFlags.Public | BindingFlags.Instance)!); + _instructions.EmitCall(TypeUtils.GetArrayGetMethod(array.Type)); - return new IndexMethodByRefUpdater(objTmp, indexLocals, array.Type.GetMethod("Set", BindingFlags.Public | BindingFlags.Instance)!, index); + return new IndexMethodByRefUpdater(objTmp, indexLocals, TypeUtils.GetArraySetMethod(array.Type), index); } private void CompileNewExpression(Expression expr) @@ -2671,7 +2671,7 @@ private void CompileInvocationExpression(Expression expr) if (typeof(LambdaExpression).IsAssignableFrom(node.Expression.Type)) { - MethodInfo compMethod = node.Expression.Type.GetMethod("Compile", Type.EmptyTypes)!; + MethodInfo compMethod = LambdaExpression.GetCompileMethod(node.Expression.Type); CompileMethodCallExpression( Expression.Call( node.Expression, diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalAccess.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalAccess.cs index 8cc0bf98ee0f040759247bbadd6eb16f87b310dd..713a48da332ab2486e743aa3c89c5da34615034f 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalAccess.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/LocalAccess.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Dynamic.Utils; using System.Reflection; using System.Runtime.CompilerServices; @@ -373,9 +374,13 @@ internal sealed class MutableValue : InitializeLocalInstruction, IBoxableInstruc internal MutableValue(int index, Type type) : base(index) { + Debug.Assert(type.IsValueType, "MutableValue only supports value types."); + _type = type; } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2077:UnrecognizedReflectionPattern", + Justification = "_type is a ValueType. You can always create an instance of a ValueType.")] public override int Run(InterpretedFrame frame) { try @@ -406,9 +411,13 @@ internal sealed class MutableBox : InitializeLocalInstruction internal MutableBox(int index, Type type) : base(index) { + Debug.Assert(type.IsValueType, "MutableBox only supports value types."); + _type = type; } + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2077:UnrecognizedReflectionPattern", + Justification = "_type is a ValueType. You can always create an instance of a ValueType.")] public override int Run(InterpretedFrame frame) { object? value; diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs index 8f50c40fd7d3a9f95e991877165a77c655bb011f..fc45b9c5ff81f872fe3933a124ed23609e21a4a0 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/LambdaExpression.cs @@ -102,6 +102,39 @@ internal virtual int ParameterCount } } + /// + /// Gets the Compile() MethodInfo on the specified LambdaExpression type. + /// + /// + /// Note that Expression{TDelegate} defines a 'new' Compile() method that hides the base + /// LambdaExpression.Compile() method. + /// + internal static MethodInfo GetCompileMethod(Type lambdaExpressionType) + { + Debug.Assert(lambdaExpressionType.IsAssignableTo(typeof(LambdaExpression))); + + if (lambdaExpressionType == typeof(LambdaExpression)) + { + // use a hard-coded type directly so the method doesn't get trimmed + return typeof(LambdaExpression).GetMethod("Compile", Type.EmptyTypes)!; + } + + return GetDerivedCompileMethod(lambdaExpressionType); + } + + [DynamicDependency("Compile()", typeof(Expression<>))] + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2070:UnrecognizedReflectionPattern", + Justification = "The 'Compile' method will be preserved by the DynamicDependency.")] + private static MethodInfo GetDerivedCompileMethod(Type lambdaExpressionType) + { + Debug.Assert(lambdaExpressionType.IsAssignableTo(typeof(LambdaExpression)) && lambdaExpressionType != typeof(LambdaExpression)); + + MethodInfo result = lambdaExpressionType.GetMethod("Compile", Type.EmptyTypes)!; + Debug.Assert(result.DeclaringType!.IsGenericType && result.DeclaringType.GetGenericTypeDefinition() == typeof(Expression<>)); + + return result; + } + /// /// Produces a delegate that represents the lambda expression. /// diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/MethodCallExpression.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/MethodCallExpression.cs index 248f63dba1d9ffe069b149f4d0fd69f1b218a5bf..b4d871b27fce83343fbcb09db36f4e5b9d3f9713 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/MethodCallExpression.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/MethodCallExpression.cs @@ -1401,8 +1401,6 @@ public static MethodCallExpression ArrayIndex(Expression array, params Expressio /// or is null. /// /// .Type does not represent an array type.-or-The rank of .Type does not match the number of elements in .-or-The property of one or more elements of does not represent the type. - [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", - Justification = "The Array 'Get' method is dynamically constructed and are not included in IL. It is not subject to trimming.")] public static MethodCallExpression ArrayIndex(Expression array, IEnumerable indexes) { ExpressionUtils.RequiresCanRead(array, nameof(array), -1); @@ -1431,7 +1429,7 @@ public static MethodCallExpression ArrayIndex(Expression array, IEnumerable