mirror of
https://github.com/VSadov/Satori.git
synced 2025-06-10 10:00:57 +09:00
Proper type name parser for native AOT compiler (#83657)
* Proper type name parser for native AOT compiler * Track failure of CA search rules in the type name parser * Fix tests * Suppress new native AOT warning for libraries tests Co-authored-by: vitek-karas <10670590+vitek-karas@users.noreply.github.com> Fixes #72833
This commit is contained in:
parent
6b0a0f3dd4
commit
c1049390d5
13 changed files with 206 additions and 150 deletions
|
@ -29,7 +29,7 @@
|
||||||
<IlcSdkPath>$(CoreCLRAotSdkDir)</IlcSdkPath>
|
<IlcSdkPath>$(CoreCLRAotSdkDir)</IlcSdkPath>
|
||||||
<IlcFrameworkPath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkPath>
|
<IlcFrameworkPath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkPath>
|
||||||
<IlcFrameworkNativePath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkNativePath>
|
<IlcFrameworkNativePath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkNativePath>
|
||||||
<NoWarn>$(NoWarn);IL1005;IL3000;IL3001;IL3002;IL3003</NoWarn>
|
<NoWarn>$(NoWarn);IL1005;IL2105;IL3000;IL3001;IL3002;IL3003</NoWarn>
|
||||||
<TrimMode>partial</TrimMode>
|
<TrimMode>partial</TrimMode>
|
||||||
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
|
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
|
||||||
<SuppressAotAnalysisWarnings>true</SuppressAotAnalysisWarnings>
|
<SuppressAotAnalysisWarnings>true</SuppressAotAnalysisWarnings>
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
@ -70,7 +71,7 @@ namespace ILCompiler.Dataflow
|
||||||
MarkEvent(origin, @event, reason);
|
MarkEvent(origin, @event, reason);
|
||||||
break;
|
break;
|
||||||
// case InterfaceImplementation
|
// case InterfaceImplementation
|
||||||
// Nothing to do currently as Native AOT will presere all interfaces on a preserved type
|
// Nothing to do currently as Native AOT will preserve all interfaces on a preserved type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,19 +79,26 @@ namespace ILCompiler.Dataflow
|
||||||
{
|
{
|
||||||
ModuleDesc? callingModule = ((diagnosticContext.Origin.MemberDefinition as MethodDesc)?.OwningType as MetadataType)?.Module;
|
ModuleDesc? callingModule = ((diagnosticContext.Origin.MemberDefinition as MethodDesc)?.OwningType as MetadataType)?.Module;
|
||||||
|
|
||||||
// NativeAOT doesn't have a fully capable type name resolver yet
|
List<ModuleDesc> referencedModules = new();
|
||||||
// Once this is implemented don't forget to wire up marking of type forwards which are used in generic parameters
|
TypeDesc foundType = System.Reflection.TypeNameParser.ResolveType(typeName, callingModule, diagnosticContext.Origin.MemberDefinition!.Context,
|
||||||
if (!DependencyAnalysis.ReflectionMethodBodyScanner.ResolveType(typeName, callingModule, diagnosticContext.Origin.MemberDefinition!.Context, out TypeDesc foundType, out ModuleDesc referenceModule))
|
referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary);
|
||||||
|
if (foundType == null)
|
||||||
{
|
{
|
||||||
|
if (needsAssemblyName && typeWasNotFoundInAssemblyNorBaseLibrary)
|
||||||
|
diagnosticContext.AddDiagnostic(DiagnosticId.TypeWasNotFoundInAssemblyNorBaseLibrary, typeName);
|
||||||
|
|
||||||
type = default;
|
type = default;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_enabled)
|
if (_enabled)
|
||||||
|
{
|
||||||
|
foreach (ModuleDesc referencedModule in referencedModules)
|
||||||
{
|
{
|
||||||
// Also add module metadata in case this reference was through a type forward
|
// Also add module metadata in case this reference was through a type forward
|
||||||
if (Factory.MetadataManager.CanGenerateMetadata(referenceModule.GetGlobalModuleType()))
|
if (Factory.MetadataManager.CanGenerateMetadata(referencedModule.GetGlobalModuleType()))
|
||||||
_dependencies.Add(Factory.ModuleMetadata(referenceModule), reason);
|
_dependencies.Add(Factory.ModuleMetadata(referencedModule), reason);
|
||||||
|
}
|
||||||
|
|
||||||
MarkType(diagnosticContext.Origin, foundType, reason);
|
MarkType(diagnosticContext.Origin, foundType, reason);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,99 +0,0 @@
|
||||||
// Licensed to the .NET Foundation under one or more agreements.
|
|
||||||
// The .NET Foundation licenses this file to you under the MIT license.
|
|
||||||
|
|
||||||
using Internal.TypeSystem;
|
|
||||||
|
|
||||||
using AssemblyName = System.Reflection.AssemblyName;
|
|
||||||
using StringBuilder = System.Text.StringBuilder;
|
|
||||||
|
|
||||||
namespace ILCompiler.DependencyAnalysis
|
|
||||||
{
|
|
||||||
internal static class ReflectionMethodBodyScanner
|
|
||||||
{
|
|
||||||
public static bool ResolveType(string name, ModuleDesc callingModule, TypeSystemContext context, out TypeDesc type, out ModuleDesc referenceModule)
|
|
||||||
{
|
|
||||||
// This can do enough resolution to resolve "Foo" or "Foo, Assembly, PublicKeyToken=...".
|
|
||||||
// The reflection resolution rules are complicated. This is only needed for a heuristic,
|
|
||||||
// not for correctness, so this shortcut is okay.
|
|
||||||
|
|
||||||
type = null;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
// Consume type name part
|
|
||||||
StringBuilder typeName = new StringBuilder();
|
|
||||||
StringBuilder typeNamespace = new StringBuilder();
|
|
||||||
string containingTypeName = null;
|
|
||||||
while (i < name.Length && (char.IsLetterOrDigit(name[i]) || name[i] == '.' || name[i] == '_' || name[i] == '`' || name[i] == '+'))
|
|
||||||
{
|
|
||||||
if (name[i] == '.')
|
|
||||||
{
|
|
||||||
if (typeNamespace.Length > 0)
|
|
||||||
typeNamespace.Append('.');
|
|
||||||
typeNamespace.Append(typeName);
|
|
||||||
typeName.Clear();
|
|
||||||
}
|
|
||||||
else if (name[i] == '+')
|
|
||||||
{
|
|
||||||
containingTypeName = typeName.ToString();
|
|
||||||
typeName.Clear();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
typeName.Append(name[i]);
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
string nestedTypeName = null;
|
|
||||||
if (containingTypeName != null)
|
|
||||||
{
|
|
||||||
nestedTypeName = typeName.ToString();
|
|
||||||
typeName = new StringBuilder(containingTypeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume any comma or white space
|
|
||||||
while (i < name.Length && (name[i] == ' ' || name[i] == ','))
|
|
||||||
{
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Consume assembly name
|
|
||||||
StringBuilder assemblyName = new StringBuilder();
|
|
||||||
while (i < name.Length && (char.IsLetterOrDigit(name[i]) || name[i] == '.' || name[i] == '_'))
|
|
||||||
{
|
|
||||||
assemblyName.Append(name[i]);
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the name was assembly-qualified, resolve the assembly
|
|
||||||
// If it wasn't qualified, we resolve in the calling assembly
|
|
||||||
|
|
||||||
referenceModule = callingModule;
|
|
||||||
if (assemblyName.Length > 0)
|
|
||||||
{
|
|
||||||
referenceModule = context.ResolveAssembly(new AssemblyName(assemblyName.ToString()), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (referenceModule == null)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Resolve type in the assembly
|
|
||||||
MetadataType mdType = referenceModule.GetType(typeNamespace.ToString(), typeName.ToString(), throwIfNotFound: false);
|
|
||||||
if (mdType != null && nestedTypeName != null)
|
|
||||||
mdType = mdType.GetNestedType(nestedTypeName);
|
|
||||||
|
|
||||||
// If it didn't resolve and wasn't assembly-qualified, we also try core library
|
|
||||||
if (mdType == null && assemblyName.Length == 0)
|
|
||||||
{
|
|
||||||
referenceModule = context.SystemModule;
|
|
||||||
mdType = referenceModule.GetType(typeNamespace.ToString(), typeName.ToString(), throwIfNotFound: false);
|
|
||||||
if (mdType != null && nestedTypeName != null)
|
|
||||||
mdType = mdType.GetNestedType(nestedTypeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
type = mdType;
|
|
||||||
|
|
||||||
return type != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,151 @@
|
||||||
|
// Licensed to the .NET Foundation under one or more agreements.
|
||||||
|
// The .NET Foundation licenses this file to you under the MIT license.
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using Internal.TypeSystem;
|
||||||
|
|
||||||
|
namespace System.Reflection
|
||||||
|
{
|
||||||
|
internal unsafe ref partial struct TypeNameParser
|
||||||
|
{
|
||||||
|
private TypeSystemContext _context;
|
||||||
|
private ModuleDesc _callingModule;
|
||||||
|
private List<ModuleDesc> _referencedModules;
|
||||||
|
private bool _typeWasNotFoundInAssemblyNorBaseLibrary;
|
||||||
|
|
||||||
|
public static TypeDesc ResolveType(string name, ModuleDesc callingModule,
|
||||||
|
TypeSystemContext context, List<ModuleDesc> referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary)
|
||||||
|
{
|
||||||
|
var parser = new System.Reflection.TypeNameParser(name)
|
||||||
|
{
|
||||||
|
_context = context,
|
||||||
|
_callingModule = callingModule,
|
||||||
|
_referencedModules = referencedModules
|
||||||
|
};
|
||||||
|
|
||||||
|
TypeDesc result = parser.Parse()?.Value;
|
||||||
|
|
||||||
|
typeWasNotFoundInAssemblyNorBaseLibrary = parser._typeWasNotFoundInAssemblyNorBaseLibrary;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class Type
|
||||||
|
{
|
||||||
|
public Type(TypeDesc type) => Value = type;
|
||||||
|
public TypeDesc Value { get; }
|
||||||
|
|
||||||
|
public Type MakeArrayType() => new Type(Value.MakeArrayType());
|
||||||
|
public Type MakeArrayType(int rank) => new Type(Value.MakeArrayType(rank));
|
||||||
|
public Type MakePointerType() => new Type(Value.MakePointerType());
|
||||||
|
public Type MakeByRefType() => new Type(Value.MakeByRefType());
|
||||||
|
|
||||||
|
public Type MakeGenericType(Type[] typeArguments)
|
||||||
|
{
|
||||||
|
TypeDesc[] instantiation = new TypeDesc[typeArguments.Length];
|
||||||
|
for (int i = 0; i < typeArguments.Length; i++)
|
||||||
|
instantiation[i] = typeArguments[i].Value;
|
||||||
|
return new Type(((MetadataType)Value).MakeInstantiatedType(instantiation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool CheckTopLevelAssemblyQualifiedName() => true;
|
||||||
|
|
||||||
|
private Type GetType(string typeName, ReadOnlySpan<string> nestedTypeNames, string assemblyNameIfAny)
|
||||||
|
{
|
||||||
|
ModuleDesc module;
|
||||||
|
|
||||||
|
if (assemblyNameIfAny != null)
|
||||||
|
{
|
||||||
|
module = (TryParseAssemblyName(assemblyNameIfAny) is AssemblyName an) ?
|
||||||
|
_context.ResolveAssembly(an, throwIfNotFound: false) : null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
module = _callingModule;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type type;
|
||||||
|
|
||||||
|
if (module != null)
|
||||||
|
{
|
||||||
|
type = GetTypeCore(module, typeName, nestedTypeNames);
|
||||||
|
if (type != null)
|
||||||
|
{
|
||||||
|
_referencedModules?.Add(module);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it didn't resolve and wasn't assembly-qualified, we also try core library
|
||||||
|
if (assemblyNameIfAny == null)
|
||||||
|
{
|
||||||
|
type = GetTypeCore(_context.SystemModule, typeName, nestedTypeNames);
|
||||||
|
if (type != null)
|
||||||
|
{
|
||||||
|
_referencedModules?.Add(_context.SystemModule);
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
_typeWasNotFoundInAssemblyNorBaseLibrary = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static AssemblyName TryParseAssemblyName(string assemblyName)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return new AssemblyName(assemblyName);
|
||||||
|
}
|
||||||
|
catch (FileLoadException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch (ArgumentException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Type GetTypeCore(ModuleDesc module, string typeName, ReadOnlySpan<string> nestedTypeNames)
|
||||||
|
{
|
||||||
|
string typeNamespace, name;
|
||||||
|
|
||||||
|
int separator = typeName.LastIndexOf('.');
|
||||||
|
if (separator <= 0)
|
||||||
|
{
|
||||||
|
typeNamespace = "";
|
||||||
|
name = typeName;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (typeName[separator - 1] == '.')
|
||||||
|
separator--;
|
||||||
|
typeNamespace = typeName.Substring(0, separator);
|
||||||
|
name = typeName.Substring(separator + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
MetadataType type = module.GetType(typeNamespace, name, throwIfNotFound: false);
|
||||||
|
if (type == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
for (int i = 0; i < nestedTypeNames.Length; i++)
|
||||||
|
{
|
||||||
|
type = type.GetNestedType(nestedTypeNames[i]);
|
||||||
|
if (type == null)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new Type(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ParseError()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -30,6 +30,12 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<Compile Include="..\..\..\..\libraries\Common\src\System\Reflection\TypeNameParser.cs">
|
||||||
|
<Link>TypeNameParser.cs</Link>
|
||||||
|
</Compile>
|
||||||
|
<Compile Include="..\..\..\..\libraries\Common\src\System\Text\ValueStringBuilder.cs">
|
||||||
|
<Link>ValueStringBuilder.cs</Link>
|
||||||
|
</Compile>
|
||||||
<Compile Include="..\..\Common\TypeSystem\IL\DelegateInfo.cs">
|
<Compile Include="..\..\Common\TypeSystem\IL\DelegateInfo.cs">
|
||||||
<Link>IL\DelegateInfo.cs</Link>
|
<Link>IL\DelegateInfo.cs</Link>
|
||||||
</Compile>
|
</Compile>
|
||||||
|
@ -406,7 +412,6 @@
|
||||||
<Compile Include="Compiler\DependencyAnalysis\ReflectedFieldNode.cs" />
|
<Compile Include="Compiler\DependencyAnalysis\ReflectedFieldNode.cs" />
|
||||||
<Compile Include="Compiler\DependencyAnalysis\ReflectedTypeNode.cs" />
|
<Compile Include="Compiler\DependencyAnalysis\ReflectedTypeNode.cs" />
|
||||||
<Compile Include="Compiler\DependencyAnalysis\ReflectionInvokeSupportDependencyAlgorithm.cs" />
|
<Compile Include="Compiler\DependencyAnalysis\ReflectionInvokeSupportDependencyAlgorithm.cs" />
|
||||||
<Compile Include="Compiler\DependencyAnalysis\ReflectionMethodBodyScanner.cs" />
|
|
||||||
<Compile Include="Compiler\DependencyAnalysis\StructMarshallingDataNode.cs" />
|
<Compile Include="Compiler\DependencyAnalysis\StructMarshallingDataNode.cs" />
|
||||||
<Compile Include="Compiler\DependencyAnalysis\Target_ARM64\ARM64TentativeMethodNode.cs" />
|
<Compile Include="Compiler\DependencyAnalysis\Target_ARM64\ARM64TentativeMethodNode.cs" />
|
||||||
<Compile Include="Compiler\DependencyAnalysis\Target_ARM\ARMTentativeMethodNode.cs" />
|
<Compile Include="Compiler\DependencyAnalysis\Target_ARM\ARMTentativeMethodNode.cs" />
|
||||||
|
@ -416,6 +421,7 @@
|
||||||
<Compile Include="Compiler\DependencyAnalysis\TentativeInstanceMethodNode.cs" />
|
<Compile Include="Compiler\DependencyAnalysis\TentativeInstanceMethodNode.cs" />
|
||||||
<Compile Include="Compiler\DependencyAnalysis\TentativeMethodNode.cs" />
|
<Compile Include="Compiler\DependencyAnalysis\TentativeMethodNode.cs" />
|
||||||
<Compile Include="Compiler\DependencyAnalysis\TrimmingDescriptorNode.cs" />
|
<Compile Include="Compiler\DependencyAnalysis\TrimmingDescriptorNode.cs" />
|
||||||
|
<Compile Include="Compiler\DependencyAnalysis\TypeNameParser.cs" />
|
||||||
<Compile Include="Compiler\DependencyAnalysis\VariantInterfaceMethodUseNode.cs" />
|
<Compile Include="Compiler\DependencyAnalysis\VariantInterfaceMethodUseNode.cs" />
|
||||||
<Compile Include="Compiler\DependencyAnalysis\CustomAttributeBasedDependencyAlgorithm.cs" />
|
<Compile Include="Compiler\DependencyAnalysis\CustomAttributeBasedDependencyAlgorithm.cs" />
|
||||||
<Compile Include="Compiler\DependencyAnalysis\FieldMetadataNode.cs" />
|
<Compile Include="Compiler\DependencyAnalysis\FieldMetadataNode.cs" />
|
||||||
|
|
|
@ -83,29 +83,22 @@ namespace System.Net.Http
|
||||||
// the latter can't in turn have an explicit dependency on the former.
|
// the latter can't in turn have an explicit dependency on the former.
|
||||||
|
|
||||||
// Get the relevant types needed.
|
// Get the relevant types needed.
|
||||||
Type? socketsHttpHandlerType = Type.GetType("System.Net.Http.SocketsHttpHandler, System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
|
Type? socketsHttpHandlerType = Type.GetType("System.Net.Http.SocketsHttpHandler, System.Net.Http", throwOnError: false);
|
||||||
Type? httpMessageHandlerType = Type.GetType("System.Net.Http.HttpMessageHandler, System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
|
Type? httpMessageHandlerType = Type.GetType("System.Net.Http.HttpMessageHandler, System.Net.Http", throwOnError: false);
|
||||||
Type? httpClientType = Type.GetType("System.Net.Http.HttpClient, System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
|
Type? httpClientType = Type.GetType("System.Net.Http.HttpClient, System.Net.Http", throwOnError: false);
|
||||||
Type? httpRequestMessageType = Type.GetType("System.Net.Http.HttpRequestMessage, System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
|
Type? httpRequestMessageType = Type.GetType("System.Net.Http.HttpRequestMessage, System.Net.Http", throwOnError: false);
|
||||||
Type? httpResponseMessageType = Type.GetType("System.Net.Http.HttpResponseMessage, System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
|
Type? httpResponseMessageType = Type.GetType("System.Net.Http.HttpResponseMessage, System.Net.Http", throwOnError: false);
|
||||||
Type? httpResponseHeadersType = Type.GetType("System.Net.Http.Headers.HttpResponseHeaders, System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
|
Type? httpResponseHeadersType = Type.GetType("System.Net.Http.Headers.HttpResponseHeaders, System.Net.Http", throwOnError: false);
|
||||||
Type? httpContentType = Type.GetType("System.Net.Http.HttpContent, System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", throwOnError: false);
|
Type? httpContentType = Type.GetType("System.Net.Http.HttpContent, System.Net.Http", throwOnError: false);
|
||||||
|
Type? taskOfHttpResponseMessageType = Type.GetType("System.Threading.Tasks.Task`1[[System.Net.Http.HttpResponseMessage, System.Net.Http]], System.Runtime", throwOnError: false);
|
||||||
|
|
||||||
if (socketsHttpHandlerType == null || httpMessageHandlerType == null || httpClientType == null || httpRequestMessageType == null ||
|
if (socketsHttpHandlerType == null || httpMessageHandlerType == null || httpClientType == null || httpRequestMessageType == null ||
|
||||||
httpResponseMessageType == null || httpResponseHeadersType == null || httpContentType == null)
|
httpResponseMessageType == null || httpResponseHeadersType == null || httpContentType == null || taskOfHttpResponseMessageType == null)
|
||||||
{
|
{
|
||||||
Debug.Fail("Unable to load required type.");
|
Debug.Fail("Unable to load required type.");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Workaround until https://github.com/dotnet/runtime/issues/72833 is fixed
|
|
||||||
[UnconditionalSuppressMessage("AotAnalysis", "IL3050:RequiresDynamicCode",
|
|
||||||
Justification = "The type HttpResponseMessage is a reference type")]
|
|
||||||
[return: DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)]
|
|
||||||
static Type GetTaskOfHttpResponseMessageType([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] Type? httpResponseMessageType) => typeof(Task<>).MakeGenericType(httpResponseMessageType!);
|
|
||||||
|
|
||||||
Type taskOfHttpResponseMessageType = GetTaskOfHttpResponseMessageType(httpResponseMessageType);
|
|
||||||
|
|
||||||
// Get the methods on those types.
|
// Get the methods on those types.
|
||||||
ConstructorInfo? socketsHttpHandlerCtor = socketsHttpHandlerType.GetConstructor(Type.EmptyTypes);
|
ConstructorInfo? socketsHttpHandlerCtor = socketsHttpHandlerType.GetConstructor(Type.EmptyTypes);
|
||||||
PropertyInfo? pooledConnectionIdleTimeoutProp = socketsHttpHandlerType.GetProperty("PooledConnectionIdleTimeout");
|
PropertyInfo? pooledConnectionIdleTimeoutProp = socketsHttpHandlerType.GetProperty("PooledConnectionIdleTimeout");
|
||||||
|
|
|
@ -6,6 +6,8 @@ using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace System.Reflection
|
namespace System.Reflection
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
|
@ -622,10 +624,12 @@ namespace System.Reflection
|
||||||
return fullName;
|
return fullName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SYSTEM_PRIVATE_CORELIB
|
||||||
private void ParseError()
|
private void ParseError()
|
||||||
{
|
{
|
||||||
if (_throwOnError)
|
if (_throwOnError)
|
||||||
throw new ArgumentException(SR.Arg_ArgumentException, $"typeName@{_errorIndex}");
|
throw new ArgumentException(SR.Arg_ArgumentException, $"typeName@{_errorIndex}");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ using System.Diagnostics;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
#nullable enable
|
||||||
|
|
||||||
namespace System.Text
|
namespace System.Text
|
||||||
{
|
{
|
||||||
internal ref partial struct ValueStringBuilder
|
internal ref partial struct ValueStringBuilder
|
||||||
|
|
|
@ -238,10 +238,10 @@ namespace System.Reflection.Tests
|
||||||
[ActiveIssue("https://github.com/mono/mono/issues/15318", TestRuntimes.Mono)]
|
[ActiveIssue("https://github.com/mono/mono/issues/15318", TestRuntimes.Mono)]
|
||||||
public void Invoke_LargeDimensionalArrayConstructor()
|
public void Invoke_LargeDimensionalArrayConstructor()
|
||||||
{
|
{
|
||||||
Type type = Type.GetType("System.Type[,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,]");
|
Type type = Type.GetType($"System.Type[{new string(',', 31)}]");
|
||||||
ConstructorInfo[] cia = TypeExtensions.GetConstructors(type);
|
ConstructorInfo[] cia = TypeExtensions.GetConstructors(type);
|
||||||
Assert.Equal(2, cia.Length);
|
Assert.Equal(2, cia.Length);
|
||||||
Assert.Throws<TypeLoadException>(() => Type.GetType("System.Type[,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,]"));
|
Assert.Throws<TypeLoadException>(() => Type.GetType($"System.Type[{new string(',', 42)}]"));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
|
@ -82,6 +82,10 @@ namespace System.Reflection.Tests
|
||||||
[InlineData(typeof(string), new Type[] { typeof(char), typeof(int) })]
|
[InlineData(typeof(string), new Type[] { typeof(char), typeof(int) })]
|
||||||
public void Properties(Type type, Type[] typeParameters)
|
public void Properties(Type type, Type[] typeParameters)
|
||||||
{
|
{
|
||||||
|
// Trick trimming into keeping the string ctor
|
||||||
|
if (string.Empty.Length > 0)
|
||||||
|
typeof(string).GetConstructors();
|
||||||
|
|
||||||
ConstructorInfo constructor = TypeExtensions.GetConstructor(type, typeParameters);
|
ConstructorInfo constructor = TypeExtensions.GetConstructor(type, typeParameters);
|
||||||
|
|
||||||
Assert.Equal(type, constructor.DeclaringType);
|
Assert.Equal(type, constructor.DeclaringType);
|
||||||
|
|
|
@ -128,9 +128,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/dotnet/runtime/issues/72833
|
[Kept]
|
||||||
// NativeAOT doesn't implement full type name parser yet
|
|
||||||
[Kept (By = Tool.Trimmer)]
|
|
||||||
class FromStringConstantWithGenericInner
|
class FromStringConstantWithGenericInner
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -143,9 +141,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
public T GetValue () { return default (T); }
|
public T GetValue () { return default (T); }
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/dotnet/runtime/issues/72833
|
[Kept]
|
||||||
// NativeAOT doesn't implement full type name parser yet
|
|
||||||
[Kept (By = Tool.Trimmer)]
|
|
||||||
class FromStringConstantWithGenericInnerInner
|
class FromStringConstantWithGenericInnerInner
|
||||||
{
|
{
|
||||||
[Kept (By = Tool.Trimmer)]
|
[Kept (By = Tool.Trimmer)]
|
||||||
|
@ -156,7 +152,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
int unusedField;
|
int unusedField;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Kept (By = Tool.Trimmer)]
|
[Kept]
|
||||||
class FromStringConstantWithGenericInnerOne<
|
class FromStringConstantWithGenericInnerOne<
|
||||||
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
|
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
|
||||||
[KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute), By = Tool.Trimmer)]
|
[KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute), By = Tool.Trimmer)]
|
||||||
|
@ -164,9 +160,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/dotnet/runtime/issues/72833
|
[Kept]
|
||||||
// NativeAOT doesn't implement full type name parser yet
|
|
||||||
[Kept (By = Tool.Trimmer)]
|
|
||||||
class FromStringConstantWithGenericInnerTwo
|
class FromStringConstantWithGenericInnerTwo
|
||||||
{
|
{
|
||||||
void UnusedMethod ()
|
void UnusedMethod ()
|
||||||
|
@ -174,22 +168,14 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/dotnet/runtime/issues/72833
|
[Kept]
|
||||||
// NativeAOT doesn't implement full type name parser yet
|
|
||||||
[Kept (By = Tool.Trimmer)]
|
|
||||||
class FromStringConstantWitGenericInnerMultiDimArray
|
class FromStringConstantWitGenericInnerMultiDimArray
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/dotnet/runtime/issues/72833
|
|
||||||
// NativeAOT actually preserves this, but for a slightly wrong reason - it completely ignores the array notations
|
|
||||||
[Kept]
|
[Kept]
|
||||||
[KeptMember (".ctor()", By = Tool.NativeAot)]
|
|
||||||
class FromStringConstantWithMultiDimArray
|
class FromStringConstantWithMultiDimArray
|
||||||
{
|
{
|
||||||
// https://github.com/dotnet/runtime/issues/72833
|
|
||||||
// NativeAOT actually preserves this, but for a slightly wrong reason - it completely ignores the array notations
|
|
||||||
[Kept (By = Tool.NativeAot)]
|
|
||||||
public void UnusedMethod () { }
|
public void UnusedMethod () { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,6 +186,8 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
}
|
}
|
||||||
|
|
||||||
[Kept]
|
[Kept]
|
||||||
|
[KeptAttributeAttribute(typeof(UnconditionalSuppressMessageAttribute))]
|
||||||
|
[UnconditionalSuppressMessage("test", "IL3050", Justification = "The test applies DAM on System.Array, which contains CreateInstance method which has RDC on it.")]
|
||||||
static void TestFromStringConstantWithGeneric ()
|
static void TestFromStringConstantWithGeneric ()
|
||||||
{
|
{
|
||||||
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1[[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInner]]");
|
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1[[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInner]]");
|
||||||
|
|
|
@ -60,11 +60,10 @@ namespace Mono.Linker.Tests.Cases.DataFlow
|
||||||
RequireNothing (type);
|
RequireNothing (type);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NativeAOT doesn't implement this yet: https://github.com/dotnet/runtime/issues/72833
|
|
||||||
[ExpectedWarning ("IL2105",
|
[ExpectedWarning ("IL2105",
|
||||||
"Type 'System.Invalid.TypeName' was not found in the caller assembly nor in the base library. " +
|
"Type 'System.Invalid.TypeName' was not found in the caller assembly nor in the base library. " +
|
||||||
"Type name strings used for dynamically accessing a type should be assembly qualified.",
|
"Type name strings used for dynamically accessing a type should be assembly qualified.",
|
||||||
ProducedBy = Tool.Trimmer)]
|
ProducedBy = Tool.Trimmer | Tool.NativeAot)]
|
||||||
static void TestUnqualifiedTypeNameWarns ()
|
static void TestUnqualifiedTypeNameWarns ()
|
||||||
{
|
{
|
||||||
RequirePublicConstructors ("System.Invalid.TypeName");
|
RequirePublicConstructors ("System.Invalid.TypeName");
|
||||||
|
|
|
@ -191,18 +191,18 @@ namespace Mono.Linker.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.MethodWithGenericTypeArgument(IList<GetDisplayNameTests.GenericClassOneParameter<Byte*[]>>)")]
|
[DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.MethodWithGenericTypeArgument(IList<GetDisplayNameTests.GenericClassOneParameter<Byte*[]>>)")]
|
||||||
public static void MethodWithGenericTypeArgument (IList<GenericClassOneParameter<byte*[]>> p)
|
public static unsafe void MethodWithGenericTypeArgument (IList<GenericClassOneParameter<byte*[]>> p)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.MethodWithGenericTypeArguments(GetDisplayNameTests.GenericClassMultipleParameters<Char*[],Int32[,][]>)")]
|
[DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.MethodWithGenericTypeArguments(GetDisplayNameTests.GenericClassMultipleParameters<Char*[],Int32[,][]>)")]
|
||||||
public static void MethodWithGenericTypeArguments (GenericClassMultipleParameters<char*[], int[,][]> p)
|
public static unsafe void MethodWithGenericTypeArguments (GenericClassMultipleParameters<char*[], int[,][]> p)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
[DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.MethodWithNestedGenericTypeArguments" +
|
[DisplayName ("Mono.Linker.Tests.GetDisplayNameTests.MethodWithNestedGenericTypeArguments" +
|
||||||
"(GetDisplayNameTests.GenericClassMultipleParameters<Char*[],Int32[,][]>.NestedGenericClassMultipleParameters<Char*[],Int32[,][]>)")]
|
"(GetDisplayNameTests.GenericClassMultipleParameters<Char*[],Int32[,][]>.NestedGenericClassMultipleParameters<Char*[],Int32[,][]>)")]
|
||||||
public static void MethodWithNestedGenericTypeArguments (GenericClassMultipleParameters<char*[], int[,][]>.NestedGenericClassMultipleParameters<char*[], int[,][]> p)
|
public static unsafe void MethodWithNestedGenericTypeArguments (GenericClassMultipleParameters<char*[], int[,][]>.NestedGenericClassMultipleParameters<char*[], int[,][]> p)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue