From 09cd9c2cfd21f7e830269ee7cd64ea11cbe47a1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Wed, 1 Dec 2021 14:00:56 +0900 Subject: [PATCH] Start building a universal System.Linq.Expressions library (#61952) System.Linq.Expressions currently offers multiple build time definitions to build different flavors of the library: * `FEATURE_COMPILE` (defined everywhere except iOS/tvOS/Catalyst, and NativeAOT) - enables Reflection.Emit-based expression tree compiler. * `FEATURE_INTERPRET` (always defined and not actually possible to build without) - enables the expression interpreter * `FEATURE_DLG_INVOKE` (defined everywhere except NativeAOT, but we likely need to be able to run without it on iOS too because there's uninvestigated bugs around it ActiveIssue'd in #54970) - in the interpreter, use a delegate to invoke `CallInstructions` instead of `MethodInfo.Invoke`. The delegate might have to be Reflection.Emitted if it's not supportable with `Func`/`Action` (that's the uninvestigated iOS/tvOS/Catalyst bug). For #61231, we need to be able to build a single System.Linq.Expression library that can switch between these build-time configurations _at publish time_ since we don't want to build a separate S.L.Expressions library for NativeAOT. There are advantages in having this setup for non-NativeAOT scenarios too. This pull request accomplishes that by mechanically changing the `#define`s into feature switches. The feature switch is placed in the last proposed location for https://github.com/dotnet/runtime/issues/17973. I expect we'll want such API to be public at some point; now that Xamarin and NativeAOT use this formerly .NET Native-only thing the API request became relevant again. This pull request is focused on the mechanical replacement of `#defines` with feature switches and it's already a lot bigger than I'm comfortable with. There's some obvious "`!FEATURE_COMPILE` means this is .NET Native with everything what that meant" that I did not touch because this is meant to be a mechanical change. Some cleanup will be needed at some point. Right now this just mostly means we're running fewer tests than we could. Validation: * Verified that we're still running the same number of tests with CoreCLR as we previously were and they're all passing. * Verified we're getting mostly the same size of the S.L.Expressions library on iOS (433 kB grew to 436 kB, the diffs are expected). * Verified things work on the NativeAOT side as well. --- eng/illink.targets | 2 + .../TestUtilities/System/PlatformDetection.cs | 10 +-- ...stitutions.IsInterpreting.LibraryBuild.xml | 7 ++ .../src/ILLink/ILLink.Substitutions.xml | 13 +++ .../src/MatchingRefApiCompatBaseline.txt | 4 +- .../src/System.Linq.Expressions.csproj | 20 +++-- .../Dynamic/UpdateDelegates.Generated.cs | 2 - .../Dynamic/UpdateDelegates.Generated.tt | 2 - .../System/Dynamic/Utils/DelegateHelpers.cs | 39 ++++++--- .../System/Dynamic/Utils/TypeExtensions.cs | 2 - .../src/System/Dynamic/Utils/TypeUtils.cs | 4 - .../Common/CachedReflectionInfo.cs | 2 - .../Compiler/DelegateHelpers.Generated.cs | 17 ++-- .../Expressions/Compiler/DelegateHelpers.cs | 37 ++++----- .../Interpreter/CallInstruction.Generated.cs | 7 -- .../Interpreter/CallInstruction.cs | 16 ++-- .../Linq/Expressions/LambdaExpression.cs | 79 +++++++++++-------- .../Runtime/CompilerServices/CallSite.cs | 16 +--- .../CompilerServices/DebugInfoGenerator.cs | 2 - .../Coalesce/BinaryCoalesceTests.cs | 4 +- .../Logical/BinaryLogicalTests.cs | 50 ++++++------ .../tests/Cast/CastTests.cs | 10 ++- .../tests/CompilerTests.cs | 28 +++---- .../tests/Constant/ConstantTests.cs | 16 ++-- .../DelegateType/GetDelegateTypeTests.cs | 50 ++++++------ .../tests/Dynamic/InvokeMemberBindingTests.cs | 23 +++--- .../ExceptionHandlingExpressions.cs | 19 ++--- .../tests/HelperTypes.cs | 40 ++++++---- .../IndexExpression/IndexExpressionTests.cs | 34 ++++---- .../tests/InterpreterTests.cs | 38 +++++---- .../tests/Invoke/InvocationTests.cs | 11 +-- .../tests/Lambda/LambdaTests.cs | 23 +++--- .../tests/Member/MemberAccessTests.cs | 4 +- .../tests/MemberInit/BindTests.cs | 6 +- .../tests/MemberInit/ListBindTests.cs | 5 +- .../tests/MemberInit/MemberBindTests.cs | 4 +- .../tests/New/NewTests.cs | 6 +- .../tests/New/NewWithByRefParameterTests.cs | 4 +- .../tests/StackSpillerTests.cs | 20 ++--- .../System.Linq.Expressions.Tests.csproj | 7 +- .../InlinePerCompilationTypeAttribute.cs | 9 +-- .../PerCompilationTypeAttribute.cs | 32 +++----- ...aryArithmeticNegateCheckedNullableTests.cs | 5 +- .../UnaryArithmeticNegateCheckedTests.cs | 5 +- 44 files changed, 357 insertions(+), 377 deletions(-) create mode 100644 src/libraries/System.Linq.Expressions/src/ILLink/ILLink.Substitutions.IsInterpreting.LibraryBuild.xml create mode 100644 src/libraries/System.Linq.Expressions/src/ILLink/ILLink.Substitutions.xml diff --git a/eng/illink.targets b/eng/illink.targets index 6c2d95c847723..018075d8b660b 100644 --- a/eng/illink.targets +++ b/eng/illink.targets @@ -236,6 +236,7 @@ $(ILLinkArgs) -b true $(ILLinkArgs) -x "$(ILLinkDescriptorsLibraryBuildXml)" + $(ILLinkArgs) --substitutions "$(ILLinkSubstitutionsLibraryBuildXml)" $(LinkerNoWarn);IL2067;IL2068;IL2069;IL2070;IL2071;IL2072;IL2073;IL2074;IL2075;IL2076;IL2077;IL2078;IL2079;IL2080;IL2081;IL2082;IL2083;IL2084;IL2085;IL2086;IL2087;IL2088;IL2089;IL2090;IL2091 $(ILLinkArgs) --nowarn $(LinkerNoWarn) + $(ILLinkArgs) --disable-opt ipconstprop diff --git a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs index b153e3f525e6a..b38d35ebc3440 100644 --- a/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs +++ b/src/libraries/Common/tests/TestUtilities/System/PlatformDetection.cs @@ -82,15 +82,7 @@ public static partial class PlatformDetection private static readonly Lazy s_LinqExpressionsBuiltWithIsInterpretingOnly = new Lazy(GetLinqExpressionsBuiltWithIsInterpretingOnly); private static bool GetLinqExpressionsBuiltWithIsInterpretingOnly() { - Type type = typeof(LambdaExpression); - if (type != null) - { - // The "Accept" method is under FEATURE_COMPILE conditional so it should not exist - MethodInfo methodInfo = type.GetMethod("Accept", BindingFlags.NonPublic | BindingFlags.Static); - return methodInfo == null; - } - - return false; + return !(bool)typeof(LambdaExpression).GetMethod("get_CanCompileToIL").Invoke(null, Array.Empty()); } // Please make sure that you have the libgdiplus dependency installed. diff --git a/src/libraries/System.Linq.Expressions/src/ILLink/ILLink.Substitutions.IsInterpreting.LibraryBuild.xml b/src/libraries/System.Linq.Expressions/src/ILLink/ILLink.Substitutions.IsInterpreting.LibraryBuild.xml new file mode 100644 index 0000000000000..67051cc12615d --- /dev/null +++ b/src/libraries/System.Linq.Expressions/src/ILLink/ILLink.Substitutions.IsInterpreting.LibraryBuild.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/src/libraries/System.Linq.Expressions/src/ILLink/ILLink.Substitutions.xml b/src/libraries/System.Linq.Expressions/src/ILLink/ILLink.Substitutions.xml new file mode 100644 index 0000000000000..2847ed81708c2 --- /dev/null +++ b/src/libraries/System.Linq.Expressions/src/ILLink/ILLink.Substitutions.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/libraries/System.Linq.Expressions/src/MatchingRefApiCompatBaseline.txt b/src/libraries/System.Linq.Expressions/src/MatchingRefApiCompatBaseline.txt index 23c307afa036c..855d90ec23c39 100644 --- a/src/libraries/System.Linq.Expressions/src/MatchingRefApiCompatBaseline.txt +++ b/src/libraries/System.Linq.Expressions/src/MatchingRefApiCompatBaseline.txt @@ -15,4 +15,6 @@ TypesMustExist : Type 'System.Linq.Expressions.Interpreter.LightLambda' does not TypesMustExist : Type 'System.Runtime.CompilerServices.CallSiteOps' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Runtime.CompilerServices.Closure' does not exist in the reference but it does exist in the implementation. TypesMustExist : Type 'System.Runtime.CompilerServices.RuntimeOps' does not exist in the reference but it does exist in the implementation. -Total Issues: 16 +MembersMustExist : Member 'public System.Boolean System.Linq.Expressions.LambdaExpression.CanCompileToIL.get()' does not exist in the reference but it does exist in the implementation. +MembersMustExist : Member 'public System.Boolean System.Linq.Expressions.LambdaExpression.CanInterpret.get()' does not exist in the reference but it does exist in the implementation. +Total Issues: 18 diff --git a/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj b/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj index 0a9d7eba08b66..dce8fedbf2ac8 100644 --- a/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj +++ b/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj @@ -1,14 +1,22 @@ - true $(NetCoreAppCurrent);$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-MacCatalyst enable false true - $(DefineConstants);FEATURE_DLG_INVOKE;FEATURE_FAST_CREATE - $(DefineConstants);FEATURE_COMPILE - $(DefineConstants);FEATURE_INTERPRET + ILLink\ILLink.Substitutions.IsInterpreting.LibraryBuild.xml + $(DefineConstants);FEATURE_FAST_CREATE + + + true + + + @@ -125,7 +133,7 @@ - + @@ -157,7 +165,7 @@ - + diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/UpdateDelegates.Generated.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/UpdateDelegates.Generated.cs index f54a21adb7a4f..2969348e143dc 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/UpdateDelegates.Generated.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/UpdateDelegates.Generated.cs @@ -7,7 +7,6 @@ namespace System.Dynamic { internal static partial class UpdateDelegates { -#if FEATURE_COMPILE [Obsolete("pregenerated CallSite.Update delegate", error: true)] internal static TRet UpdateAndExecute1(CallSite site, T0 arg0) { @@ -2895,6 +2894,5 @@ internal static void NoMatchVoid10(CallS site._match = false; return; } -#endif } } diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/UpdateDelegates.Generated.tt b/src/libraries/System.Linq.Expressions/src/System/Dynamic/UpdateDelegates.Generated.tt index 44c6c3fc62802..ae41482f94899 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/UpdateDelegates.Generated.tt +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/UpdateDelegates.Generated.tt @@ -13,7 +13,6 @@ namespace System.Dynamic { internal static partial class UpdateDelegates { -#if FEATURE_COMPILE <# for (int i = 1; i <= 10; i++) { @@ -330,6 +329,5 @@ for (int i = 1; i <= 10; i++) } } #> -#endif } } diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/DelegateHelpers.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/DelegateHelpers.cs index cd3446767c633..b46fa67682891 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/DelegateHelpers.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/DelegateHelpers.cs @@ -3,28 +3,43 @@ using System.Diagnostics.CodeAnalysis; using System.Reflection; - -#if !FEATURE_DYNAMIC_DELEGATE using System.Reflection.Emit; using System.Text; using System.Threading; -#endif namespace System.Dynamic.Utils { internal static class DelegateHelpers { - internal static Delegate CreateObjectArrayDelegate(Type delegateType, Func handler) + // This can be flipped to true using feature switches at publishing time + internal static bool CanEmitObjectArrayDelegate => true; + + // Separate class so that the it can be trimmed away and doesn't get conflated + // with the Reflection.Emit statics below. + private static class DynamicDelegateLightup { -#if !FEATURE_DYNAMIC_DELEGATE - return CreateObjectArrayDelegateRefEmit(delegateType, handler); -#else - return Internal.Runtime.Augments.DynamicDelegateAugments.CreateObjectArrayDelegate(delegateType, handler); -#endif + public static Func, Delegate> CreateObjectArrayDelegate { get; } + = CreateObjectArrayDelegateInternal(); + + [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2075:UnrecognizedReflectionPattern", + Justification = "Works around https://github.com/dotnet/linker/issues/2392")] + private static Func, Delegate> CreateObjectArrayDelegateInternal() + => Type.GetType("Internal.Runtime.Augments.DynamicDelegateAugments")! + .GetMethod("CreateObjectArrayDelegate")! + .CreateDelegate, Delegate>>(); } - -#if !FEATURE_DYNAMIC_DELEGATE + internal static Delegate CreateObjectArrayDelegate(Type delegateType, Func handler) + { + if (CanEmitObjectArrayDelegate) + { + return CreateObjectArrayDelegateRefEmit(delegateType, handler); + } + else + { + return DynamicDelegateLightup.CreateObjectArrayDelegate(delegateType, handler); + } + } private static readonly CacheDict s_thunks = new CacheDict(256); private static readonly MethodInfo s_FuncInvoke = typeof(Func).GetMethod("Invoke")!; @@ -290,7 +305,5 @@ private static Type ConvertToBoxableType(Type t) { return (t.IsPointer) ? typeof(IntPtr) : t; } - -#endif } } diff --git a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeExtensions.cs b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeExtensions.cs index 4b57dba01726a..71244b2a67d85 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeExtensions.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Dynamic/Utils/TypeExtensions.cs @@ -80,7 +80,6 @@ internal static ParameterInfo[] GetParametersCached(this MethodBase method) return pis; } -#if FEATURE_COMPILE // Expression trees/compiler just use IsByRef, why do we need this? // (see LambdaCompiler.EmitArguments for usage in the compiler) internal static bool IsByRefParameter(this ParameterInfo pi) @@ -91,6 +90,5 @@ internal static bool IsByRefParameter(this ParameterInfo pi) return (pi.Attributes & ParameterAttributes.Out) == ParameterAttributes.Out; } -#endif } } 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 f676a13dce7ee..1d0fca59e3068 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 @@ -911,8 +911,6 @@ public static MethodInfo GetInvokeMethod(this Type delegateType) return delegateType.GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)!; } -#if FEATURE_COMPILE - internal static bool IsUnsigned(this Type type) => IsUnsigned(GetNonNullableType(type).GetTypeCode()); internal static bool IsUnsigned(this TypeCode typeCode) @@ -946,8 +944,6 @@ 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) diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Common/CachedReflectionInfo.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Common/CachedReflectionInfo.cs index 752ed754007c1..f26c16b3e448a 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Common/CachedReflectionInfo.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Common/CachedReflectionInfo.cs @@ -159,7 +159,6 @@ public static FieldInfo DateTime_MinValue (s_Math_Pow_Double_Double = typeof(Math).GetMethod(nameof(Math.Pow), new[] { typeof(double), typeof(double) })!); // Closure and RuntimeOps helpers are used only in the compiler. -#if FEATURE_COMPILE private static ConstructorInfo? s_Closure_ObjectArray_ObjectArray; public static ConstructorInfo Closure_ObjectArray_ObjectArray => s_Closure_ObjectArray_ObjectArray ?? @@ -194,6 +193,5 @@ public static FieldInfo DateTime_MinValue public static MethodInfo RuntimeOps_Quote => s_RuntimeOps_Quote ?? (s_RuntimeOps_Quote = typeof(RuntimeOps).GetMethod(nameof(RuntimeOps.Quote))!); -#endif } } diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.Generated.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.Generated.cs index 6e6a915e76e98..8884a2774951a 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.Generated.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.Generated.cs @@ -84,8 +84,6 @@ private static TypeInfo NextTypeInfo(Type initialArg, TypeInfo curTypeInfo) return nextTypeInfo; } -#if !FEATURE_COMPILE - public delegate object VBCallSiteDelegate0(T callSite, object instance); public delegate object VBCallSiteDelegate1(T callSite, object instance, ref object arg1); public delegate object VBCallSiteDelegate2(T callSite, object instance, ref object arg1, ref object arg2); @@ -95,7 +93,6 @@ private static TypeInfo NextTypeInfo(Type initialArg, TypeInfo curTypeInfo) public delegate object VBCallSiteDelegate6(T callSite, object instance, ref object arg1, ref object arg2, ref object arg3, ref object arg4, ref object arg5, ref object arg6); public delegate object VBCallSiteDelegate7(T callSite, object instance, ref object arg1, ref object arg2, ref object arg3, ref object arg4, ref object arg5, ref object arg6, ref object arg7); - private static Type TryMakeVBStyledCallSite(Type[] types) { // Shape of VB CallSiteDelegates is CallSite * (instance : obj) * [arg-n : byref obj] -> obj @@ -128,7 +125,6 @@ private static Type TryMakeVBStyledCallSite(Type[] types) default: return null; } } -#endif /// /// Creates a new delegate, or uses a func/action @@ -163,11 +159,14 @@ internal static Type MakeNewDelegate(Type[] types) if (needCustom) { -#if FEATURE_COMPILE - return MakeNewCustomDelegate(types); -#else - return TryMakeVBStyledCallSite(types) ?? MakeNewCustomDelegate(types); -#endif + if (LambdaExpression.CanCompileToIL) + { + return MakeNewCustomDelegate(types); + } + else + { + return TryMakeVBStyledCallSite(types) ?? MakeNewCustomDelegate(types); + } } Type result; diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.cs index f1cb6e844bb90..35dae2e3a1102 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Compiler/DelegateHelpers.cs @@ -107,26 +107,27 @@ private static bool IsByRef(DynamicMetaObject mo) return mo.Expression is ParameterExpression pe && pe.IsByRef; } -#if FEATURE_COMPILE - private const MethodAttributes CtorAttributes = MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public; - private const MethodImplAttributes ImplAttributes = MethodImplAttributes.Runtime | MethodImplAttributes.Managed; - private const MethodAttributes InvokeAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual; - private static readonly Type[] s_delegateCtorSignature = { typeof(object), typeof(IntPtr) }; -#endif - private static Type MakeNewCustomDelegate(Type[] types) { -#if FEATURE_COMPILE - Type returnType = types[types.Length - 1]; - Type[] parameters = types.RemoveLast(); - - TypeBuilder builder = AssemblyGen.DefineDelegateType("Delegate" + types.Length); - builder.DefineConstructor(CtorAttributes, CallingConventions.Standard, s_delegateCtorSignature).SetImplementationFlags(ImplAttributes); - builder.DefineMethod("Invoke", InvokeAttributes, returnType, parameters).SetImplementationFlags(ImplAttributes); - return builder.CreateTypeInfo()!; -#else - throw new PlatformNotSupportedException(); -#endif + if (LambdaExpression.CanCompileToIL) + { + Type returnType = types[types.Length - 1]; + Type[] parameters = types.RemoveLast(); + Type[] delegateCtorSignature = { typeof(object), typeof(IntPtr) }; + + const MethodAttributes ctorAttributes = MethodAttributes.RTSpecialName | MethodAttributes.HideBySig | MethodAttributes.Public; + const MethodImplAttributes implAttributes = MethodImplAttributes.Runtime | MethodImplAttributes.Managed; + const MethodAttributes invokeAttributes = MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.NewSlot | MethodAttributes.Virtual; + + TypeBuilder builder = AssemblyGen.DefineDelegateType("Delegate" + types.Length); + builder.DefineConstructor(ctorAttributes, CallingConventions.Standard, delegateCtorSignature).SetImplementationFlags(implAttributes); + builder.DefineMethod("Invoke", invokeAttributes, returnType, parameters).SetImplementationFlags(implAttributes); + return builder.CreateTypeInfo()!; + } + else + { + throw new PlatformNotSupportedException(); + } } } } diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.Generated.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.Generated.cs index e9855aebed634..34203b5512d28 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.Generated.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.Generated.cs @@ -13,9 +13,7 @@ namespace System.Linq.Expressions.Interpreter { internal partial class CallInstruction { -#if FEATURE_DLG_INVOKE private const int MaxHelpers = 5; -#endif #if FEATURE_FAST_CREATE private const int MaxArgs = 3; @@ -158,7 +156,6 @@ private static CallInstruction FastCreate(MethodInfo target, ParameterIn } #endif -#if FEATURE_DLG_INVOKE [return: DynamicallyAccessedMembersAttribute(DynamicallyAccessedMemberTypes.PublicConstructors)] private static Type GetHelperType(MethodInfo info, Type[] arrTypes) { @@ -211,10 +208,8 @@ private static Type GetHelperType(MethodInfo info, Type[] arrTypes) } return t; } -#endif } -#if FEATURE_DLG_INVOKE internal sealed class ActionCallInstruction : CallInstruction { private readonly Action _target; @@ -577,6 +572,4 @@ public override int Run(InterpretedFrame frame) public override string ToString() => "Call(" + _target.Method + ")"; } - -#endif } diff --git a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.cs b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.cs index f10233360deb0..42ecb44bb8489 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Linq/Expressions/Interpreter/CallInstruction.cs @@ -16,13 +16,13 @@ internal abstract partial class CallInstruction : Instruction /// public abstract int ArgumentCount { get; } + private static bool CanCreateArbitraryDelegates => true; + #region Construction public override string InstructionName => "Call"; -#if FEATURE_DLG_INVOKE private static readonly CacheDict s_cache = new CacheDict(256); -#endif public static CallInstruction Create(MethodInfo info) { @@ -47,9 +47,9 @@ public static CallInstruction Create(MethodInfo info, ParameterInfo[] parameters return GetArrayAccessor(info, argumentCount); } -#if !FEATURE_DLG_INVOKE - return new MethodInfoCallInstruction(info, argumentCount); -#else + if (!CanCreateArbitraryDelegates) + return new MethodInfoCallInstruction(info, argumentCount); + if (!info.IsStatic && info.DeclaringType!.IsValueType) { return new MethodInfoCallInstruction(info, argumentCount); @@ -119,7 +119,6 @@ public static CallInstruction Create(MethodInfo info, ParameterInfo[] parameters } return res; -#endif } private static CallInstruction GetArrayAccessor(MethodInfo info, int argumentCount) @@ -171,12 +170,11 @@ public static void ArrayItemSetter3(Array array, int index0, int index1, int ind { array.SetValue(value, index0, index1, index2); } -#if FEATURE_DLG_INVOKE + private static bool ShouldCache(MethodInfo info) { return true; } -#endif #if FEATURE_FAST_CREATE /// @@ -215,7 +213,6 @@ private static bool IndexIsNotReturnType(int index, MethodInfo target, Parameter } #endif -#if FEATURE_DLG_INVOKE /// /// Uses reflection to create new instance of the appropriate ReflectedCaller /// @@ -243,7 +240,6 @@ private static CallInstruction SlowCreate(MethodInfo info, ParameterInfo[] pis) throw ContractUtils.Unreachable; } } -#endif #endregion 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 0c591d6f3ae05..35c0c9cb92874 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 @@ -25,6 +25,12 @@ public abstract class LambdaExpression : Expression, IParameterProvider private readonly Expression _body; + // This can be flipped to false using feature switches at publishing time + public static bool CanCompileToIL => true; + + // This could be flipped to false using feature switches at publishing time + public static bool CanInterpret => true; + internal LambdaExpression(Expression body) { _body = body; @@ -130,11 +136,15 @@ internal static MethodInfo GetCompileMethod(Type lambdaExpressionType) /// A delegate containing the compiled version of the lambda. public Delegate Compile() { -#if FEATURE_COMPILE - return Compiler.LambdaCompiler.Compile(this); -#else - return new Interpreter.LightCompiler().CompileTop(this).CreateDelegate(); -#endif + if (CanCompileToIL) + { + return Compiler.LambdaCompiler.Compile(this); + } + else + { + Debug.Assert(CanInterpret); + return new Interpreter.LightCompiler().CompileTop(this).CreateDelegate(); + } } /// @@ -144,12 +154,11 @@ public Delegate Compile() /// A delegate containing the compiled version of the lambda. public Delegate Compile(bool preferInterpretation) { -#if FEATURE_COMPILE && FEATURE_INTERPRET - if (preferInterpretation) + if (CanCompileToIL && CanInterpret && preferInterpretation) { return new Interpreter.LightCompiler().CompileTop(this).CreateDelegate(); } -#endif + return Compile(); } @@ -169,10 +178,7 @@ public void CompileToMethod(System.Reflection.Emit.MethodBuilder method) } #endif - -#if FEATURE_COMPILE internal abstract LambdaExpression Accept(Compiler.StackSpiller spiller); -#endif /// /// Produces a delegate that represents the lambda expression. @@ -210,11 +216,15 @@ internal Expression(Expression body) /// A delegate containing the compiled version of the lambda. public new TDelegate Compile() { -#if FEATURE_COMPILE - return (TDelegate)(object)Compiler.LambdaCompiler.Compile(this); -#else - return (TDelegate)(object)new Interpreter.LightCompiler().CompileTop(this).CreateDelegate(); -#endif + if (CanCompileToIL) + { + return (TDelegate)(object)Compiler.LambdaCompiler.Compile(this); + } + else + { + Debug.Assert(CanInterpret); + return (TDelegate)(object)new Interpreter.LightCompiler().CompileTop(this).CreateDelegate(); + } } /// @@ -224,12 +234,11 @@ internal Expression(Expression body) /// A delegate containing the compiled version of the lambda. public new TDelegate Compile(bool preferInterpretation) { -#if FEATURE_COMPILE && FEATURE_INTERPRET - if (preferInterpretation) + if (CanCompileToIL && CanInterpret && preferInterpretation) { return (TDelegate)(object)new Interpreter.LightCompiler().CompileTop(this).CreateDelegate(); } -#endif + return Compile(); } @@ -290,7 +299,6 @@ protected internal override Expression Accept(ExpressionVisitor visitor) return visitor.VisitLambda(this); } -#if FEATURE_COMPILE internal override LambdaExpression Accept(Compiler.StackSpiller spiller) { return spiller.Rewrite(this); @@ -312,7 +320,6 @@ internal static Expression Create(Expression body, string? name, bool return new FullExpression(body, name, tailCall, parameters); } -#endif /// /// Produces a delegate that represents the lambda expression. @@ -325,7 +332,6 @@ internal static Expression Create(Expression body, string? name, bool } } -#if !FEATURE_COMPILE // Separate expression creation class to hide the CreateExpressionFunc function from users reflecting on Expression internal static class ExpressionCreator { @@ -346,7 +352,6 @@ public static Expression CreateExpressionFunc(Expression body, string return new FullExpression(body, name, tailCall, parameters); } } -#endif internal sealed class Expression0 : Expression { @@ -616,11 +621,16 @@ internal static LambdaExpression CreateLambda(Type delegateType, Expression body if (!factories.TryGetValue(delegateType, out fastPath)) { -#if FEATURE_COMPILE - MethodInfo create = typeof(Expression<>).MakeGenericType(delegateType).GetMethod("Create", BindingFlags.Static | BindingFlags.NonPublic)!; -#else - MethodInfo create = typeof(ExpressionCreator<>).MakeGenericType(delegateType).GetMethod("CreateExpressionFunc", BindingFlags.Static | BindingFlags.Public)!; -#endif + MethodInfo create; + if (LambdaExpression.CanCompileToIL) + { + create = typeof(Expression<>).MakeGenericType(delegateType).GetMethod("Create", BindingFlags.Static | BindingFlags.NonPublic)!; + } + else + { + create = typeof(ExpressionCreator<>).MakeGenericType(delegateType).GetMethod("CreateExpressionFunc", BindingFlags.Static | BindingFlags.Public)!; + } + if (delegateType.IsCollectible) { return (LambdaExpression)create.Invoke(null, new object?[] { body, name, tailCall, parameters })!; @@ -708,11 +718,14 @@ public static Expression Lambda(Expression body, string? n { ReadOnlyCollection parameterList = parameters.ToReadOnly(); ValidateLambdaArgs(typeof(TDelegate), ref body, parameterList, nameof(TDelegate)); -#if FEATURE_COMPILE - return Expression.Create(body, name, tailCall, parameterList); -#else - return ExpressionCreator.CreateExpressionFunc(body, name, tailCall, parameterList); -#endif + if (LambdaExpression.CanCompileToIL) + { + return Expression.Create(body, name, tailCall, parameterList); + } + else + { + return ExpressionCreator.CreateExpressionFunc(body, name, tailCall, parameterList); + } } /// diff --git a/src/libraries/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSite.cs b/src/libraries/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSite.cs index 13d01aeb3cec2..e89265ab73334 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSite.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Runtime/CompilerServices/CallSite.cs @@ -279,24 +279,15 @@ internal void MoveRule(int i) } } -#if FEATURE_COMPILE [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:MakeGenericMethod", Justification = "UpdateDelegates methods don't have ILLink annotations.")] -#endif internal T MakeUpdateDelegate() { -#if !FEATURE_COMPILE Type target = typeof(T); MethodInfo invoke = target.GetInvokeMethod(); - s_cachedNoMatch = CreateCustomNoMatchDelegate(invoke); - return CreateCustomUpdateDelegate(invoke); -#else - Type target = typeof(T); - Type[] args; - MethodInfo invoke = target.GetInvokeMethod(); - - if (target.IsGenericType && IsSimpleSignature(invoke, out args)) + if (System.Linq.Expressions.LambdaExpression.CanCompileToIL + && target.IsGenericType && IsSimpleSignature(invoke, out Type[] args)) { MethodInfo? method = null; MethodInfo? noMatchMethod = null; @@ -326,10 +317,8 @@ internal T MakeUpdateDelegate() s_cachedNoMatch = CreateCustomNoMatchDelegate(invoke); return CreateCustomUpdateDelegate(invoke); -#endif } -#if FEATURE_COMPILE private static bool IsSimpleSignature(MethodInfo invoke, out Type[] sig) { ParameterInfo[] pis = invoke.GetParametersCached(); @@ -354,7 +343,6 @@ private static bool IsSimpleSignature(MethodInfo invoke, out Type[] sig) sig = args; return supported; } -#endif [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2060:MakeGenericMethod", Justification = "CallSiteOps methods don't have trimming annotations.")] diff --git a/src/libraries/System.Linq.Expressions/src/System/Runtime/CompilerServices/DebugInfoGenerator.cs b/src/libraries/System.Linq.Expressions/src/System/Runtime/CompilerServices/DebugInfoGenerator.cs index a1bd0c8c45fc5..7b8127295d504 100644 --- a/src/libraries/System.Linq.Expressions/src/System/Runtime/CompilerServices/DebugInfoGenerator.cs +++ b/src/libraries/System.Linq.Expressions/src/System/Runtime/CompilerServices/DebugInfoGenerator.cs @@ -32,7 +32,6 @@ public static DebugInfoGenerator CreatePdbGenerator() /// Debug information corresponding to the sequence point. public abstract void MarkSequencePoint(LambdaExpression method, int ilOffset, DebugInfoExpression sequencePoint); -#if FEATURE_COMPILE internal virtual void MarkSequencePoint(LambdaExpression method, MethodBase methodBase, ILGenerator ilg, DebugInfoExpression sequencePoint) { MarkSequencePoint(method, ilg.ILOffset, sequencePoint); @@ -42,6 +41,5 @@ internal virtual void SetLocalName(LocalBuilder localBuilder, string name) { // nop } -#endif } } diff --git a/src/libraries/System.Linq.Expressions/tests/BinaryOperators/Coalesce/BinaryCoalesceTests.cs b/src/libraries/System.Linq.Expressions/tests/BinaryOperators/Coalesce/BinaryCoalesceTests.cs index bbe954f78a1d3..50131d51cbc25 100644 --- a/src/libraries/System.Linq.Expressions/tests/BinaryOperators/Coalesce/BinaryCoalesceTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/BinaryOperators/Coalesce/BinaryCoalesceTests.cs @@ -494,8 +494,7 @@ public static void CoalesceReferenceToValueType(bool useInterpreter) Assert.Equal(1, func()); } -#if FEATURE_COMPILE - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [ActiveIssue("https://github.com/mono/mono/issues/14919", TestRuntimes.Mono)] public static void VerifyIL_NullableIntCoalesceToNullableInt() { @@ -523,7 +522,6 @@ [0] valuetype [System.Private.CoreLib]System.Nullable`1 IL_0015: ret }"); } -#endif [Theory, ClassData(typeof(CompilationTypes))] public static void CoalesceWideningLeft(bool useInterpreter) diff --git a/src/libraries/System.Linq.Expressions/tests/BinaryOperators/Logical/BinaryLogicalTests.cs b/src/libraries/System.Linq.Expressions/tests/BinaryOperators/Logical/BinaryLogicalTests.cs index ea2ebbb60b8ca..c1db2afa8e146 100644 --- a/src/libraries/System.Linq.Expressions/tests/BinaryOperators/Logical/BinaryLogicalTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/BinaryOperators/Logical/BinaryLogicalTests.cs @@ -415,9 +415,7 @@ public static void MethodDeclaringTypeHasNoTrueFalseOperator_ThrowsArgumentExcep AssertExtensions.Throws(null, () => Expression.OrElse(Expression.Constant(5), Expression.Constant(5), method)); } -#if FEATURE_COMPILE - - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void AndAlso_NoMethod_NotStatic_ThrowsInvalidOperationException() { TypeBuilder type = GetTypeBuilder(); @@ -430,7 +428,7 @@ public static void AndAlso_NoMethod_NotStatic_ThrowsInvalidOperationException() Assert.Throws(() => Expression.AndAlso(Expression.Constant(obj), Expression.Constant(obj))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void OrElse_NoMethod_NotStatic_ThrowsInvalidOperationException() { TypeBuilder type = GetTypeBuilder(); @@ -443,7 +441,7 @@ public static void OrElse_NoMethod_NotStatic_ThrowsInvalidOperationException() Assert.Throws(() => Expression.OrElse(Expression.Constant(obj), Expression.Constant(obj))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void AndAlso_NoMethod_VoidReturnType_ThrowsArgumentException() { TypeBuilder type = GetTypeBuilder(); @@ -456,7 +454,7 @@ public static void AndAlso_NoMethod_VoidReturnType_ThrowsArgumentException() AssertExtensions.Throws("method", () => Expression.AndAlso(Expression.Constant(obj), Expression.Constant(obj))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void OrElse_NoMethod_VoidReturnType_ThrowsArgumentException() { TypeBuilder type = GetTypeBuilder(); @@ -469,7 +467,7 @@ public static void OrElse_NoMethod_VoidReturnType_ThrowsArgumentException() AssertExtensions.Throws("method", () => Expression.OrElse(Expression.Constant(obj), Expression.Constant(obj))); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [InlineData(0)] [InlineData(1)] [InlineData(3)] @@ -485,7 +483,7 @@ public static void AndAlso_NoMethod_DoesntHaveTwoParameters_ThrowsInvalidOperati Assert.Throws(() => Expression.AndAlso(Expression.Constant(obj), Expression.Constant(obj))); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [InlineData(0)] [InlineData(1)] [InlineData(3)] @@ -501,7 +499,7 @@ public static void OrElse_NoMethod_DoesntHaveTwoParameters_ThrowsInvalidOperatio Assert.Throws(() => Expression.OrElse(Expression.Constant(obj), Expression.Constant(obj))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void AndAlso_NoMethod_ExpressionDoesntMatchMethodParameters_ThrowsInvalidOperationException() { TypeBuilder type = GetTypeBuilder(); @@ -514,7 +512,7 @@ public static void AndAlso_NoMethod_ExpressionDoesntMatchMethodParameters_Throws Assert.Throws(() => Expression.AndAlso(Expression.Constant(obj), Expression.Constant(obj))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void OrElse_NoMethod_ExpressionDoesntMatchMethodParameters_ThrowsInvalidOperationException() { TypeBuilder type = GetTypeBuilder(); @@ -528,7 +526,7 @@ public static void OrElse_NoMethod_ExpressionDoesntMatchMethodParameters_ThrowsI } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void AndAlso_NoMethod_ReturnTypeNotEqualToParameterTypes_ThrowsArgumentException() { TypeBuilder type = GetTypeBuilder(); @@ -541,7 +539,7 @@ public static void AndAlso_NoMethod_ReturnTypeNotEqualToParameterTypes_ThrowsArg AssertExtensions.Throws(null, () => Expression.AndAlso(Expression.Constant(obj), Expression.Constant(obj))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void OrElse_NoMethod_ReturnTypeNotEqualToParameterTypes_ThrowsArgumentException() { TypeBuilder type = GetTypeBuilder(); @@ -571,7 +569,7 @@ public static IEnumerable Operator_IncorrectMethod_TestData() yield return new object[] { GetTypeBuilder(), typeof(bool), new Type[0] }; } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [MemberData(nameof(Operator_IncorrectMethod_TestData))] public static void Method_TrueOperatorIncorrectMethod_ThrowsArgumentException(TypeBuilder builder, Type returnType, Type[] parameterTypes) { @@ -592,7 +590,7 @@ public static void Method_TrueOperatorIncorrectMethod_ThrowsArgumentException(Ty AssertExtensions.Throws(null, () => Expression.OrElse(Expression.Constant(obj), Expression.Constant(obj), createdMethod)); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [MemberData(nameof(Operator_IncorrectMethod_TestData))] public static void Method_FalseOperatorIncorrectMethod_ThrowsArgumentException(TypeBuilder builder, Type returnType, Type[]parameterTypes) { @@ -613,7 +611,7 @@ public static void Method_FalseOperatorIncorrectMethod_ThrowsArgumentException(T AssertExtensions.Throws(null, () => Expression.OrElse(Expression.Constant(obj), Expression.Constant(obj), createdMethod)); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [MemberData(nameof(Operator_IncorrectMethod_TestData))] public static void AndAlso_NoMethod_TrueOperatorIncorrectMethod_ThrowsArgumentException(TypeBuilder builder, Type returnType, Type[] parameterTypes) { @@ -632,7 +630,7 @@ public static void AndAlso_NoMethod_TrueOperatorIncorrectMethod_ThrowsArgumentEx AssertExtensions.Throws(null, () => Expression.AndAlso(Expression.Constant(obj), Expression.Constant(obj))); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [MemberData(nameof(Operator_IncorrectMethod_TestData))] public static void OrElse_NoMethod_TrueOperatorIncorrectMethod_ThrowsArgumentException(TypeBuilder builder, Type returnType, Type[] parameterTypes) { @@ -651,7 +649,7 @@ public static void OrElse_NoMethod_TrueOperatorIncorrectMethod_ThrowsArgumentExc AssertExtensions.Throws(null, () => Expression.OrElse(Expression.Constant(obj), Expression.Constant(obj))); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [InlineData("op_True")] [InlineData("op_False")] public static void Method_NoTrueFalseOperator_ThrowsArgumentException(string name) @@ -674,7 +672,7 @@ public static void Method_NoTrueFalseOperator_ThrowsArgumentException(string nam AssertExtensions.Throws(null, () => Expression.OrElse(Expression.Constant(obj), Expression.Constant(obj), createdMethod)); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [InlineData("op_True")] [InlineData("op_False")] public static void AndAlso_NoMethod_NoTrueFalseOperator_ThrowsArgumentException(string name) @@ -694,7 +692,7 @@ public static void AndAlso_NoMethod_NoTrueFalseOperator_ThrowsArgumentException( AssertExtensions.Throws(null, () => Expression.AndAlso(Expression.Constant(obj), Expression.Constant(obj))); } - [Theory] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [InlineData("op_True")] [InlineData("op_False")] public static void OrElse_NoMethod_NoTrueFalseOperator_ThrowsArgumentException(string name) @@ -714,7 +712,7 @@ public static void OrElse_NoMethod_NoTrueFalseOperator_ThrowsArgumentException(s AssertExtensions.Throws(null, () => Expression.OrElse(Expression.Constant(obj), Expression.Constant(obj))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void Method_ParamsDontMatchOperator_ThrowsInvalidOperationException() { TypeBuilder builder = GetTypeBuilder(); @@ -735,7 +733,7 @@ public static void Method_ParamsDontMatchOperator_ThrowsInvalidOperationExceptio Assert.Throws(() => Expression.OrElse(Expression.Constant(5), Expression.Constant(5), createdMethod)); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void AndAlso_NoMethod_ParamsDontMatchOperator_ThrowsInvalidOperationException() { TypeBuilder builder = GetTypeBuilder(); @@ -753,7 +751,7 @@ public static void AndAlso_NoMethod_ParamsDontMatchOperator_ThrowsInvalidOperati Assert.Throws(() => Expression.OrElse(Expression.Constant(5), Expression.Constant(5))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void OrElse_NoMethod_ParamsDontMatchOperator_ThrowsInvalidOperationException() { TypeBuilder builder = GetTypeBuilder(); @@ -771,8 +769,6 @@ public static void OrElse_NoMethod_ParamsDontMatchOperator_ThrowsInvalidOperatio Assert.Throws(() => Expression.OrElse(Expression.Constant(5), Expression.Constant(5))); } -#endif - [Fact] public static void ImplicitConversionToBool_ThrowsArgumentException() { @@ -821,15 +817,14 @@ public static void ToStringTest() Assert.Equal("(a OrElse b)", e2.ToString()); } -#if FEATURE_COMPILE - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void AndAlsoGlobalMethod() { MethodInfo method = GlobalMethod(typeof(int), new[] { typeof(int), typeof(int) }); AssertExtensions.Throws(null, () => Expression.AndAlso(Expression.Constant(1), Expression.Constant(2), method)); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void OrElseGlobalMethod() { MethodInfo method = GlobalMethod(typeof(int), new [] { typeof(int), typeof(int) }); @@ -851,7 +846,6 @@ private static MethodInfo GlobalMethod(Type returnType, Type[] parameterTypes) module.CreateGlobalFunctions(); return module.GetMethod(globalMethod.Name); } -#endif public class NonGenericClass { diff --git a/src/libraries/System.Linq.Expressions/tests/Cast/CastTests.cs b/src/libraries/System.Linq.Expressions/tests/Cast/CastTests.cs index 090878f8fee7e..64e20adf5cfdd 100644 --- a/src/libraries/System.Linq.Expressions/tests/Cast/CastTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Cast/CastTests.cs @@ -2372,10 +2372,12 @@ public static IEnumerable EnumerableTypes() yield return typeof(UInt32Enum); yield return typeof(Int64Enum); yield return typeof(UInt64Enum); -#if FEATURE_COMPILE - yield return NonCSharpTypes.CharEnumType; - yield return NonCSharpTypes.BoolEnumType; -#endif + + if (PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly) + { + yield return NonCSharpTypes.CharEnumType; + yield return NonCSharpTypes.BoolEnumType; + } } public static IEnumerable EnumerableTypeArgs() => EnumerableTypes().Select(t => new object[] { t }); diff --git a/src/libraries/System.Linq.Expressions/tests/CompilerTests.cs b/src/libraries/System.Linq.Expressions/tests/CompilerTests.cs index 9f4d1f7f6a53d..18cd5b02400b2 100644 --- a/src/libraries/System.Linq.Expressions/tests/CompilerTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/CompilerTests.cs @@ -27,8 +27,7 @@ public static void CompileDeepTree_NoStackOverflow(bool useInterpreter) Assert.Equal(n, f()); } -#if FEATURE_COMPILE - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void EmitConstantsToIL_NonNullableValueTypes() { VerifyEmitConstantsToIL((bool)true); @@ -49,7 +48,7 @@ public static void EmitConstantsToIL_NonNullableValueTypes() VerifyEmitConstantsToIL((decimal)49.95m); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void EmitConstantsToIL_NullableValueTypes() { VerifyEmitConstantsToIL((bool?)null); @@ -85,14 +84,14 @@ public static void EmitConstantsToIL_NullableValueTypes() VerifyEmitConstantsToIL((DateTime?)null); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void EmitConstantsToIL_ReferenceTypes() { VerifyEmitConstantsToIL((string)null); VerifyEmitConstantsToIL((string)"bar"); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void EmitConstantsToIL_Enums() { VerifyEmitConstantsToIL(ConstantsEnum.A); @@ -100,21 +99,21 @@ public static void EmitConstantsToIL_Enums() VerifyEmitConstantsToIL((ConstantsEnum?)ConstantsEnum.A); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void EmitConstantsToIL_ShareReferences() { var o = new object(); VerifyEmitConstantsToIL(Expression.Equal(Expression.Constant(o), Expression.Constant(o)), 1, true); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void EmitConstantsToIL_LiftedToClosure() { VerifyEmitConstantsToIL(DateTime.Now, 1); VerifyEmitConstantsToIL((DateTime?)DateTime.Now, 1); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void VariableBinder_CatchBlock_Filter1() { // See https://github.com/dotnet/runtime/issues/18676 for reported issue @@ -128,7 +127,7 @@ public static void VariableBinder_CatchBlock_Filter1() ); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void VariableBinder_CatchBlock_Filter2() { // See https://github.com/dotnet/runtime/issues/18676 for reported issue @@ -142,7 +141,7 @@ public static void VariableBinder_CatchBlock_Filter2() ); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [ActiveIssue("https://github.com/mono/mono/issues/14919", TestRuntimes.Mono)] public static void VerifyIL_Simple() { @@ -159,7 +158,7 @@ .maxstack 1 }"); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [ActiveIssue("https://github.com/mono/mono/issues/14919", TestRuntimes.Mono)] public static void VerifyIL_Exceptions() { @@ -220,7 +219,7 @@ [0] int32 }"); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [ActiveIssue("https://github.com/mono/mono/issues/14919", TestRuntimes.Mono)] public static void VerifyIL_Closure1() { @@ -255,7 +254,7 @@ .maxstack 1 appendInnerLambdas: true); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [ActiveIssue("https://github.com/mono/mono/issues/14919", TestRuntimes.Mono)] public static void VerifyIL_Closure2() { @@ -313,7 +312,7 @@ [0] object[] appendInnerLambdas: true); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [ActiveIssue("https://github.com/mono/mono/issues/14919", TestRuntimes.Mono)] public static void VerifyIL_Closure3() { @@ -431,7 +430,6 @@ private static void Verify_VariableBinder_CatchBlock_Filter(CatchBlock @catch) Assert.Throws(() => e.Compile()); } -#endif } public enum ConstantsEnum diff --git a/src/libraries/System.Linq.Expressions/tests/Constant/ConstantTests.cs b/src/libraries/System.Linq.Expressions/tests/Constant/ConstantTests.cs index b5e1503172136..40ff43d0d5ff0 100644 --- a/src/libraries/System.Linq.Expressions/tests/Constant/ConstantTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Constant/ConstantTests.cs @@ -278,14 +278,12 @@ public static void CheckUShortConstantTest(bool useInterpreter) } } -#if FEATURE_COMPILE private static TypeBuilder GetTypeBuilder() { AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.RunAndCollect); ModuleBuilder module = assembly.DefineDynamicModule("Name"); return module.DefineType("Type"); } -#endif [Theory, ClassData(typeof(CompilationTypes))] public static void CheckTypeConstantTest(bool useInterpreter) @@ -296,9 +294,6 @@ public static void CheckTypeConstantTest(bool useInterpreter) typeof(int), typeof(Func), typeof(List<>).GetGenericArguments()[0], -#if FEATURE_COMPILE - GetTypeBuilder(), -#endif typeof(PrivateGenericClass<>).GetGenericArguments()[0], typeof(PrivateGenericClass<>), typeof(PrivateGenericClass) @@ -306,9 +301,12 @@ public static void CheckTypeConstantTest(bool useInterpreter) { VerifyTypeConstant(value, useInterpreter); } - } -#if FEATURE_COMPILE + if (PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly) + { + VerifyTypeConstant(GetTypeBuilder(), useInterpreter); + } + } private static MethodInfo GlobalMethod(params Type[] parameterTypes) { @@ -319,7 +317,8 @@ private static MethodInfo GlobalMethod(params Type[] parameterTypes) return module.GetMethod(globalMethod.Name); } - [Theory, ClassData(typeof(CompilationTypes))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] + [ClassData(typeof(CompilationTypes))] public static void CheckMethodInfoConstantTest(bool useInterpreter) { foreach (MethodInfo value in new MethodInfo[] @@ -338,7 +337,6 @@ public static void CheckMethodInfoConstantTest(bool useInterpreter) VerifyMethodInfoConstant(value, useInterpreter); } } -#endif [Theory, ClassData(typeof(CompilationTypes))] public static void CheckConstructorInfoConstantTest(bool useInterpreter) diff --git a/src/libraries/System.Linq.Expressions/tests/DelegateType/GetDelegateTypeTests.cs b/src/libraries/System.Linq.Expressions/tests/DelegateType/GetDelegateTypeTests.cs index 6b790c4911866..9d0852a847916 100644 --- a/src/libraries/System.Linq.Expressions/tests/DelegateType/GetDelegateTypeTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/DelegateType/GetDelegateTypeTests.cs @@ -57,17 +57,20 @@ public void GetNullaryAction() [MemberData(nameof(ManagedPointerTypeArgs))] public void CantBeFunc(Type[] typeArgs) { -#if !FEATURE_COMPILE - Assert.Throws(() => Expression.GetDelegateType(typeArgs)); -#else - Type delType = Expression.GetDelegateType(typeArgs); - Assert.True(typeof(MulticastDelegate).IsAssignableFrom(delType)); - Assert.DoesNotMatch(new Regex(@"System\.Action"), delType.FullName); - Assert.DoesNotMatch(new Regex(@"System\.Func"), delType.FullName); - Reflection.MethodInfo method = delType.GetMethod("Invoke"); - Assert.Equal(typeArgs.Last(), method.ReturnType); - Assert.Equal(typeArgs.Take(typeArgs.Length - 1), method.GetParameters().Select(p => p.ParameterType)); -#endif + if (PlatformDetection.IsLinqExpressionsBuiltWithIsInterpretingOnly) + { + Assert.Throws(() => Expression.GetDelegateType(typeArgs)); + } + else + { + Type delType = Expression.GetDelegateType(typeArgs); + Assert.True(typeof(MulticastDelegate).IsAssignableFrom(delType)); + Assert.DoesNotMatch(new Regex(@"System\.Action"), delType.FullName); + Assert.DoesNotMatch(new Regex(@"System\.Func"), delType.FullName); + Reflection.MethodInfo method = delType.GetMethod("Invoke"); + Assert.Equal(typeArgs.Last(), method.ReturnType); + Assert.Equal(typeArgs.Take(typeArgs.Length - 1), method.GetParameters().Select(p => p.ParameterType)); + } } [Theory] @@ -80,17 +83,20 @@ public void CantBeFunc(Type[] typeArgs) public void CantBeAction(Type[] typeArgs) { Type[] delegateArgs = typeArgs.Append(typeof(void)).ToArray(); -#if !FEATURE_COMPILE - Assert.Throws(() => Expression.GetDelegateType(delegateArgs)); -#else - Type delType = Expression.GetDelegateType(delegateArgs); - Assert.True(typeof(MulticastDelegate).IsAssignableFrom(delType)); - Assert.DoesNotMatch(new Regex(@"System\.Action"), delType.FullName); - Assert.DoesNotMatch(new Regex(@"System\.Func"), delType.FullName); - Reflection.MethodInfo method = delType.GetMethod("Invoke"); - Assert.Equal(typeof(void), method.ReturnType); - Assert.Equal(typeArgs, method.GetParameters().Select(p => p.ParameterType)); -#endif + if (PlatformDetection.IsLinqExpressionsBuiltWithIsInterpretingOnly) + { + Assert.Throws(() => Expression.GetDelegateType(delegateArgs)); + } + else + { + Type delType = Expression.GetDelegateType(delegateArgs); + Assert.True(typeof(MulticastDelegate).IsAssignableFrom(delType)); + Assert.DoesNotMatch(new Regex(@"System\.Action"), delType.FullName); + Assert.DoesNotMatch(new Regex(@"System\.Func"), delType.FullName); + Reflection.MethodInfo method = delType.GetMethod("Invoke"); + Assert.Equal(typeof(void), method.ReturnType); + Assert.Equal(typeArgs, method.GetParameters().Select(p => p.ParameterType)); + } } // Open generic type args aren't useful directly with Expressions, but creating them is allowed. diff --git a/src/libraries/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs b/src/libraries/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs index a9a77a61e7f9d..616f223452476 100644 --- a/src/libraries/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Dynamic/InvokeMemberBindingTests.cs @@ -186,8 +186,6 @@ public void CallInfoStored() Assert.Same(info, new MinimumOverrideInvokeMemberBinding("name", false, info).CallInfo); } -#if FEATURE_COMPILE // We're not testing compilation, but we do need Reflection.Emit for the test - private static dynamic GetObjectWithNonIndexerParameterProperty(bool hasGetter, bool hasSetter) { TypeBuilder typeBuild = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.RunAndCollect) @@ -233,7 +231,8 @@ private static dynamic GetObjectWithNonIndexerParameterProperty(bool hasGetter, return Activator.CreateInstance(typeBuild.CreateType()); } - [Fact] + // We're not testing compilation, but we do need Reflection.Emit for the test + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void NonIndexerParameterizedDirectAccess() { // If a parameterized property isn't the type's indexer, we should be allowed to use the @@ -244,7 +243,8 @@ public void NonIndexerParameterizedDirectAccess() Assert.Equal(19, value); } - [Fact] + // We're not testing compilation, but we do need Reflection.Emit for the test + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void NonIndexerParameterizedGetterAndSetterIndexAccess() { dynamic d = GetObjectWithNonIndexerParameterProperty(true, true); @@ -254,7 +254,8 @@ public void NonIndexerParameterizedGetterAndSetterIndexAccess() Assert.Contains("set_ItemProp", ex.Message); } - [Fact] + // We're not testing compilation, but we do need Reflection.Emit for the test + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void NonIndexerParameterizedGetterOnlyIndexAccess() { dynamic d = GetObjectWithNonIndexerParameterProperty(true, false); @@ -264,7 +265,8 @@ public void NonIndexerParameterizedGetterOnlyIndexAccess() Assert.Contains("get_ItemProp", ex.Message); } - [Fact] + // We're not testing compilation, but we do need Reflection.Emit for the test + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void NonIndexerParameterizedSetterOnlyIndexAccess() { dynamic d = GetObjectWithNonIndexerParameterProperty(false, true); @@ -333,7 +335,8 @@ public int GetValue2( int arg10) => 11; } - [Fact] + // We're not testing compilation, but we do need Reflection.Emit for the test + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void ManyArities() { dynamic d = new ManyOverloads(); @@ -377,7 +380,9 @@ public static IEnumerable SameNameObjectPairs() return testObjects.SelectMany(i => testObjects.Select(j => new[] { i, j })); } - [Theory, MemberData(nameof(SameNameObjectPairs))] + // We're not testing compilation, but we do need Reflection.Emit for the test + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] + [MemberData(nameof(SameNameObjectPairs))] public void OperationOnTwoObjectsDifferentTypesOfSameName(object x, object y) { dynamic dX = x; @@ -386,8 +391,6 @@ public void OperationOnTwoObjectsDifferentTypesOfSameName(object x, object y) Assert.Equal(x == y, equal); } -#endif - public class FuncWrapper { public delegate void OutAction(out TResult arg); diff --git a/src/libraries/System.Linq.Expressions/tests/ExceptionHandling/ExceptionHandlingExpressions.cs b/src/libraries/System.Linq.Expressions/tests/ExceptionHandling/ExceptionHandlingExpressions.cs index d9d1d951a4418..26ca0e2ea5119 100644 --- a/src/libraries/System.Linq.Expressions/tests/ExceptionHandling/ExceptionHandlingExpressions.cs +++ b/src/libraries/System.Linq.Expressions/tests/ExceptionHandling/ExceptionHandlingExpressions.cs @@ -240,9 +240,8 @@ public void ExpressionsUnwrapeExternallyThrownRuntimeWrappedException(bool useIn Assert.Equal(4, func()); } -#if FEATURE_COMPILE - - [Theory, ClassData(typeof(CompilationTypes))] + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] + [ClassData(typeof(CompilationTypes))] public void CatchFromExternallyThrownString(bool useInterpreter) { foreach (bool assemblyWraps in new []{false, true}) @@ -274,7 +273,6 @@ public void CatchFromExternallyThrownString(bool useInterpreter) Assert.Equal("An Exceptional Exception!", func()); } } -#endif [Theory] [ClassData(typeof(CompilationTypes))] @@ -1006,11 +1004,14 @@ public void TryFinallyWithinFilterCompiledProhibited() ) ); Expression> lambda = Expression.Lambda>(tryExp); -#if FEATURE_COMPILE - Assert.Throws(() => lambda.Compile(false)); -#else - lambda.Compile(true); -#endif + if (PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly) + { + Assert.Throws(() => lambda.Compile(false)); + } + else + { + lambda.Compile(true); + } } [Theory, InlineData(true)] diff --git a/src/libraries/System.Linq.Expressions/tests/HelperTypes.cs b/src/libraries/System.Linq.Expressions/tests/HelperTypes.cs index aca1e6a4a5c50..ae01067743f9d 100644 --- a/src/libraries/System.Linq.Expressions/tests/HelperTypes.cs +++ b/src/libraries/System.Linq.Expressions/tests/HelperTypes.cs @@ -246,13 +246,23 @@ public struct PS internal class CompilationTypes : IEnumerable { - private static readonly IEnumerable Booleans = new[] + private static IEnumerable Booleans { -#if FEATURE_COMPILE && FEATURE_INTERPRET - new object[] {false}, -#endif - new object[] {true}, - }; + get + { + return LambdaExpression.CanCompileToIL ? + new[] + { + new object[] {false}, + new object[] {true}, + } + : + new[] + { + new object[] {true}, + }; + } + } public IEnumerator GetEnumerator() => Booleans.GetEnumerator(); @@ -366,7 +376,6 @@ public enum UInt32Enum : uint { A = uint.MaxValue } public enum Int64Enum : long { A = long.MaxValue } public enum UInt64Enum : ulong { A = ulong.MaxValue } -#if FEATURE_COMPILE public static class NonCSharpTypes { private static Type _charEnumType; @@ -412,7 +421,6 @@ public static Type BoolEnumType } } } -#endif public class FakeExpression : Expression { @@ -467,15 +475,17 @@ public static class ExpressionAssert { public static void Verify(this LambdaExpression expression, string il, string instructions) { -#if FEATURE_COMPILE - expression.VerifyIL(il); -#endif + if (LambdaExpression.CanCompileToIL) + { + expression.VerifyIL(il); + } - // FEATURE_COMPILE is not directly required, + // LambdaExpression.CanCompileToIL is not directly required, // but this functionality relies on private reflection and that would not work with AOT -#if FEATURE_INTERPRET && FEATURE_COMPILE - expression.VerifyInstructions(instructions); -#endif + if (LambdaExpression.CanCompileToIL && LambdaExpression.CanInterpret) + { + expression.VerifyInstructions(instructions); + } } } diff --git a/src/libraries/System.Linq.Expressions/tests/IndexExpression/IndexExpressionTests.cs b/src/libraries/System.Linq.Expressions/tests/IndexExpression/IndexExpressionTests.cs index 438bdf04ea701..98a436c9f4a17 100644 --- a/src/libraries/System.Linq.Expressions/tests/IndexExpression/IndexExpressionTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/IndexExpression/IndexExpressionTests.cs @@ -92,13 +92,12 @@ public static void ToStringTest() Assert.Equal("xs[i, j]", e3.ToString()); } -#if FEATURE_COMPILE private static TypeBuilder GetTestTypeBuilder() => AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.RunAndCollect) .DefineDynamicModule("TestModule") .DefineType("TestType"); - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [ActiveIssue("https://github.com/mono/mono/issues/14920", TestRuntimes.Mono)] public void NoAccessorIndexedProperty() { @@ -114,7 +113,7 @@ public void NoAccessorIndexedProperty() AssertExtensions.Throws("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void ByRefIndexedProperty() { TypeBuilder typeBuild = GetTestTypeBuilder(); @@ -145,7 +144,7 @@ public void ByRefIndexedProperty() AssertExtensions.Throws("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void VoidIndexedProperty() { TypeBuilder typeBuild = GetTestTypeBuilder(); @@ -173,7 +172,7 @@ public void VoidIndexedProperty() AssertExtensions.Throws("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [ActiveIssue("https://github.com/mono/mono/issues/14927", TestRuntimes.Mono)] public void IndexedPropertyGetReturnsWrongType() { @@ -202,7 +201,7 @@ public void IndexedPropertyGetReturnsWrongType() AssertExtensions.Throws("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void IndexedPropertySetterNoParams() { TypeBuilder typeBuild = GetTestTypeBuilder(); @@ -230,7 +229,7 @@ public void IndexedPropertySetterNoParams() AssertExtensions.Throws("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void IndexedPropertySetterByrefValueType() { TypeBuilder typeBuild = GetTestTypeBuilder(); @@ -258,7 +257,7 @@ public void IndexedPropertySetterByrefValueType() AssertExtensions.Throws("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void IndexedPropertySetterNotReturnVoid() { TypeBuilder typeBuild = GetTestTypeBuilder(); @@ -286,7 +285,7 @@ public void IndexedPropertySetterNotReturnVoid() AssertExtensions.Throws("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void IndexedPropertyGetterInstanceSetterStatic() { TypeBuilder typeBuild = GetTestTypeBuilder(); @@ -326,7 +325,7 @@ public void IndexedPropertyGetterInstanceSetterStatic() AssertExtensions.Throws("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [ActiveIssue("https://github.com/mono/mono/issues/14927", TestRuntimes.Mono)] public void IndexedPropertySetterValueTypeNotMatchPropertyType() { @@ -355,7 +354,7 @@ public void IndexedPropertySetterValueTypeNotMatchPropertyType() AssertExtensions.Throws("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void IndexedPropertyGetterSetterArgCountMismatch() { TypeBuilder typeBuild = GetTestTypeBuilder(); @@ -395,7 +394,7 @@ public void IndexedPropertyGetterSetterArgCountMismatch() AssertExtensions.Throws("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void IndexedPropertyGetterSetterArgumentTypeMismatch() { TypeBuilder typeBuild = GetTestTypeBuilder(); @@ -435,7 +434,7 @@ public void IndexedPropertyGetterSetterArgumentTypeMismatch() AssertExtensions.Throws("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0), Expression.Constant(0), Expression.Constant(0))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void IndexedPropertyVarArgs() { TypeBuilder typeBuild = GetTestTypeBuilder(); @@ -465,7 +464,7 @@ public void IndexedPropertyVarArgs() AssertExtensions.Throws("propertyName", () => Expression.Property(instance, "Item", Expression.Constant(0), Expression.Constant(0), Expression.Constant(0))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void NullInstanceInstanceProperty() { PropertyInfo prop = typeof(Dictionary).GetProperty("Item"); @@ -473,7 +472,7 @@ public void NullInstanceInstanceProperty() AssertExtensions.Throws("instance", () => Expression.Property(null, prop, index)); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void InstanceToStaticProperty() { TypeBuilder typeBuild = GetTestTypeBuilder(); @@ -501,7 +500,7 @@ public void InstanceToStaticProperty() AssertExtensions.Throws("instance", () => Expression.Property(instance, prop, Expression.Constant(0))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void ByRefIndexer() { TypeBuilder typeBuild = GetTestTypeBuilder(); @@ -529,9 +528,6 @@ public void ByRefIndexer() AssertExtensions.Throws("indexes[0]", () => Expression.Property(instance, prop, Expression.Constant(0))); } -// FEATURE_COMPILE -#endif - [Fact] public void CallWithoutIndices() { diff --git a/src/libraries/System.Linq.Expressions/tests/InterpreterTests.cs b/src/libraries/System.Linq.Expressions/tests/InterpreterTests.cs index 146dffb4be4c4..4298013f5f59c 100644 --- a/src/libraries/System.Linq.Expressions/tests/InterpreterTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/InterpreterTests.cs @@ -1,10 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// FEATURE_COMPILE is not directly required, -// but this functionality relies on private reflection and that would not work with AOT -#if FEATURE_INTERPRET && FEATURE_COMPILE - using System.Linq.Expressions.Interpreter; using System.Reflection; using Xunit; @@ -15,7 +11,9 @@ public static class InterpreterTests { private static readonly PropertyInfo s_debugView = typeof(LightLambda).GetPropertyAssert("DebugView"); - [Fact] + // IsNotLinqExpressionsBuiltWithIsInterpretingOnly is not directly required, + // but this functionality relies on private reflection and that would not work with AOT + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void VerifyInstructions_Simple() { // Using an unchecked multiplication to ensure that a mul instruction is emitted (and not mul.ovf) @@ -46,7 +44,9 @@ .maxcontinuation 0 }"); } - [Fact] + // IsNotLinqExpressionsBuiltWithIsInterpretingOnly is not directly required, + // but this functionality relies on private reflection and that would not work with AOT + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void VerifyInstructions_Exceptions() { ParameterExpression x = Expression.Parameter(typeof(int), "x"); @@ -101,7 +101,9 @@ .maxcontinuation 1 }"); } - [Fact] + // IsNotLinqExpressionsBuiltWithIsInterpretingOnly is not directly required, + // but this functionality relies on private reflection and that would not work with AOT + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [ActiveIssue ("https://github.com/dotnet/runtime/issues/53599", platforms: TestPlatforms.MacCatalyst, runtimes: TestRuntimes.Mono)] public static void ConstructorThrows_StackTrace() { @@ -110,7 +112,9 @@ public static void ConstructorThrows_StackTrace() AssertStackTrace(() => f(), "Thrower..ctor"); } - [Fact] + // IsNotLinqExpressionsBuiltWithIsInterpretingOnly is not directly required, + // but this functionality relies on private reflection and that would not work with AOT + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void PropertyGetterThrows_StackTrace() { Expression> e = t => t.Bar; @@ -118,7 +122,9 @@ public static void PropertyGetterThrows_StackTrace() AssertStackTrace(() => f(new Thrower(error: false)), "Thrower.get_Bar"); } - [Fact] + // IsNotLinqExpressionsBuiltWithIsInterpretingOnly is not directly required, + // but this functionality relies on private reflection and that would not work with AOT + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void PropertySetterThrows_StackTrace() { ParameterExpression t = Expression.Parameter(typeof(Thrower), "t"); @@ -127,7 +133,9 @@ public static void PropertySetterThrows_StackTrace() AssertStackTrace(() => f(new Thrower(error: false)), "Thrower.set_Bar"); } - [Fact] + // IsNotLinqExpressionsBuiltWithIsInterpretingOnly is not directly required, + // but this functionality relies on private reflection and that would not work with AOT + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void IndexerGetterThrows_StackTrace() { ParameterExpression t = Expression.Parameter(typeof(Thrower), "t"); @@ -136,7 +144,9 @@ public static void IndexerGetterThrows_StackTrace() AssertStackTrace(() => f(new Thrower(error: false)), "Thrower.get_Item"); } - [Fact] + // IsNotLinqExpressionsBuiltWithIsInterpretingOnly is not directly required, + // but this functionality relies on private reflection and that would not work with AOT + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void IndexerSetterThrows_StackTrace() { ParameterExpression t = Expression.Parameter(typeof(Thrower), "t"); @@ -145,7 +155,9 @@ public static void IndexerSetterThrows_StackTrace() AssertStackTrace(() => f(new Thrower(error: false)), "Thrower.set_Item"); } - [Fact] + // IsNotLinqExpressionsBuiltWithIsInterpretingOnly is not directly required, + // but this functionality relies on private reflection and that would not work with AOT + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void MethodThrows_StackTrace() { Expression> e = t => t.Foo(); @@ -232,5 +244,3 @@ public void Foo() } } } - -#endif diff --git a/src/libraries/System.Linq.Expressions/tests/Invoke/InvocationTests.cs b/src/libraries/System.Linq.Expressions/tests/Invoke/InvocationTests.cs index ea2e7b9b85aa1..829e7e435ba33 100644 --- a/src/libraries/System.Linq.Expressions/tests/Invoke/InvocationTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Invoke/InvocationTests.cs @@ -244,9 +244,9 @@ public static void LambdaAndArgChangeVisit(InvocationExpression invoke) Assert.NotSame(invoke, new ParameterAndConstantChangingVisitor().Visit(invoke)); } -#if FEATURE_COMPILE // When we don't have FEATURE_COMPILE we don't have the Reflection.Emit used in the tests. - - [Theory, ClassData(typeof(CompilationTypes))] + // When we don't have IsNotLinqExpressionsBuiltWithIsInterpretingOnly we don't have the Reflection.Emit used in the tests. + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] + [ClassData(typeof(CompilationTypes))] public static void InvokePrivateDelegate(bool useInterpreter) { AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.RunAndCollect); @@ -263,7 +263,9 @@ public static void InvokePrivateDelegate(bool useInterpreter) Assert.Equal(42, invFunc()); } - [Theory, ClassData(typeof(CompilationTypes))] + // When we don't have IsNotLinqExpressionsBuiltWithIsInterpretingOnly we don't have the Reflection.Emit used in the tests. + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] + [ClassData(typeof(CompilationTypes))] public static void InvokePrivateDelegateTypeLambda(bool useInterpreter) { AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.RunAndCollect); @@ -278,7 +280,6 @@ public static void InvokePrivateDelegateTypeLambda(bool useInterpreter) var invFunc = invLambda.Compile(useInterpreter); Assert.Equal(42, invFunc()); } -#endif private delegate void RefIntAction(ref int x); diff --git a/src/libraries/System.Linq.Expressions/tests/Lambda/LambdaTests.cs b/src/libraries/System.Linq.Expressions/tests/Lambda/LambdaTests.cs index 9cd8d5ef12fda..c62a6ed60273e 100644 --- a/src/libraries/System.Linq.Expressions/tests/Lambda/LambdaTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Lambda/LambdaTests.cs @@ -268,9 +268,11 @@ public void ImplicitlyTyped() double, double, double, double, bool>), exp.Type); -#if FEATURE_COMPILE - // From this point on, the tests require FEATURE_COMPILE (RefEmit) support as SLE needs to create delegate types on the fly. + // From this point on, the tests require IsLinqExpressionsBuiltWithIsInterpretingOnly (RefEmit) support as SLE needs to create delegate types on the fly. // You can't instantiate Func<> over 20 arguments or over byrefs. + if (PlatformDetection.IsLinqExpressionsBuiltWithIsInterpretingOnly) + return; + ParameterExpression[] paramList = Enumerable.Range(0, 20).Select(_ => Expression.Variable(typeof(int))).ToArray(); exp = Expression.Lambda( Expression.Constant(0), @@ -302,7 +304,6 @@ public void ImplicitlyTyped() Assert.Equal(1, delMethod.GetParameters().Length); Assert.Equal(typeof(int).MakeByRefType(), delMethod.GetParameters()[0].ParameterType); Assert.Same(delType, Expression.Lambda(Expression.Constant(3L), Expression.Parameter(typeof(int).MakeByRefType())).Type); -#endif //FEATURE_COMPILE } [Fact] @@ -790,8 +791,7 @@ public void AboveByteMaxArityArg(bool useInterpreter) Assert.Equal(23, result); } -#if FEATURE_COMPILE - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void AboveByteMaxArityArgIL() { ParameterExpression[] pars = Enumerable.Range(0, 300) @@ -808,7 +808,6 @@ .maxstack 1 } "); } -#endif private struct Mutable { @@ -882,8 +881,7 @@ public void AboveByteMaxArityArgAddress(bool useInterpreter) Assert.True(result.Mutated); } -#if FEATURE_COMPILE - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void AboveByteMaxArityArgAddressIL() { ParameterExpression parToMutate = Expression.Parameter(typeof(Mutable)); @@ -903,7 +901,6 @@ .maxstack 1 } "); } -#endif [Theory, ClassData(typeof(CompilationTypes))] public void ExcessiveArity(bool useInterpreter) @@ -927,9 +924,9 @@ public void OpenGenericDelegate() AssertExtensions.Throws("delegateType", () => Expression.Lambda(typeof(Action<>), Expression.Empty(), false, Enumerable.Empty())); } -#if FEATURE_COMPILE // When we don't have FEATURE_COMPILE we don't have the Reflection.Emit used in the tests. - - [Theory, ClassData(typeof(CompilationTypes))] + // When we don't have IsLinqExpressionsBuiltWithIsInterpretingOnly we don't have the Reflection.Emit used in the tests. + [ConditionalTheory(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] + [ClassData(typeof(CompilationTypes))] public void PrivateDelegate(bool useInterpreter) { AssemblyBuilder assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.RunAndCollect); @@ -944,8 +941,6 @@ public void PrivateDelegate(bool useInterpreter) Assert.Equal(42, del.DynamicInvoke()); } -#endif - [Fact] [SkipOnTargetFramework(~TargetFrameworkMonikers.Netcoreapp, "Optimization in .NET Core")] public void ValidateThatInterpreterWithSimpleTypeUsesNonDynamicThunk() diff --git a/src/libraries/System.Linq.Expressions/tests/Member/MemberAccessTests.cs b/src/libraries/System.Linq.Expressions/tests/Member/MemberAccessTests.cs index cca9a0e08c85b..78466bcd842ee 100644 --- a/src/libraries/System.Linq.Expressions/tests/Member/MemberAccessTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Member/MemberAccessTests.cs @@ -552,8 +552,7 @@ public static void MakeMemberAccess_MemberNotFieldOrProperty_ThrowsArgumentExcep AssertExtensions.Throws("member", () => Expression.MakeMemberAccess(Expression.Constant(new PC()), member)); } -#if FEATURE_COMPILE - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [ActiveIssue("https://github.com/mono/mono/issues/14920", TestRuntimes.Mono)] public static void Property_NoGetOrSetAccessors_ThrowsArgumentException() { @@ -575,7 +574,6 @@ public static void Property_NoGetOrSetAccessors_ThrowsArgumentException() AssertExtensions.Throws("property", () => Expression.MakeMemberAccess(expression, createdProperty)); } -#endif [Fact] public static void ToStringTest() diff --git a/src/libraries/System.Linq.Expressions/tests/MemberInit/BindTests.cs b/src/libraries/System.Linq.Expressions/tests/MemberInit/BindTests.cs index 006c4d51cdd37..8777d108110b0 100644 --- a/src/libraries/System.Linq.Expressions/tests/MemberInit/BindTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/MemberInit/BindTests.cs @@ -284,8 +284,7 @@ public void BogusBindingType(MemberBinding binding) AssertExtensions.Throws("bindings[0]", () => Expression.MemberInit(Expression.New(typeof(PropertyAndFields)), binding)); } -#if FEATURE_COMPILE - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void GlobalMethod() { ModuleBuilder module = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.RunAndCollect).DefineDynamicModule("Module"); @@ -296,7 +295,7 @@ public void GlobalMethod() AssertExtensions.Throws("propertyAccessor", () => Expression.Bind(globalMethodInfo, Expression.Constant(2))); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void GlobalField() { ModuleBuilder module = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.RunAndCollect).DefineDynamicModule("Module"); @@ -305,6 +304,5 @@ public void GlobalField() FieldInfo globalField = module.GetField(fieldBuilder.Name); AssertExtensions.Throws("member", () => Expression.Bind(globalField, Expression.Default(globalField.FieldType))); } -#endif } } diff --git a/src/libraries/System.Linq.Expressions/tests/MemberInit/ListBindTests.cs b/src/libraries/System.Linq.Expressions/tests/MemberInit/ListBindTests.cs index c38457740ae5f..3b25685e8368f 100644 --- a/src/libraries/System.Linq.Expressions/tests/MemberInit/ListBindTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/MemberInit/ListBindTests.cs @@ -290,8 +290,7 @@ public void OpenGenericTypesMembers() AssertExtensions.Throws(null, () => Expression.ListBind(method)); } -#if FEATURE_COMPILE - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void GlobalMethod() { ModuleBuilder module = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.RunAndCollect).DefineDynamicModule("Module"); @@ -301,7 +300,5 @@ public void GlobalMethod() MethodInfo globalMethodInfo = module.GetMethod(globalMethod.Name); AssertExtensions.Throws("propertyAccessor", () => Expression.ListBind(globalMethodInfo)); } -#endif - } } diff --git a/src/libraries/System.Linq.Expressions/tests/MemberInit/MemberBindTests.cs b/src/libraries/System.Linq.Expressions/tests/MemberInit/MemberBindTests.cs index 413ab0d7633a0..8a72d0e39849e 100644 --- a/src/libraries/System.Linq.Expressions/tests/MemberInit/MemberBindTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/MemberInit/MemberBindTests.cs @@ -253,8 +253,7 @@ public void StaticReadonlyInnerField(bool useInterpreter) Assert.Throws(() => exp.Compile(useInterpreter)); } -#if FEATURE_COMPILE - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void GlobalMethod() { ModuleBuilder module = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.RunAndCollect).DefineDynamicModule("Module"); @@ -264,7 +263,6 @@ public void GlobalMethod() MethodInfo globalMethodInfo = module.GetMethod(globalMethod.Name); AssertExtensions.Throws("propertyAccessor", () => Expression.MemberBind(globalMethodInfo)); } -#endif [Fact] public void WriteOnlyInnerProperty() diff --git a/src/libraries/System.Linq.Expressions/tests/New/NewTests.cs b/src/libraries/System.Linq.Expressions/tests/New/NewTests.cs index 6d48041ade2bd..f056ed3df36c1 100644 --- a/src/libraries/System.Linq.Expressions/tests/New/NewTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/New/NewTests.cs @@ -555,8 +555,7 @@ public static void OpenGenericConstructorsInvalid(ConstructorInfo ctor, Expressi } } -#if FEATURE_COMPILE - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void GlobalMethodInMembers() { ModuleBuilder module = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.RunAndCollect).DefineDynamicModule("Module"); @@ -570,7 +569,7 @@ public static void GlobalMethodInMembers() AssertExtensions.Throws("members[0]", () => Expression.New(constructor, arguments, members)); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void GlobalFieldInMembers() { ModuleBuilder module = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("Name"), AssemblyBuilderAccess.RunAndCollect).DefineDynamicModule("Module"); @@ -582,7 +581,6 @@ public static void GlobalFieldInMembers() MemberInfo[] members = { globalField }; AssertExtensions.Throws("members[0]", () => Expression.New(constructor, arguments, members)); } -#endif static class StaticCtor { diff --git a/src/libraries/System.Linq.Expressions/tests/New/NewWithByRefParameterTests.cs b/src/libraries/System.Linq.Expressions/tests/New/NewWithByRefParameterTests.cs index 09fbcfcd7ec98..04804eef82f9b 100644 --- a/src/libraries/System.Linq.Expressions/tests/New/NewWithByRefParameterTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/New/NewWithByRefParameterTests.cs @@ -70,13 +70,11 @@ public void CreateByRefAliasingInterpreted() CreateByRefAliasing(useInterpreter: true); } -#if FEATURE_COMPILE - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public void CreateByRefAliasingCompiled() { CreateByRefAliasing(useInterpreter: false); } -#endif [Theory, ClassData(typeof(CompilationTypes))] public void CreateByRefReferencingReadonly(bool useInterpreter) diff --git a/src/libraries/System.Linq.Expressions/tests/StackSpillerTests.cs b/src/libraries/System.Linq.Expressions/tests/StackSpillerTests.cs index cff5a1da09999..480b85028db88 100644 --- a/src/libraries/System.Linq.Expressions/tests/StackSpillerTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/StackSpillerTests.cs @@ -1676,9 +1676,7 @@ .maxcontinuation 1 }"); } -#if FEATURE_COMPILE - - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void Spill_Optimizations_Constant() { ParameterExpression xs = Expression.Parameter(typeof(int[])); @@ -1736,7 +1734,7 @@ [2] int32 ); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void Spill_Optimizations_Default() { ParameterExpression xs = Expression.Parameter(typeof(int[])); @@ -1794,7 +1792,7 @@ [2] int32 ); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void Spill_Optimizations_LiteralField_NotNetFramework() { Expression> e = @@ -1842,7 +1840,7 @@ [1] float64 ); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void Spill_Optimizations_StaticReadOnlyField() { Expression> e = @@ -1891,7 +1889,7 @@ [1] string ); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void Spill_Optimizations_RuntimeVariables1() { ParameterExpression f = Expression.Parameter(typeof(Action)); @@ -1950,7 +1948,7 @@ [2] int32 ); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void Spill_Optimizations_RuntimeVariables2() { ParameterExpression f = Expression.Parameter(typeof(Action)); @@ -2028,7 +2026,7 @@ [3] int32 ); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void Spill_Optimizations_NoSpillBeyondSpillSite1() { ParameterExpression f = Expression.Parameter(typeof(Func)); @@ -2101,7 +2099,7 @@ [2] int32 }"); } - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] public static void Spill_Optimizations_NoSpillBeyondSpillSite2() { ParameterExpression f = Expression.Parameter(typeof(Func)); @@ -2187,8 +2185,6 @@ [4] int32 }"); } -#endif - private static void Test(Func factory, Expression arg1) { Test(args => factory(args[0]), new[] { arg1 }, false); diff --git a/src/libraries/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj b/src/libraries/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj index c2efe998ee96a..7744fdd0edbcd 100644 --- a/src/libraries/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj +++ b/src/libraries/System.Linq.Expressions/tests/System.Linq.Expressions.Tests.csproj @@ -1,10 +1,5 @@ - true - false - true - $(DefineConstants);FEATURE_COMPILE - $(DefineConstants);FEATURE_INTERPRET $(NetCoreAppCurrent);$(NetCoreAppCurrent)-iOS;$(NetCoreAppCurrent)-tvOS;$(NetCoreAppCurrent)-MacCatalyst @@ -221,7 +216,7 @@ - + diff --git a/src/libraries/System.Linq.Expressions/tests/TestExtensions/InlinePerCompilationTypeAttribute.cs b/src/libraries/System.Linq.Expressions/tests/TestExtensions/InlinePerCompilationTypeAttribute.cs index f68d74290d7a5..9925653879113 100644 --- a/src/libraries/System.Linq.Expressions/tests/TestExtensions/InlinePerCompilationTypeAttribute.cs +++ b/src/libraries/System.Linq.Expressions/tests/TestExtensions/InlinePerCompilationTypeAttribute.cs @@ -9,13 +9,8 @@ namespace System.Linq.Expressions.Tests { internal class InlinePerCompilationTypeAttribute : DataAttribute { - private static readonly object[] s_boxedBooleans = - { - false, -#if FEATURE_COMPILE && FEATURE_INTERPRET - true -#endif - }; + private static readonly object[] s_boxedBooleans = PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly ? + new object[] { false, true } : new object[] { false }; private readonly object[] _data; diff --git a/src/libraries/System.Linq.Expressions/tests/TestExtensions/PerCompilationTypeAttribute.cs b/src/libraries/System.Linq.Expressions/tests/TestExtensions/PerCompilationTypeAttribute.cs index 8caa6e9082415..2f399a7078ab7 100644 --- a/src/libraries/System.Linq.Expressions/tests/TestExtensions/PerCompilationTypeAttribute.cs +++ b/src/libraries/System.Linq.Expressions/tests/TestExtensions/PerCompilationTypeAttribute.cs @@ -32,42 +32,30 @@ public override IEnumerable GetData(MethodInfo testMethod) // we'd therefore end up with multiple copies of the last result. foreach (object[] received in delegatedTo.GetData(testMethod)) { -#if FEATURE_COMPILE - object[] withFalse = new object[received.Length + 1]; -#endif + object[] withFalse = null; + if (PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly) + { + withFalse = new object[received.Length + 1]; + withFalse[received.Length] = s_boxedFalse; + } -#if FEATURE_INTERPRET object[] withTrue = new object[received.Length + 1]; -#endif - -#if FEATURE_COMPILE - withFalse[received.Length] = s_boxedFalse; -#endif - -#if FEATURE_INTERPRET withTrue[received.Length] = s_boxedTrue; -#endif for (int i = 0; i != received.Length; ++i) { object arg = received[i]; -#if FEATURE_COMPILE - withFalse[i] = arg; -#endif + if (withFalse != null) + withFalse[i] = arg; -#if FEATURE_INTERPRET withTrue[i] = arg; -#endif } -#if FEATURE_COMPILE - yield return withFalse; -#endif + if (withFalse != null) + yield return withFalse; -#if FEATURE_INTERPRET yield return withTrue; -#endif } } } diff --git a/src/libraries/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedNullableTests.cs b/src/libraries/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedNullableTests.cs index ce051238ea2a4..9811cd7b632d3 100644 --- a/src/libraries/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedNullableTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedNullableTests.cs @@ -201,8 +201,7 @@ private static void VerifyArithmeticNegateCheckedNullableShort(short? value, boo #endregion -#if FEATURE_COMPILE - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [ActiveIssue("https://github.com/mono/mono/issues/14919", TestRuntimes.Mono)] public static void VerifyIL_NullableShortNegateChecked() { @@ -234,7 +233,5 @@ [0] valuetype [System.Private.CoreLib]System.Nullable`1 IL_001d: ret }"); } -#endif - } } diff --git a/src/libraries/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedTests.cs b/src/libraries/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedTests.cs index dd44ab27bc03c..460c2c2cd15f1 100644 --- a/src/libraries/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedTests.cs +++ b/src/libraries/System.Linq.Expressions/tests/Unary/UnaryArithmeticNegateCheckedTests.cs @@ -208,8 +208,7 @@ private static void VerifyArithmeticNegateCheckedShort(short value, bool useInte #endregion -#if FEATURE_COMPILE - [Fact] + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.IsNotLinqExpressionsBuiltWithIsInterpretingOnly))] [ActiveIssue("https://github.com/mono/mono/issues/14919", TestRuntimes.Mono)] public static void VerifyIL_ShortNegateChecked() { @@ -229,7 +228,5 @@ .maxstack 2 IL_0004: ret }"); } -#endif - } }