Repository navigation
Microsoft.Extensions.Configuration APIs haven't been AOT-annotated #71654
Copy link
Copy link
Closed
Description
Consider this small application
using System.Diagnostics.CodeAnalysis;
using Microsoft.Extensions.Configuration;
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.Build();
var appSettings = GetAppSettings(config);
Console.WriteLine($"{appSettings.Database}: {appSettings.ConnectionString}");
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026:UnrecognizedReflectionPattern",
Justification = "AppSettings is consists only from primitive type and thus will never be trimmed")]
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050:UnrecognizedReflectionPattern",
Justification = "AppSettings is consists only from primitive type and thus will never be trimmed")]
AppSettings GetAppSettings(IConfiguration config)
{
return config.Get<AppSettings>();
}
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
public class AppSettings
{
public string? ConnectionString { get; set; }
public DatabaseServer Database { get; set; } = DatabaseServer.None;
}
public enum DatabaseServer
{
None,
SqlServer,
PostgreSql,
MySql
}With following packages
dotnet add package Microsoft.Extensions.Configuration.Binder -v 7.0.0-*
dotnet add package Microsoft.Extensions.Configuration.Json -v 7.0.0-*
and `appsettings.json
{
"ConnectionString": "Server=tfb-database;Database=hello_world;User Id=benchmarkdbuser;Password=benchmarkdbpass;Maximum Pool Size=1024;SslMode=None;ConnectionReset=false;ConnectionIdlePingTime=900;ConnectionIdleTimeout=0;AutoEnlist=false;DefaultCommandTimeout=0;ConnectionTimeout=0;IgnorePrepare=false;",
"Database": "mysql"
}ILC spill warnings
ILC : AOT analysis warning IL3050: Microsoft.Extensions.Configuration.ConfigurationBinder.AttemptBindToCollectionInterfaces(Type,IConfiguration,BinderOptions): Using member 'System.Type.MakeGenericType(Type[]
)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime. [D:\d\scratch\ConsoleApp7\ConsoleApp7.csproj]
ILC : AOT analysis warning IL3050: Microsoft.Extensions.Configuration.ConfigurationBinder.AttemptBindToCollectionInterfaces(Type,IConfiguration,BinderOptions): Using member 'System.Type.MakeGenericType(Type[]
)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime. [D:\d\scratch\ConsoleApp7\ConsoleApp7.csproj]
ILC : AOT analysis warning IL3050: Microsoft.Extensions.Configuration.ConfigurationBinder.BindArray(Type,IEnumerable,IConfiguration,BinderOptions): Using member 'System.Array.CreateInstance(Type,Int32)' which
has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. The code for an array of the specified type might not be available. [D:\d\scratch\ConsoleApp7\ConsoleApp7.csproj]
ILC : AOT analysis warning IL3050: Microsoft.Extensions.Configuration.ConfigurationBinder.BindToCollection(Type,IConfiguration,BinderOptions): Using member 'System.Type.MakeGenericType(Type[])' which has 'Req
uiresDynamicCodeAttribute' can break functionality when AOT compiling. The native code for this instantiation might not be available at runtime. [D:\d\scratch\ConsoleApp7\ConsoleApp7.csproj]
/_/src/libraries/System.ComponentModel.TypeConverter/src/System/ComponentModel/EnumConverter.cs(174): AOT analysis warning IL3050: System.ComponentModel.EnumConverter.ConvertTo(ITypeDescriptorContext,CultureI
nfo,Object,Type): Using member 'System.Enum.GetValues(Type)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. It might not be possible to create an array of the enum type a
t runtime. Use the GetValues<TEnum> overload instead. [D:\d\scratch\ConsoleApp7\ConsoleApp7.csproj]
From my understanding AppSettings is safe to map IConfiguration and I want express that. But as you can see all my silly attempts fails.
Reactions are currently unavailable
Activity
kant2002 commentedon Jul 5, 2022
This is boils down to patterns like this
runtime/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
Lines 289 to 304 in 338db1a
which looks very similar to what FSharp do with
printfspecialization at runtime.I can give only indirect hint on this in form of these declarations required to make Printf works in NativeAOT
https://github.com/kant2002/RdXmlLibrary/blob/625eaf01310f2e098b8a17cfe9658e140d37262e/FSharp.Core.xml#L25-L39
agocke commentedon Jul 5, 2022
I assume from the
ILCprefix that this is from NativeAOT -- moving back to the runtime repo.agocke commentedon Jul 5, 2022
I assume this is just because the APIs haven't been annotated with
RequiresDynamicCodeto bubble the requirements up to the public API, right?[-]Cannot suppress configuration warning even if everything is ok.[/-][+]Microsoft.Extensions.Configuration APIs haven't been AOT-annotated[/+]kant2002 commentedon Jul 5, 2022
You are right. I really misinterpret results and regular trimming works fine.
eerhardt commentedon Jul 5, 2022
They have been annotated with
RequiresUnreferencedCodealready. Doesn't that imply that they are not safe for NativeAOT?This API is marked as
RequiresUnreferencedCode:runtime/src/libraries/Microsoft.Extensions.Configuration.Binder/src/ConfigurationBinder.cs
Lines 34 to 48 in 0cb001f
agocke commentedon Jul 5, 2022
Good question. So far we haven’t had RUC suppress RDC, but maybe we should @tlakollo @MichalStrehovsky
tlakollo commentedon Jul 5, 2022
The way I see it is:
PublishTrimmed requires to be trim safe. Therefore any
RequiresUnreferencedCodeattribute makes the app not safePublishSingleFile requires to be single file safe. Therefore any
RequiresAssemblyFilesattribute makes the app not safePublishAOT requires being trim, single file and dynamic code safe. Therefore any
RequiresUnreferencedCode,RequiresAssemblyFiles,RequiresDynamicCodemake the app not safeRequiresUnreferencedCodemeans the result of the publishing the NativeAOT app is not safe, since trimming is not safe. Do we need to annotate also withRequiresDynamicCodebecause it might also be DynamicCode? The app is not going to be safe anyway. It's already trim unsafe and making it dynamic code unsafe won't make a difference for the final NativeAOT publishing.On the other hand the attributes are independent of the publishing type, there could be a theoretical Publishing in the future that only requires being dynamic code safe and doesn't care about trimming or single file. In that case if you didn't annotate with
RequiresDynamicCodeyou have a problem.My opinion as expresed before is that the attributes are independent, they even have different behaviors depending on the attribute (for example
RequiresUnreferencedCodeinteracts with Reflection andDynamicallyAccessedMembersand the other attributes don't). They also can evolve and go completely different paths.Also, it would be difficult to document, RUC does not suppress RAF, RDC does not suppress RUC and to be honest Im not sure RUC suppresses RDC. It kind of implies that all dynamic code is a trimming problem too, and again wouldnt hold up for a hipotetical scenario that only cares about dynamic code.
MichalStrehovsky commentedon Jul 5, 2022
Two comments on that. Basically +1 on what Tlaka just wrote.
doubletofloat(both "primitive types") you'll run into a runtime exception. I think we'll want a RequiresDynamicCode that specifically describes the situations when MakeGeneric could be called and surface that to the user in addition to the trimming warning.eerhardt commentedon Jul 12, 2022
It would be good to annotate these APIs for
RequiresDynamicCodein 7.0.EnableAOTAnalyzer for most of Microsoft.Extensions libraries
EnableAOTAnalyzer for most of Microsoft.Extensions libraries (#73737)
EnableAOTAnalyzer for Microsoft.Extensions.DependencyInjection
EnableAOTAnalyzer for Microsoft.Extensions.DependencyInjection (#73829)
EnableAOTAnalyzer for Microsoft.Extensions.Hosting
EnableAOTAnalyzer for Microsoft.Extensions.Hosting (#73853)