1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-08 03:27:04 +09:00

Fix type parsing issues in ILLink and ILC (#104060)

- Fixes https://github.com/dotnet/runtime/issues/98955

   We will now produce a warning when a non-assembly-qualified type
   flows into a string location annotated with
   DynamicallyAccessedMembers, and we don't try to look up or mark the
   type (since we don't know which assemblies will be searched at
   runtime by the Type.GetType call).

- Fixes https://github.com/dotnet/runtime/issues/103906

   The ILLink intrinsic handling for `Type.GetType` will now look in
   corelib for generic arguments, matching native AOT.

This replaces the existing warning IL2105. This uses a new warning
instead of repurposing IL2105, because we already documented IL2105
and older versions of ILLink will produce it. Best to avoid any
confusion about them.
This commit is contained in:
Sven Boemer 2024-07-12 14:07:32 -07:00 committed by GitHub
parent 856a0a6f5e
commit 9407c9cfa8
Signed by: github
GPG key ID: B5690EEEBB952194
30 changed files with 308 additions and 136 deletions

View file

@ -1870,6 +1870,22 @@ void TestMethod()
}
```
#### `IL2122`: Type 'typeName' is not assembly qualified. Type name strings used for dynamically accessing a type should be assembly qualified.
- The type name string passed to a location with `DynamicallyAccessedMembers` requirements was not assembly-qualified, so the trimmer cannot guarantee that the type is preserved. Consider using an assembly-qualified name instead.
```C#
// warning IL2122: Type 'MyClass' is not assembly qualified. Type name strings used for dynamically accessing a type should be assembly qualified.
GetTypeWrapper("MyClass");
class MyClass { }
// May be defined in another assembly, so at runtime Type.GetType will look in that assembly for "MyClass".
void GetTypeWrapper([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] string typeName)
{
var type = Type.GetType(typeName);
}
```
## Single-File Warning Codes

View file

@ -29,7 +29,7 @@
<PublishTrimmed>true</PublishTrimmed>
<!-- Suppress trimming warnings as these are tests -->
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
<NoWarn>$(NoWarn);IL2103;IL2105;IL2025;IL2111</NoWarn>
<NoWarn>$(NoWarn);IL2103;IL2025;IL2111;IL2122</NoWarn>
<!-- Reduce library test app size by trimming framework library features -->
<DebuggerSupport Condition="'$(DebuggerSupport)' == '' and '$(Configuration)' != 'Debug'">false</DebuggerSupport>

View file

@ -29,7 +29,7 @@
<IlcSdkPath>$(CoreCLRAotSdkDir)</IlcSdkPath>
<IlcFrameworkPath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkPath>
<IlcFrameworkNativePath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkNativePath>
<NoWarn>$(NoWarn);IL1005;IL2105;IL3000;IL3001;IL3002;IL3003;IL3050;IL3051;IL3052;IL3053</NoWarn>
<NoWarn>$(NoWarn);IL1005;IL2122;IL3000;IL3001;IL3002;IL3003;IL3050;IL3051;IL3052;IL3053</NoWarn>
<TrimMode>partial</TrimMode>
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
<TrimmerSingleWarn>false</TrimmerSingleWarn>

View file

@ -36,13 +36,18 @@ namespace Internal.TypeSystem
}
public static TypeDesc GetTypeByCustomAttributeTypeNameForDataFlow(string name, ModuleDesc callingModule,
TypeSystemContext context, List<ModuleDesc> referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary)
TypeSystemContext context, List<ModuleDesc> referencedModules, bool needsAssemblyName, out bool failedBecauseNotFullyQualified)
{
typeWasNotFoundInAssemblyNorBaseLibrary = false;
failedBecauseNotFullyQualified = false;
if (!TypeName.TryParse(name.AsSpan(), out TypeName parsed, s_typeNameParseOptions))
return null;
if (needsAssemblyName && !IsFullyQualified(parsed))
{
failedBecauseNotFullyQualified = true;
return null;
}
TypeNameResolver resolver = new()
{
_context = context,
@ -52,8 +57,33 @@ namespace Internal.TypeSystem
TypeDesc type = resolver.Resolve(parsed);
typeWasNotFoundInAssemblyNorBaseLibrary = resolver._typeWasNotFoundInAssemblyNorBaseLibrary;
return type;
static bool IsFullyQualified(TypeName typeName)
{
if (typeName.AssemblyName is null)
{
return false;
}
if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef)
{
return IsFullyQualified(typeName.GetElementType());
}
if (typeName.IsConstructedGenericType)
{
foreach (var typeArgument in typeName.GetGenericArguments())
{
if (!IsFullyQualified(typeArgument))
{
return false;
}
}
}
return true;
}
}
private struct TypeNameResolver
@ -64,7 +94,6 @@ namespace Internal.TypeSystem
internal Func<ModuleDesc, string, MetadataType> _canonResolver;
internal List<ModuleDesc> _referencedModules;
internal bool _typeWasNotFoundInAssemblyNorBaseLibrary;
internal TypeDesc Resolve(TypeName typeName)
{
@ -136,8 +165,6 @@ namespace Internal.TypeSystem
return type;
}
}
_typeWasNotFoundInAssemblyNorBaseLibrary = true;
}
if (_throwIfNotFound)

View file

@ -89,12 +89,13 @@ namespace ILCompiler.Dataflow
List<ModuleDesc> referencedModules = new();
TypeDesc foundType = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeNameForDataFlow(typeName, callingModule, diagnosticContext.Origin.MemberDefinition!.Context,
referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary);
referencedModules, needsAssemblyName, out bool failedBecauseNotFullyQualified);
if (foundType == null)
{
if (needsAssemblyName && typeWasNotFoundInAssemblyNorBaseLibrary)
diagnosticContext.AddDiagnostic(DiagnosticId.TypeWasNotFoundInAssemblyNorBaseLibrary, typeName);
if (failedBecauseNotFullyQualified)
{
diagnosticContext.AddDiagnostic(DiagnosticId.TypeNameIsNotAssemblyQualified, typeName);
}
type = default;
return false;
}

View file

@ -12,6 +12,7 @@ using Internal.TypeSystem.Ecma;
using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Linker.Tests.Cases.Expectations.Assertions;
using Mono.Linker.Tests.Cases.Expectations.Helpers;
using Mono.Linker.Tests.Extensions;
using Xunit;
using MetadataType = Internal.TypeSystem.MetadataType;

View file

@ -14,7 +14,7 @@ class Program
/// </summary>
static int Main(string[] args)
{
TypeDescriptionProviderAttribute attr = new TypeDescriptionProviderAttribute("Program+MyTypeDescriptionProvider");
TypeDescriptionProviderAttribute attr = new TypeDescriptionProviderAttribute("Program+MyTypeDescriptionProvider, project");
if (!RunTest(attr))
{
return -1;

View file

@ -53,7 +53,7 @@ class Program
}
}
[DebuggerTypeProxy("Program+MyClassWithProxyStringProxy")]
[DebuggerTypeProxy("Program+MyClassWithProxyStringProxy, project")]
public class MyClassWithProxyString
{
public string Name { get; set; }

View file

@ -113,8 +113,8 @@ class Program
}
}
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer")]
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer2", "Program+MyClassWithVisualizerStringVisualizerObjectSource")]
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer, project")]
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer2, project", "Program+MyClassWithVisualizerStringVisualizerObjectSource, project")]
public class MyClassWithVisualizerString
{
public string Name { get; set; }

View file

@ -37,7 +37,7 @@
<PropertyGroup Condition="'$(EnableAggressiveTrimming)' == 'true'">
<!-- Suppress trimming warnings as these are tests -->
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
<NoWarn>$(NoWarn);IL2103;IL2105;IL2025;IL2111</NoWarn>
<NoWarn>$(NoWarn);IL2103;IL2025;IL2111;IL2122</NoWarn>
</PropertyGroup>
<!-- This .targets file is also imported by the runtime Trimming tests, and we want to be able to manually configure trimming in them so this

View file

@ -83,7 +83,7 @@ namespace ILLink.Shared
_unused_RearrangedXmlWarning2 = 2021,
XmlCouldNotFindMatchingConstructorForCustomAttribute = 2022,
XmlMoreThanOneReturnElementForMethod = 2023,
XmlMoreThanOneValyForParameterOfMethod = 2024,
XmlMoreThanOneValueForParameterOfMethod = 2024,
XmlDuplicatePreserveMember = 2025,
RequiresUnreferencedCode = 2026,
AttributeShouldOnlyBeUsedOnceOnMember = 2027,
@ -169,7 +169,7 @@ namespace ILLink.Shared
InvalidIsTrimmableValue = 2102,
PropertyAccessorParameterInLinqExpressionsCannotBeStaticallyDetermined = 2103,
AssemblyProducedTrimWarnings = 2104,
TypeWasNotFoundInAssemblyNorBaseLibrary = 2105,
_unused_TypeWasNotFoundInAssemblyNorBaseLibrary = 2105,
DynamicallyAccessedMembersOnMethodReturnValueCanOnlyApplyToTypesOrStrings = 2106,
MethodsAreAssociatedWithStateMachine = 2107,
InvalidScopeInUnconditionalSuppressMessage = 2108,
@ -186,6 +186,7 @@ namespace ILLink.Shared
DynamicallyAccessedMembersOnTypeReferencesCompilerGeneratedMember = 2119,
DynamicallyAccessedMembersOnTypeReferencesCompilerGeneratedMemberOnBase = 2120,
RedundantSuppression = 2121,
TypeNameIsNotAssemblyQualified = 2122,
// Single-file diagnostic ids.
AvoidAssemblyLocationInSingleFile = 3000,

View file

@ -525,10 +525,10 @@
<data name="XmlMoreThanOneReturnElementForMethodMessage" xml:space="preserve">
<value>There is more than one 'return' child element specified for method '{0}'.</value>
</data>
<data name="XmlMoreThanOneValyForParameterOfMethodTitle" xml:space="preserve">
<data name="XmlMoreThanOneValueForParameterOfMethodTitle" xml:space="preserve">
<value>Method has more than one parameter for the XML element 'parameter'. There can only be one value specified for each parameter.</value>
</data>
<data name="XmlMoreThanOneValyForParameterOfMethodMessage" xml:space="preserve">
<data name="XmlMoreThanOneValueForParameterOfMethodMessage" xml:space="preserve">
<value>More than one value specified for parameter '{0}' of method '{1}'.</value>
</data>
<data name="XmlDuplicatePreserveMemberTitle" xml:space="preserve">
@ -1209,4 +1209,10 @@
<data name="InvalidFeatureGuardTitle" xml:space="preserve">
<value>Invalid FeatureGuardAttribute.</value>
</data>
<data name="TypeNameIsNotAssemblyQualifiedMessage" xml:space="preserve">
<value>Type '{0}' is not assembly qualified. Type name strings used for dynamically accessing a type should be assembly qualified.</value>
</data>
<data name="TypeNameIsNotAssemblyQualifiedTitle" xml:space="preserve">
<value>Type name is not assembly qualified.</value>
</data>
</root>

View file

@ -44,7 +44,7 @@ namespace ILLink.Shared.TrimAnalysis
} else if (uniqueValue is SystemTypeValue systemTypeValue) {
MarkTypeForDynamicallyAccessedMembers (systemTypeValue.RepresentedType, targetValue.DynamicallyAccessedMemberTypes);
} else if (uniqueValue is KnownStringValue knownStringValue) {
if (!TryResolveTypeNameAndMark (knownStringValue.Contents, true, out TypeProxy foundType)) {
if (!TryResolveTypeNameAndMark (knownStringValue.Contents, needsAssemblyName: true, out TypeProxy foundType)) {
// Intentionally ignore - it's not wrong for code to call Type.GetType on non-existing name, the code might expect null/exception back.
} else {
MarkTypeForDynamicallyAccessedMembers (foundType, targetValue.DynamicallyAccessedMemberTypes);

View file

@ -1509,6 +1509,12 @@
<Left>ref/net9.0/illink.dll</Left>
<Right>lib/net9.0/illink.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Mono.Linker.LinkContext.get_SystemModuleName</Target>
<Left>ref/net9.0/illink.dll</Left>
<Right>lib/net9.0/illink.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Mono.Linker.LinkContext.set_KeepComInterfaces(System.Boolean)</Target>
@ -1521,6 +1527,12 @@
<Left>ref/net9.0/illink.dll</Left>
<Right>lib/net9.0/illink.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>M:Mono.Linker.LinkContext.set_SystemModuleName(System.String)</Target>
<Left>ref/net9.0/illink.dll</Left>
<Right>lib/net9.0/illink.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0008</DiagnosticId>
<Target>T:Mono.Linker.LinkContext</Target>

View file

@ -72,7 +72,7 @@ namespace Mono.Linker.Steps
continue;
}
CustomAttribute? customAttribute = CreateCustomAttribute (attributeNav, attributeType);
CustomAttribute? customAttribute = CreateCustomAttribute (attributeNav, attributeType, provider);
if (customAttribute != null) {
_context.LogMessage ($"Assigning external custom attribute '{FormatCustomAttribute (customAttribute)}' instance to '{provider}'.");
customAttributesBuilder.Add (customAttribute);
@ -153,9 +153,9 @@ namespace Mono.Linker.Steps
return _context.MarkedKnownMembers.RemoveAttributeInstancesAttributeDefinition = td;
}
CustomAttribute? CreateCustomAttribute (XPathNavigator nav, TypeDefinition attributeType)
CustomAttribute? CreateCustomAttribute (XPathNavigator nav, TypeDefinition attributeType, ICustomAttributeProvider provider)
{
CustomAttributeArgument[] arguments = ReadCustomAttributeArguments (nav, attributeType);
CustomAttributeArgument[] arguments = ReadCustomAttributeArguments (nav, provider);
MethodDefinition? constructor = FindBestMatchingConstructor (attributeType, arguments);
if (constructor == null) {
@ -223,12 +223,12 @@ namespace Mono.Linker.Steps
}
}
CustomAttributeArgument[] ReadCustomAttributeArguments (XPathNavigator nav, TypeDefinition attributeType)
CustomAttributeArgument[] ReadCustomAttributeArguments (XPathNavigator nav, ICustomAttributeProvider provider)
{
ArrayBuilder<CustomAttributeArgument> args = default;
foreach (XPathNavigator argumentNav in nav.SelectChildren ("argument", string.Empty)) {
CustomAttributeArgument? caa = ReadCustomAttributeArgument (argumentNav, attributeType);
CustomAttributeArgument? caa = ReadCustomAttributeArgument (argumentNav, provider);
if (caa is not null)
args.Add (caa.Value);
}
@ -236,9 +236,9 @@ namespace Mono.Linker.Steps
return args.ToArray () ?? Array.Empty<CustomAttributeArgument> ();
}
CustomAttributeArgument? ReadCustomAttributeArgument (XPathNavigator nav, IMemberDefinition memberWithAttribute)
CustomAttributeArgument? ReadCustomAttributeArgument (XPathNavigator nav, ICustomAttributeProvider provider)
{
TypeReference? typeref = ResolveArgumentType (nav, memberWithAttribute);
TypeReference? typeref = ResolveArgumentType (nav, provider);
if (typeref is null)
return null;
@ -295,8 +295,8 @@ namespace Mono.Linker.Steps
if (!typeref.IsTypeOf (WellKnownType.System_Type))
goto default;
var diagnosticContext = new DiagnosticContext (new MessageOrigin (memberWithAttribute), diagnosticsEnabled: true, _context);
if (!_context.TypeNameResolver.TryResolveTypeName (svalue, diagnosticContext, out TypeReference? type, out _)) {
var diagnosticContext = new DiagnosticContext (new MessageOrigin (provider), diagnosticsEnabled: true, _context);
if (!_context.TypeNameResolver.TryResolveTypeName (svalue, diagnosticContext, out TypeReference? type, out _, needsAssemblyName: false)) {
_context.LogError (GetMessageOriginForPosition (nav), DiagnosticId.CouldNotResolveCustomAttributeTypeValue, svalue);
return null;
}
@ -308,7 +308,7 @@ namespace Mono.Linker.Steps
var arrayArgumentIterator = nav.SelectChildren ("argument", string.Empty);
ArrayBuilder<CustomAttributeArgument> elements = default;
foreach (XPathNavigator elementNav in arrayArgumentIterator) {
if (ReadCustomAttributeArgument (elementNav, memberWithAttribute) is CustomAttributeArgument arg) {
if (ReadCustomAttributeArgument (elementNav, provider) is CustomAttributeArgument arg) {
// To match Cecil, elements of a list that are subclasses of the list type must be boxed in the base type
// e.g. object[] { 73 } translates to Cecil.CAA { Type: object[] : Value: CAA{ Type: object, Value: CAA{ Type: int, Value: 73} } }
if (arg.Type == elementType) {
@ -338,14 +338,14 @@ namespace Mono.Linker.Steps
return null;
}
TypeReference? ResolveArgumentType (XPathNavigator nav, IMemberDefinition memberWithAttribute)
TypeReference? ResolveArgumentType (XPathNavigator nav, ICustomAttributeProvider provider)
{
string typeName = GetAttribute (nav, "type");
if (string.IsNullOrEmpty (typeName))
typeName = "System.String";
var diagnosticContext = new DiagnosticContext (new MessageOrigin (memberWithAttribute), diagnosticsEnabled: true, _context);
if (!_context.TypeNameResolver.TryResolveTypeName (typeName, diagnosticContext, out TypeReference? typeref, out _)) {
var diagnosticContext = new DiagnosticContext (new MessageOrigin (provider), diagnosticsEnabled: true, _context);
if (!_context.TypeNameResolver.TryResolveTypeName (typeName, diagnosticContext, out TypeReference? typeref, out _, needsAssemblyName: false)) {
_context.LogError (GetMessageOriginForPosition (nav), DiagnosticId.TypeUsedWithAttributeValueCouldNotBeFound, typeName, nav.Value);
return null;
}
@ -501,7 +501,7 @@ namespace Mono.Linker.Steps
foreach (ParameterDefinition parameter in method.Parameters) {
if (paramName == parameter.Name) {
if (parameter.HasCustomAttributes || _attributeInfo.CustomAttributes.ContainsKey (parameter))
LogWarning (parameterNav, DiagnosticId.XmlMoreThanOneValyForParameterOfMethod, paramName, method.GetDisplayName ());
LogWarning (parameterNav, DiagnosticId.XmlMoreThanOneValueForParameterOfMethod, paramName, method.GetDisplayName ());
_attributeInfo.AddCustomAttributes (parameter, attributes, origins);
break;
}
@ -513,11 +513,15 @@ namespace Mono.Linker.Steps
void ProcessReturnParameters (MethodDefinition method, XPathNavigator nav)
{
Debug.Assert (_attributeInfo != null);
bool firstAppearance = true;
foreach (XPathNavigator returnNav in nav.SelectChildren ("return", string.Empty)) {
if (firstAppearance) {
firstAppearance = false;
PopulateAttributeInfo (method.MethodReturnType, returnNav);
var (attributes, origins) = ProcessAttributes (returnNav, method);
if (attributes != null && origins != null) {
_attributeInfo.AddCustomAttributes (method.MethodReturnType, attributes, origins);
}
} else {
LogWarning (returnNav, DiagnosticId.XmlMoreThanOneReturnElementForMethod, method.GetDisplayName ());
}

View file

@ -45,10 +45,6 @@ using Mono.Cecil.Cil;
using Mono.Collections.Generic;
using Mono.Linker.Dataflow;
using AssemblyNameInfo = System.Reflection.Metadata.AssemblyNameInfo;
using TypeName = System.Reflection.Metadata.TypeName;
using TypeNameParseOptions = System.Reflection.Metadata.TypeNameParseOptions;
namespace Mono.Linker.Steps
{

View file

@ -68,7 +68,7 @@ namespace Mono.Linker
int? _targetRuntime;
readonly AssemblyResolver _resolver;
readonly TypeNameResolver _typeNameResolver;
TypeNameResolver? _typeNameResolver;
readonly AnnotationStore _annotations;
readonly CustomAttributeSource _customAttributes;
@ -146,9 +146,8 @@ namespace Mono.Linker
get { return _resolver; }
}
internal TypeNameResolver TypeNameResolver {
get { return _typeNameResolver; }
}
internal TypeNameResolver TypeNameResolver
=> _typeNameResolver ??= new TypeNameResolver (this, this);
public ISymbolReaderProvider SymbolReaderProvider { get; set; }
@ -205,7 +204,6 @@ namespace Mono.Linker
_logger = logger ?? throw new ArgumentNullException (nameof (logger));
_resolver = factory.CreateResolver (this);
_typeNameResolver = new TypeNameResolver (this, this);
_actions = new Dictionary<string, AssemblyAction> ();
_parameters = new Dictionary<string, string> (StringComparer.Ordinal);
_customAttributes = new CustomAttributeSource (this);
@ -973,7 +971,7 @@ namespace Mono.Linker
public TypeDefinition? TryResolve (AssemblyDefinition assembly, string typeNameString)
{
// It could be cached if it shows up on fast path
return _typeNameResolver.TryResolveTypeName (assembly, typeNameString, out TypeReference? typeReference, out _)
return TypeNameResolver.TryResolveTypeName (assembly, typeNameString, out TypeReference? typeReference, out _)
? TryResolve (typeReference)
: null;
}

View file

@ -7,10 +7,8 @@ using System.Diagnostics.CodeAnalysis;
using ILLink.Shared;
using ILLink.Shared.TrimAnalysis;
using Mono.Cecil;
using Mono.Linker;
using TypeName = System.Reflection.Metadata.TypeName;
using AssemblyNameInfo = System.Reflection.Metadata.AssemblyNameInfo;
namespace Mono.Linker
{
@ -21,7 +19,7 @@ namespace Mono.Linker
in DiagnosticContext diagnosticContext,
[NotNullWhen (true)] out TypeReference? typeReference,
[NotNullWhen (true)] out List<TypeResolutionRecord>? typeResolutionRecords,
bool needsAssemblyName = true)
bool needsAssemblyName)
{
typeReference = null;
typeResolutionRecords = null;
@ -31,28 +29,16 @@ namespace Mono.Linker
if (!TypeName.TryParse (typeNameString, out TypeName? parsedTypeName, s_typeNameParseOptions))
return false;
typeResolutionRecords = new List<TypeResolutionRecord> ();
AssemblyDefinition? typeAssembly;
if (parsedTypeName.AssemblyName is AssemblyNameInfo assemblyName) {
typeAssembly = _assemblyResolver.TryResolve (assemblyName.Name);
if (typeAssembly is null) {
typeResolutionRecords = null;
return false;
}
typeReference = ResolveTypeName (typeAssembly, parsedTypeName, typeResolutionRecords);
if (typeReference == null) {
typeResolutionRecords = null;
}
return typeReference != null;
if (needsAssemblyName && !IsFullyQualified (parsedTypeName)) {
diagnosticContext.AddDiagnostic (DiagnosticId.TypeNameIsNotAssemblyQualified, typeNameString);
return false;
}
// If parsedTypeName doesn't have an assembly name in it but it does have a namespace,
// search for the type in the calling object's assembly. If not found, look in the core
// assembly.
ICustomAttributeProvider? provider = diagnosticContext.Origin.Provider;
typeAssembly = provider switch {
AssemblyDefinition? referencingAssembly = provider switch {
AssemblyDefinition asm => asm,
TypeDefinition type => type.Module?.Assembly,
IMemberDefinition member => member.DeclaringType.Module.Assembly,
@ -60,30 +46,29 @@ namespace Mono.Linker
_ => throw new NotSupportedException ()
};
if (typeAssembly != null && TryResolveTypeName (typeAssembly, parsedTypeName, out typeReference, typeResolutionRecords))
return true;
if (referencingAssembly is null)
return false;
// If type is not found in the caller's assembly, try in core assembly.
typeAssembly = _assemblyResolver.TryResolve (PlatformAssemblies.CoreLib);
if (typeAssembly != null && TryResolveTypeName (typeAssembly, parsedTypeName, out typeReference, typeResolutionRecords))
return true;
typeResolutionRecords = new List<TypeResolutionRecord> ();
typeReference = ResolveTypeName (referencingAssembly, parsedTypeName, typeResolutionRecords);
return typeReference != null;
// It is common to use Type.GetType for looking if a type is available.
// If no type was found only warn and return null.
if (needsAssemblyName && provider != null)
diagnosticContext.AddDiagnostic (DiagnosticId.TypeWasNotFoundInAssemblyNorBaseLibrary, typeNameString);
typeResolutionRecords = null;
return false;
bool TryResolveTypeName (AssemblyDefinition assemblyDefinition, TypeName? typeName, [NotNullWhen (true)] out TypeReference? typeReference, List<TypeResolutionRecord> typeResolutionRecords)
static bool IsFullyQualified (TypeName typeName)
{
typeReference = null;
if (assemblyDefinition == null)
if (typeName.AssemblyName is null)
return false;
typeReference = ResolveTypeName (assemblyDefinition, typeName, typeResolutionRecords);
return typeReference != null;
if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef)
return IsFullyQualified (typeName.GetElementType ());
if (typeName.IsConstructedGenericType) {
foreach (var typeArgument in typeName.GetGenericArguments ()) {
if (!IsFullyQualified (typeArgument))
return false;
}
}
return true;
}
}
}

View file

@ -107,6 +107,19 @@ namespace Mono.Linker
return resolvedType;
}
// If it didn't resolve and wasn't assembly-qualified, we also try core library
var coreLibrary = _metadataResolver.TryResolve (originalAssembly.MainModule.TypeSystem.Object)?.Module.Assembly;
if (coreLibrary is null)
return null;
if (topLevelTypeName.AssemblyName == null && assembly != coreLibrary) {
resolvedType = GetSimpleTypeFromModule (typeName, coreLibrary.MainModule);
if (resolvedType != null) {
typeResolutionRecords.Add (new (coreLibrary, resolvedType));
return resolvedType;
}
}
return null;
TypeDefinition? GetSimpleTypeFromModule (TypeName typeName, ModuleDefinition module)

View file

@ -45,8 +45,8 @@ namespace Mono.Linker.Tests.Cases.ComponentModel
[Kept]
[KeptAttributeAttribute (typeof (TypeConverterAttribute))]
[KeptBackingField]
[ExpectedWarning ("IL2105",
"Type 'NonExistentType' was not found in the caller assembly nor in the base library. " +
[ExpectedWarning ("IL2122",
"Type 'NonExistentType' is not assembly qualified. " +
"Type name strings used for dynamically accessing a type should be assembly qualified.")]
public string Bar { [Kept] get; set; }

View file

@ -78,7 +78,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
[Kept]
static void TestFromStringContantWithAnnotation ()
{
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithAnnotationTestType");
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithAnnotationTestType, test");
}
[Kept]
@ -188,10 +188,19 @@ namespace Mono.Linker.Tests.Cases.DataFlow
[UnconditionalSuppressMessage("test", "IL3050", Justification = "The test applies DAM on System.Array, which contains CreateInstance method which has RDC on it.")]
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+FromStringConstantWithGenericTwoParameters`2[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerOne`1[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerInner],Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerTwo]");
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1[[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWitGenericInnerMultiDimArray[,]]]");
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithMultiDimArray[,]");
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1["
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInner, test]"
+ "], test");
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericTwoParameters`2["
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerOne`1["
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerInner, test]"
+ "], test],"
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericInnerTwo, test]"
+ "], test");
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGeneric`1["
+ "[Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWitGenericInnerMultiDimArray[,], test]"
+ "], test");
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithMultiDimArray[,], test");
}
[Kept]
@ -205,7 +214,9 @@ namespace Mono.Linker.Tests.Cases.DataFlow
[Kept]
static void TestFromStringConstantWithGenericAndAssemblyQualified ()
{
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericAndAssemblyQualified`1[[Mono.Linker.Tests.Cases.Expectations.Assertions.KeptAttribute,Mono.Linker.Tests.Cases.Expectations]]");
RequireCombinationOnString ("Mono.Linker.Tests.Cases.DataFlow.ApplyTypeAnnotations+FromStringConstantWithGenericAndAssemblyQualified`1["
+ "[Mono.Linker.Tests.Cases.Expectations.Assertions.KeptAttribute, Mono.Linker.Tests.Cases.Expectations]"
+ "], test");
}
class InvalidAssemblyNameType

View file

@ -58,7 +58,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
RequireNothing (type);
}
[ExpectedWarning ("IL2105", "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.", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
[ExpectedWarning ("IL2122", "Type 'System.Invalid.TypeName' is not assembly qualified. " + "Type name strings used for dynamically accessing a type should be assembly qualified.", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
static void TestUnqualifiedTypeNameWarns ()
{
RequirePublicConstructors ("System.Invalid.TypeName");

View file

@ -22,7 +22,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
[KeptAttributeAttribute (typeof (KeepsPublicFieldsAttribute))]
[KeptAttributeAttribute (typeof (TypeArrayAttribute))]
[KeepsPublicConstructor (typeof (ClassWithKeptPublicConstructor))]
[KeepsPublicMethods ("Mono.Linker.Tests.Cases.DataFlow.AttributeConstructorDataflow+ClassWithKeptPublicMethods")]
[KeepsPublicMethods ("Mono.Linker.Tests.Cases.DataFlow.AttributeConstructorDataflow+ClassWithKeptPublicMethods, test")]
[KeepsPublicFields (null, null)]
[TypeArray (new Type[] { typeof (AttributeConstructorDataflow) })]
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2273")]

View file

@ -40,9 +40,8 @@ namespace Mono.Linker.Tests.Cases.DataFlow
[Kept]
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
// Trimmer/NativeAot only for now - https://github.com/dotnet/linker/issues/2273
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
[KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributeFieldDataflow+ClassWithKeptPublicMethods")]
[KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributeFieldDataflow+ClassWithKeptPublicMethods, test")]
public static void TestKeepsPublicMethodsString ()
{
typeof (AttributeFieldDataflow).GetMethod (nameof (TestKeepsPublicMethodsString)).GetCustomAttribute (typeof (KeepsPublicMethodsAttribute));

View file

@ -57,7 +57,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
// Trimmer/NativeAot only for now
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethodsKeptByName--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
[KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributesOnMethod+ClassWithKeptPublicMethodsKeptByName")]
[KeepsPublicMethods (TypeName = "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributesOnMethod+ClassWithKeptPublicMethodsKeptByName, test")]
public static void TestKeepsPublicMethodsByName ()
{
typeof (AttributesOnMethod).GetMethod (nameof (TestKeepsPublicMethodsByName)).GetCustomAttribute (typeof (KeepsPublicMethodsAttribute));
@ -213,7 +213,7 @@ namespace Mono.Linker.Tests.Cases.DataFlow
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
// Trimmer/NativeAot only for now
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
[KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethods" : null)]
[KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethodsKeptByName, test" : null)]
public static void Test ()
{
typeof (AttributeWithConditionalExpression).GetMethod ("Test").GetCustomAttribute (typeof (KeepsPublicMethodsAttribute));
@ -225,11 +225,11 @@ namespace Mono.Linker.Tests.Cases.DataFlow
[Kept]
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
[KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethods" : null)]
[KeepsPublicMethods (TypeName = 1 + 1 == 2 ? "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+AttributeWithConditionalExpression+ClassWithKeptPublicMethodsKeptByName, test" : null)]
public static int field;
[Kept]
class ClassWithKeptPublicMethods
class ClassWithKeptPublicMethodsKeptByName
{
[Kept]
[KeptAttributeAttribute (typeof (RequiresUnreferencedCodeAttribute))]

View file

@ -1372,29 +1372,32 @@ namespace Mono.Linker.Tests.Cases.DataFlow
{
static void MethodWithAnnotatedParameter ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)] string typeName) { }
// Analyzer: https://github.com/dotnet/runtime/issues/95118
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")]
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
static void AnnotatedParameter ()
{
MethodWithAnnotatedParameter ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]");
MethodWithAnnotatedParameter ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[["
+ "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod, test"
+ "]], test");
}
// Analyzer: https://github.com/dotnet/runtime/issues/95118
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")]
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
[return: DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
static string AnnotatedReturnValue ()
{
return "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]";
return "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[["
+ "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod, test"
+ "]], test";
}
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicMethods)]
static string _annotatedField;
// Analyzer: https://github.com/dotnet/runtime/issues/95118
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")]
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
static void AnnotatedField ()
{
_annotatedField = "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]";
_annotatedField = "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[["
+ "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod, test"
+ "]], test";
}
public static void Test ()
@ -1407,11 +1410,12 @@ namespace Mono.Linker.Tests.Cases.DataFlow
class TypeGetType
{
// Analyzer: https://github.com/dotnet/runtime/issues/95118
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "")]
[ExpectedWarning ("IL2026", "TypeWithRUCMethod.PrivateRUCMethod", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
static void SpecificType ()
{
Type.GetType ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[[Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod]]");
Type.GetType ("Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithPrivateMethods`1[["
+ "Mono.Linker.Tests.Cases.DataFlow.GenericParameterWarningLocation+MethodBody+TypeWithRUCMethod"
+ "]]");
}
public static void Test ()

View file

@ -3,12 +3,12 @@
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A ) // .?_....:
}
.assembly 'library'
.assembly 'EscapedTypeNames'
{
.hash algorithm 0x00008004
.ver 1:0:0:0
}
.module library.dll
.module EscapedTypeNames.dll
// =============== CLASS MEMBERS DECLARATION ===================

View file

@ -0,0 +1,14 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace Mono.Linker.Tests.Cases.Reflection.Dependencies
{
public class RequireHelper
{
public static Type RequireType ([DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] string type) {
return Type.GetType (type);
}
}
public class TypeDefinedInSameAssemblyAsGetType {}
}

View file

@ -4,16 +4,19 @@ using System.Reflection;
using Mono.Linker.Tests.Cases.Expectations.Assertions;
using Mono.Linker.Tests.Cases.Expectations.Helpers;
using Mono.Linker.Tests.Cases.Expectations.Metadata;
using Mono.Linker.Tests.Cases.Reflection.Dependencies;
namespace Mono.Linker.Tests.Cases.Reflection
{
[KeptMember (".cctor()")]
[ExpectedNoWarnings ()]
[Define ("IL_ASSEMBLY_AVAILABLE")]
[SetupCompileBefore ("library.dll", new[] { "Dependencies/EscapedTypeNames.il" })]
[KeptTypeInAssembly ("library", "Library.Not\\+Nested")]
[KeptTypeInAssembly ("library", "Library.Not\\+Nested+Nes\\\\ted")]
[KeptTypeInAssembly ("library", "Library.Not\\+Nested+Nes/ted")]
[SetupCompileBefore ("EscapedTypeNames.dll", new[] { "Dependencies/EscapedTypeNames.il" })]
[SetupCompileBefore ("RequireHelper.dll", new[] { "Dependencies/RequireHelper.cs" })]
[KeptTypeInAssembly ("EscapedTypeNames", "Library.Not\\+Nested")]
[KeptTypeInAssembly ("EscapedTypeNames", "Library.Not\\+Nested+Nes\\\\ted")]
[KeptTypeInAssembly ("EscapedTypeNames", "Library.Not\\+Nested+Nes/ted")]
[RemovedTypeInAssembly ("RequireHelper", typeof (TypeDefinedInSameAssemblyAsGetType))]
[KeptDelegateCacheField ("0", nameof (AssemblyResolver))]
[KeptDelegateCacheField ("1", nameof (GetTypeFromAssembly))]
public class TypeUsedViaReflection
@ -31,8 +34,9 @@ namespace Mono.Linker.Tests.Cases.Reflection
TestReference ();
TestArray ();
TestArrayOfArray ();
TestGenericArray ();
TestGenericArrayFullString ();
TestGenericInstantiation ();
TestGenericInstantiationFullString ();
TestGenericInstantiationOverCoreLib ();
TestMultiDimensionalArray ();
TestMultiDimensionalArrayFullString ();
TestMultiDimensionalArrayAsmName ();
@ -55,6 +59,7 @@ namespace Mono.Linker.Tests.Cases.Reflection
TestInvalidTypeCombination ();
TestEscapedTypeName ();
AssemblyTypeResolutionBehavior.Test ();
}
[Kept]
@ -92,30 +97,42 @@ namespace Mono.Linker.Tests.Cases.Reflection
}
[Kept]
public class GenericArray<T> { }
public class GenericInstantiation<T> { }
[Kept]
public class GenericArgument { }
[Kept]
public static void TestGenericArray ()
public static void TestGenericInstantiation ()
{
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArray`1[[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArgument]]";
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericInstantiation`1[[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArgument]]";
var typeKept = Type.GetType (reflectionTypeKeptString, false);
}
[Kept]
public class GenericArrayFullString<T> { }
public class GenericInstantiationFullString<T> { }
[Kept]
public class GenericArgumentFullString { }
[Kept]
public static void TestGenericArrayFullString ()
public static void TestGenericInstantiationFullString ()
{
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArrayFullString`1" +
"[[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArgumentFullString, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]," +
" test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericInstantiationFullString`1["
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericArgumentFullString, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]"
+ "], test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
var typeKept = Type.GetType (reflectionTypeKeptString, false);
}
[Kept]
public class GenericInstantiationOverCoreLib<T> { }
[Kept]
public static void TestGenericInstantiationOverCoreLib ()
{
// Note: the argument type should not be assembly-qualified for this test, which is checking that
// we can resolve non-assembly-qualified generic argument types from corelib.
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericInstantiationOverCoreLib`1[[System.String]], test";
var typeKept = Type.GetType (reflectionTypeKeptString, false);
}
@ -420,9 +437,9 @@ namespace Mono.Linker.Tests.Cases.Reflection
[Kept]
static void TestGenericTypeWithAnnotations ()
{
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericTypeWithAnnotations_OuterType`1" +
"[[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericTypeWithAnnotations_InnerType, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]]," +
" test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
const string reflectionTypeKeptString = "Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericTypeWithAnnotations_OuterType`1["
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+GenericTypeWithAnnotations_InnerType, test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null]"
+ "], test, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null";
Type.GetType (reflectionTypeKeptString);
}
@ -475,9 +492,75 @@ namespace Mono.Linker.Tests.Cases.Reflection
[Kept]
static void TestEscapedTypeName ()
{
var typeKept = Type.GetType ("Library.Not\\+Nested, library");
typeKept = Type.GetType ("Library.Not\\+Nested+Nes\\\\ted, library");
typeKept = Type.GetType ("Library.Not\\+Nested+Nes/ted, library");
var typeKept = Type.GetType ("Library.Not\\+Nested, EscapedTypeNames");
typeKept = Type.GetType ("Library.Not\\+Nested+Nes\\\\ted, EscapedTypeNames");
typeKept = Type.GetType ("Library.Not\\+Nested+Nes/ted, EscapedTypeNames");
}
[Kept]
class AssemblyTypeResolutionBehavior
{
[Kept]
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
static void TestRequireTypeInSameAssemblyAsGetType () {
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.Dependencies.TypeDefinedInSameAssemblyAsGetType");
}
[Kept]
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
static void TestRequireTypeInSameAssemblyAsCallToRequireType () {
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+TypeDefinedInSameAssemblyAsCallToRequireType");
}
[Kept]
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
static void TestRequireTypeWithNonAssemblyQualifiedGenericArguments () {
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+Generic`1[[System.Int32]], test");
}
[Kept]
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
static void TestRequireTypeWithNonAssemblyQualifiedArrayType () {
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+Generic`1["
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+ArrayElementGenericArgumentType]"
+ "][], test");
}
[Kept]
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
static void TestRequireTypeWithNonAssemblyQualifiedPointerType () {
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+Generic`1["
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+PointerElementGenericArgumentType]"
+ "]*, test");
}
[Kept]
[ExpectedWarning ("IL2122", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/runtime/issues/95118")]
static void TestRequireTypeWithNonAssemblyQualifiedByRefType () {
RequireHelper.RequireType ("Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+Generic`1["
+ "[Mono.Linker.Tests.Cases.Reflection.TypeUsedViaReflection+AssemblyTypeResolutionBehavior+ByRefElementGenericArgumentType]"
+ "]&, test");
}
[Kept]
public static void Test () {
TestRequireTypeInSameAssemblyAsGetType ();
TestRequireTypeInSameAssemblyAsCallToRequireType ();
TestRequireTypeWithNonAssemblyQualifiedGenericArguments ();
TestRequireTypeWithNonAssemblyQualifiedArrayType ();
TestRequireTypeWithNonAssemblyQualifiedPointerType ();
TestRequireTypeWithNonAssemblyQualifiedByRefType ();
}
class TypeDefinedInSameAssemblyAsCallToRequireType {}
class Generic<T> {}
class ArrayElementGenericArgumentType {}
class PointerElementGenericArgumentType {}
class ByRefElementGenericArgumentType {}
}
}
}

View file

@ -14,6 +14,7 @@ using Mono.Cecil;
using Mono.Cecil.Cil;
using Mono.Linker;
using Mono.Linker.Tests.Cases.Expectations.Assertions;
using Mono.Linker.Tests.Cases.Expectations.Helpers;
using Mono.Linker.Tests.Cases.Expectations.Metadata;
using Mono.Linker.Tests.Extensions;
using Mono.Linker.Tests.TestCasesRunner.ILVerification;