diff --git a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs index bf676b7b6f26be..230e4cb4276a42 100644 --- a/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs +++ b/src/libraries/Common/tests/TestUtilities/System/AssertExtensions.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; @@ -15,6 +16,26 @@ public static class AssertExtensions { private static bool IsNetFramework => RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework"); + + /// + /// Helper for AOT tests that verifies that the compile succeeds, or throws PlatformNotSupported + /// when AOT is enabled. + /// + public static void ThrowsOnAot(Action action) + where T : Exception + { +#if NETCOREAPP // Dynamic code is always supported on .NET Framework + if (!RuntimeFeature.IsDynamicCodeSupported) + { + Assert.Throws(action); + } + else +#endif + { + action(); + } + } + public static void Throws(Action action, string expectedMessage) where T : Exception { diff --git a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs index c28b9f00bb4e7d..670c62ee2f69a8 100644 --- a/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs +++ b/src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/Expressions/ExpressionResolverBuilder.cs @@ -123,6 +123,15 @@ static MethodInfo GetArrayEmptyMethodInfo(Type elementType) return ServiceLookupHelpers.GetArrayEmptyMethodInfo(elementType); } + [UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode", + Justification = "VerifyAotCompatibility ensures elementType is not a ValueType")] + static NewArrayExpression NewArrayInit(Type elementType, IEnumerable expr) + { + Debug.Assert(!ServiceProvider.VerifyAotCompatibility || !elementType.IsValueType, "VerifyAotCompatibility=true will throw during building the IEnumerableCallSite if elementType is a ValueType."); + + return Expression.NewArrayInit(elementType, expr); + } + if (callSite.ServiceCallSites.Length == 0) { return Expression.Constant( @@ -130,7 +139,7 @@ static MethodInfo GetArrayEmptyMethodInfo(Type elementType) .Invoke(obj: null, parameters: Array.Empty())); } - return Expression.NewArrayInit( + return NewArrayInit( callSite.ItemType, callSite.ServiceCallSites.Select(cs => Convert( diff --git a/src/libraries/System.Linq.Expressions/ref/System.Linq.Expressions.cs b/src/libraries/System.Linq.Expressions/ref/System.Linq.Expressions.cs index 98bfd460ddb960..015cfb079d360a 100644 --- a/src/libraries/System.Linq.Expressions/ref/System.Linq.Expressions.cs +++ b/src/libraries/System.Linq.Expressions/ref/System.Linq.Expressions.cs @@ -607,9 +607,13 @@ protected Expression(System.Linq.Expressions.ExpressionType nodeType, System.Typ public static System.Linq.Expressions.NewExpression New(System.Reflection.ConstructorInfo constructor, System.Collections.Generic.IEnumerable? arguments, params System.Reflection.MemberInfo[]? members) { throw null; } public static System.Linq.Expressions.NewExpression New(System.Reflection.ConstructorInfo constructor, params System.Linq.Expressions.Expression[]? arguments) { throw null; } public static System.Linq.Expressions.NewExpression New([System.Diagnostics.CodeAnalysis.DynamicallyAccessedMembersAttribute(System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.NonPublicConstructors | System.Diagnostics.CodeAnalysis.DynamicallyAccessedMemberTypes.PublicConstructors)] System.Type type) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Creating arrays at runtime requires dynamic code generation.")] public static System.Linq.Expressions.NewArrayExpression NewArrayBounds(System.Type type, System.Collections.Generic.IEnumerable bounds) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Creating arrays at runtime requires dynamic code generation.")] public static System.Linq.Expressions.NewArrayExpression NewArrayBounds(System.Type type, params System.Linq.Expressions.Expression[] bounds) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Creating arrays at runtime requires dynamic code generation.")] public static System.Linq.Expressions.NewArrayExpression NewArrayInit(System.Type type, System.Collections.Generic.IEnumerable initializers) { throw null; } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Creating arrays at runtime requires dynamic code generation.")] public static System.Linq.Expressions.NewArrayExpression NewArrayInit(System.Type type, params System.Linq.Expressions.Expression[] initializers) { throw null; } public static System.Linq.Expressions.UnaryExpression Not(System.Linq.Expressions.Expression expression) { throw null; } public static System.Linq.Expressions.UnaryExpression Not(System.Linq.Expressions.Expression expression, System.Reflection.MethodInfo? method) { throw null; } @@ -1028,6 +1032,7 @@ internal MethodCallExpression() { } System.Linq.Expressions.Expression System.Linq.Expressions.IArgumentProvider.GetArgument(int index) { throw null; } public System.Linq.Expressions.MethodCallExpression Update(System.Linq.Expressions.Expression? @object, System.Collections.Generic.IEnumerable? arguments) { throw null; } } + [System.Diagnostics.CodeAnalysis.RequiresDynamicCode("Creating arrays at runtime requires dynamic code generation.")] public partial class NewArrayExpression : System.Linq.Expressions.Expression { internal NewArrayExpression() { } diff --git a/src/libraries/System.Linq.Expressions/src/CompatibilitySuppressions.xml b/src/libraries/System.Linq.Expressions/src/CompatibilitySuppressions.xml index 8185aa8209fa11..bf51da8ccbe294 100644 --- a/src/libraries/System.Linq.Expressions/src/CompatibilitySuppressions.xml +++ b/src/libraries/System.Linq.Expressions/src/CompatibilitySuppressions.xml @@ -97,6 +97,48 @@ ref/net8.0/System.Linq.Expressions.dll lib/net8.0/System.Linq.Expressions.dll + + CP0016 + M:System.Linq.Expressions.Expression.Call(System.Linq.Expressions.Expression,System.String,System.Type[],System.Linq.Expressions.Expression[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + ref/net8.0/System.Linq.Expressions.dll + lib/net8.0/System.Linq.Expressions.dll + + + CP0016 + M:System.Linq.Expressions.Expression.Call(System.Type,System.String,System.Type[],System.Linq.Expressions.Expression[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + ref/net8.0/System.Linq.Expressions.dll + lib/net8.0/System.Linq.Expressions.dll + + + CP0016 + M:System.Linq.Expressions.Expression.ListInit(System.Linq.Expressions.NewExpression,System.Collections.Generic.IEnumerable{System.Linq.Expressions.Expression}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + ref/net8.0/System.Linq.Expressions.dll + lib/net8.0/System.Linq.Expressions.dll + + + CP0016 + M:System.Linq.Expressions.Expression.ListInit(System.Linq.Expressions.NewExpression,System.Linq.Expressions.Expression[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + ref/net8.0/System.Linq.Expressions.dll + lib/net8.0/System.Linq.Expressions.dll + + + CP0016 + M:System.Linq.Expressions.Expression.ListInit(System.Linq.Expressions.NewExpression,System.Reflection.MethodInfo,System.Collections.Generic.IEnumerable{System.Linq.Expressions.Expression}):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + ref/net8.0/System.Linq.Expressions.dll + lib/net8.0/System.Linq.Expressions.dll + + + CP0016 + M:System.Linq.Expressions.Expression.ListInit(System.Linq.Expressions.NewExpression,System.Reflection.MethodInfo,System.Linq.Expressions.Expression[]):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + ref/net8.0/System.Linq.Expressions.dll + lib/net8.0/System.Linq.Expressions.dll + + + CP0016 + M:System.Runtime.CompilerServices.CallSite`1.Create(System.Runtime.CompilerServices.CallSiteBinder):[T:System.Diagnostics.CodeAnalysis.RequiresDynamicCodeAttribute] + ref/net8.0/System.Linq.Expressions.dll + lib/net8.0/System.Linq.Expressions.dll + CP0020 M:System.Linq.Expressions.DynamicExpressionVisitor.#ctor diff --git a/src/libraries/System.Linq.Expressions/src/Resources/Strings.resx b/src/libraries/System.Linq.Expressions/src/Resources/Strings.resx index 01f6ec7be8ddc5..cfbf09d82e02e9 100644 --- a/src/libraries/System.Linq.Expressions/src/Resources/Strings.resx +++ b/src/libraries/System.Linq.Expressions/src/Resources/Strings.resx @@ -564,4 +564,7 @@ The given key '{0}' was not present in the dictionary. + + Nullable lifting on non-primitive type '{0}' is only supported in expression trees when dynamic code generation is available. + 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 47375e1d827797..08f93036a937da 100644 --- a/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj +++ b/src/libraries/System.Linq.Expressions/src/System.Linq.Expressions.csproj @@ -3,7 +3,6 @@ $(NetCoreAppCurrent) $(DefineConstants);FEATURE_FAST_CREATE $(NoWarn);CA1859 - false