Skip to content

Commit c5213de

Browse files
Enable more ILLink test cases with native AOT (#110166)
When I was working on the `DAMT.All*`, I noticed we don't run many Reflection tests, this is progress towards that. Also fixes rare `CreateInstance` overloads - these were never worth the effort to implement honestly, but more code sharing made implementing them a breeze. Contributes to #82447.
1 parent 05fa881 commit c5213de

File tree

7 files changed

+66
-25
lines changed

7 files changed

+66
-25
lines changed

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/HandleCallAction.cs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -638,17 +638,31 @@ private partial bool TryGetBaseType(TypeProxy type, out TypeProxy? baseType)
638638
return false;
639639
}
640640

641-
#pragma warning disable IDE0060
642641
private partial bool TryResolveTypeNameForCreateInstanceAndMark(in MethodProxy calledMethod, string assemblyName, string typeName, out TypeProxy resolvedType)
643642
{
644-
// TODO: niche APIs that we probably shouldn't even have added
645-
// We have to issue a warning, otherwise we could break the app without a warning.
646-
// This is not the ideal warning, but it's good enough for now.
647-
_diagnosticContext.AddDiagnostic(DiagnosticId.UnrecognizedParameterInMethodCreateInstance, calledMethod.GetParameter((ParameterIndex)(1 + (calledMethod.HasImplicitThis() ? 1 : 0))).GetDisplayName(), calledMethod.GetDisplayName());
648-
resolvedType = default;
649-
return false;
643+
if (!System.Reflection.Metadata.AssemblyNameInfo.TryParse(assemblyName, out var an)
644+
|| _callingMethod.Context.ResolveAssembly(an) is not ModuleDesc resolvedAssembly)
645+
{
646+
_diagnosticContext.AddDiagnostic(DiagnosticId.UnresolvedAssemblyInCreateInstance,
647+
assemblyName,
648+
calledMethod.GetDisplayName());
649+
resolvedType = default;
650+
return false;
651+
}
652+
653+
if (!_reflectionMarker.TryResolveTypeNameAndMark(resolvedAssembly, typeName, _diagnosticContext, "Reflection", out TypeDesc? foundType))
654+
{
655+
// It's not wrong to have a reference to non-existing type - the code may well expect to get an exception in this case
656+
// Note that we did find the assembly, so it's not a ILLink config problem, it's either intentional, or wrong versions of assemblies
657+
// but ILLink can't know that. In case a user tries to create an array using System.Activator we should simply ignore it, the user
658+
// might expect an exception to be thrown.
659+
resolvedType = default;
660+
return false;
661+
}
662+
663+
resolvedType = new TypeProxy(foundType);
664+
return true;
650665
}
651-
#pragma warning restore IDE0060
652666

653667
private partial void MarkStaticConstructor(TypeProxy type)
654668
=> _reflectionMarker.MarkStaticConstructor(_diagnosticContext.Origin, type.Type, _reason);

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,33 @@ internal bool TryResolveTypeNameAndMark(string typeName, in DiagnosticContext di
116116
return true;
117117
}
118118

119+
internal bool TryResolveTypeNameAndMark(ModuleDesc assembly, string typeName, in DiagnosticContext diagnosticContext, string reason, [NotNullWhen(true)] out TypeDesc? type)
120+
{
121+
List<ModuleDesc> referencedModules = new();
122+
TypeDesc foundType = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeNameForDataFlow(typeName, assembly, assembly.Context,
123+
referencedModules, needsAssemblyName: false, out _);
124+
if (foundType == null)
125+
{
126+
type = default;
127+
return false;
128+
}
129+
130+
if (_enabled)
131+
{
132+
foreach (ModuleDesc referencedModule in referencedModules)
133+
{
134+
// Also add module metadata in case this reference was through a type forward
135+
if (Factory.MetadataManager.CanGenerateMetadata(referencedModule.GetGlobalModuleType()))
136+
_dependencies.Add(Factory.ModuleMetadata(referencedModule), reason);
137+
}
138+
139+
MarkType(diagnosticContext.Origin, foundType, reason);
140+
}
141+
142+
type = foundType;
143+
return true;
144+
}
145+
119146
internal void MarkType(in MessageOrigin origin, TypeDesc type, string reason, AccessKind accessKind = AccessKind.Unspecified)
120147
{
121148
if (!_enabled)

src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCases/TestSuites.cs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,17 @@ public void LinkXml (string t)
6969
[MemberData (nameof (TestDatabase.Reflection), MemberType = typeof (TestDatabase))]
7070
public void Reflection (string t)
7171
{
72-
switch (t) {
73-
case "TypeHierarchyReflectionWarnings":
74-
case "ParametersUsedViaReflection":
75-
case "UnsafeAccessor":
76-
case "TypeUsedViaReflection":
77-
case "RunClassConstructor":
78-
case "NestedTypeUsedViaReflection":
79-
Run (t);
72+
switch (t)
73+
{
74+
case "ObjectGetType":
75+
// Skip for now
76+
break;
77+
case "ObjectGetTypeLibraryMode":
78+
case "TypeHierarchyLibraryModeSuppressions":
79+
// No Library mode
8080
break;
8181
default:
82-
// Skip the rest for now
82+
Run (t);
8383
break;
8484
}
8585
}

src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/ComplexTypeHandling.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ static void TestArrayTypeGetType ()
142142
// doesn't work on arrays, but the current implementation will preserve it anyway due to how it processes
143143
// string -> Type resolution. This will only impact code which would have failed at runtime, so very unlikely to
144144
// actually occur in real apps (and even if it does happen, it just increases size, doesn't break behavior).
145-
[Kept (By = Tool.Trimmer)] // NativeAOT doesn't preserve array element types just due to the usage of the array type
145+
[Kept (By = Tool.Trimmer | Tool.NativeAot)]
146146
class ArrayCreateInstanceByNameElement
147147
{
148148
public ArrayCreateInstanceByNameElement ()
@@ -151,7 +151,6 @@ public ArrayCreateInstanceByNameElement ()
151151
}
152152

153153
[Kept]
154-
[ExpectedWarning ("IL2032", Tool.NativeAot, "https://github.com/dotnet/runtime/issues/82447")]
155154
static void TestArrayCreateInstanceByName ()
156155
{
157156
Activator.CreateInstance ("test", "Mono.Linker.Tests.Cases.DataFlow.ComplexTypeHandling+ArrayCreateInstanceByNameElement[]");

src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ActivatorCreateInstance.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ public FromParameterOnStaticMethodTypeB (int arg) { }
171171
}
172172

173173
// Small formatting difference
174-
[ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, Object[])", Tool.Trimmer, "")]
174+
[ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, Object[])", Tool.Trimmer | Tool.NativeAot, "")]
175175
[ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, params Object[])", Tool.Analyzer, "")]
176176
[ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance), nameof (CultureInfo))]
177177
[Kept]
@@ -197,7 +197,7 @@ public FromParameterOnInstanceMethodType (int arg, int arg2) { }
197197

198198
[ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type)")]
199199
// Small formatting difference
200-
[ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, Object[])", Tool.Trimmer, "")]
200+
[ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, Object[])", Tool.Trimmer | Tool.NativeAot, "")]
201201
[ExpectedWarning ("IL2067", nameof (Activator) + "." + nameof (Activator.CreateInstance) + "(Type, params Object[])", Tool.Analyzer, "")]
202202
[Kept]
203203
private static void FromParameterWithNonPublicConstructors (
@@ -552,6 +552,7 @@ private static void TestCreateInstanceOfTWithNewConstraint<
552552
[Kept]
553553
class TestCreateInstanceOfTWithNoConstraintType
554554
{
555+
[Kept(By = Tool.NativeAot /* native AOT intrinsically expands CreateInstance<T> and would keep this method, albeit not reflection-visible */)]
555556
public TestCreateInstanceOfTWithNoConstraintType ()
556557
{
557558
}
@@ -680,7 +681,7 @@ public void TestCreateInstance ()
680681

681682
[Kept]
682683
[KeptBaseType (typeof (AnnotatedBase))]
683-
[KeptMember (".ctor()")]
684+
[KeptMember (".ctor()", By = Tool.Trimmer /* This type is never allocated so there's no reason to keep ctor due to a GetType call */)]
684685
class Derived : AnnotatedBase
685686
{
686687
[Kept]

src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/ExpressionPropertyMethodInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,10 @@ public int InstancePropertyViaReflection {
8383
}
8484

8585
[Kept]
86-
[ExpectedWarning ("IL2026", nameof (StaticPropertyExpressionAccess), Tool.Trimmer, "https://github.com/dotnet/linker/issues/2669")]
86+
[ExpectedWarning ("IL2026", nameof (StaticPropertyExpressionAccess), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2669")]
8787
[ExpectedWarning ("IL2026", nameof (StaticPropertyViaReflection))]
8888
[ExpectedWarning ("IL2026", nameof (StaticPropertyViaRuntimeMethod))]
89-
[ExpectedWarning ("IL2026", nameof (InstancePropertyExpressionAccess), Tool.Trimmer, "https://github.com/dotnet/linker/issues/2669")]
89+
[ExpectedWarning ("IL2026", nameof (InstancePropertyExpressionAccess), Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2669")]
9090
[ExpectedWarning ("IL2026", nameof (InstancePropertyViaReflection))]
9191
public static void Test ()
9292
{

src/tools/illink/test/Mono.Linker.Tests.Cases/Reflection/MethodsUsedViaReflection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ private void PrivateMethodWithRUC () { }
337337
}
338338

339339
[Kept]
340-
[ExpectedWarning ("IL2026", Tool.Trimmer, "https://github.com/dotnet/linker/issues/2638")]
340+
[ExpectedWarning ("IL2026", Tool.Trimmer | Tool.NativeAot, "https://github.com/dotnet/linker/issues/2638")]
341341
public static void Test ()
342342
{
343343
BindingFlags left = BindingFlags.Instance | BindingFlags.Static;

0 commit comments

Comments
 (0)