Skip to content

Commit 9407c9c

Browse files
authored
Fix type parsing issues in ILLink and ILC (#104060)
- Fixes #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 #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.
1 parent 856a0a6 commit 9407c9c

File tree

30 files changed

+308
-136
lines changed

30 files changed

+308
-136
lines changed

docs/tools/illink/error-codes.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,6 +1870,22 @@ void TestMethod()
18701870
}
18711871
```
18721872

1873+
#### `IL2122`: Type 'typeName' is not assembly qualified. Type name strings used for dynamically accessing a type should be assembly qualified.
1874+
1875+
- 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.
1876+
1877+
```C#
1878+
// warning IL2122: Type 'MyClass' is not assembly qualified. Type name strings used for dynamically accessing a type should be assembly qualified.
1879+
GetTypeWrapper("MyClass");
1880+
1881+
class MyClass { }
1882+
1883+
// May be defined in another assembly, so at runtime Type.GetType will look in that assembly for "MyClass".
1884+
void GetTypeWrapper([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] string typeName)
1885+
{
1886+
var type = Type.GetType(typeName);
1887+
}
1888+
```
18731889

18741890
## Single-File Warning Codes
18751891

eng/testing/tests.mobile.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
<PublishTrimmed>true</PublishTrimmed>
3030
<!-- Suppress trimming warnings as these are tests -->
3131
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
32-
<NoWarn>$(NoWarn);IL2103;IL2105;IL2025;IL2111</NoWarn>
32+
<NoWarn>$(NoWarn);IL2103;IL2025;IL2111;IL2122</NoWarn>
3333

3434
<!-- Reduce library test app size by trimming framework library features -->
3535
<DebuggerSupport Condition="'$(DebuggerSupport)' == '' and '$(Configuration)' != 'Debug'">false</DebuggerSupport>

eng/testing/tests.singlefile.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
<IlcSdkPath>$(CoreCLRAotSdkDir)</IlcSdkPath>
3030
<IlcFrameworkPath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkPath>
3131
<IlcFrameworkNativePath>$(NetCoreAppCurrentTestHostSharedFrameworkPath)</IlcFrameworkNativePath>
32-
<NoWarn>$(NoWarn);IL1005;IL2105;IL3000;IL3001;IL3002;IL3003;IL3050;IL3051;IL3052;IL3053</NoWarn>
32+
<NoWarn>$(NoWarn);IL1005;IL2122;IL3000;IL3001;IL3002;IL3003;IL3050;IL3051;IL3052;IL3053</NoWarn>
3333
<TrimMode>partial</TrimMode>
3434
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
3535
<TrimmerSingleWarn>false</TrimmerSingleWarn>

src/coreclr/tools/Common/TypeSystem/Common/Utilities/CustomAttributeTypeNameParser.cs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,18 @@ public static TypeDesc GetTypeByCustomAttributeTypeName(this ModuleDesc module,
3636
}
3737

3838
public static TypeDesc GetTypeByCustomAttributeTypeNameForDataFlow(string name, ModuleDesc callingModule,
39-
TypeSystemContext context, List<ModuleDesc> referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary)
39+
TypeSystemContext context, List<ModuleDesc> referencedModules, bool needsAssemblyName, out bool failedBecauseNotFullyQualified)
4040
{
41-
typeWasNotFoundInAssemblyNorBaseLibrary = false;
42-
41+
failedBecauseNotFullyQualified = false;
4342
if (!TypeName.TryParse(name.AsSpan(), out TypeName parsed, s_typeNameParseOptions))
4443
return null;
4544

45+
if (needsAssemblyName && !IsFullyQualified(parsed))
46+
{
47+
failedBecauseNotFullyQualified = true;
48+
return null;
49+
}
50+
4651
TypeNameResolver resolver = new()
4752
{
4853
_context = context,
@@ -52,8 +57,33 @@ public static TypeDesc GetTypeByCustomAttributeTypeNameForDataFlow(string name,
5257

5358
TypeDesc type = resolver.Resolve(parsed);
5459

55-
typeWasNotFoundInAssemblyNorBaseLibrary = resolver._typeWasNotFoundInAssemblyNorBaseLibrary;
5660
return type;
61+
62+
static bool IsFullyQualified(TypeName typeName)
63+
{
64+
if (typeName.AssemblyName is null)
65+
{
66+
return false;
67+
}
68+
69+
if (typeName.IsArray || typeName.IsPointer || typeName.IsByRef)
70+
{
71+
return IsFullyQualified(typeName.GetElementType());
72+
}
73+
74+
if (typeName.IsConstructedGenericType)
75+
{
76+
foreach (var typeArgument in typeName.GetGenericArguments())
77+
{
78+
if (!IsFullyQualified(typeArgument))
79+
{
80+
return false;
81+
}
82+
}
83+
}
84+
85+
return true;
86+
}
5787
}
5888

5989
private struct TypeNameResolver
@@ -64,7 +94,6 @@ private struct TypeNameResolver
6494
internal Func<ModuleDesc, string, MetadataType> _canonResolver;
6595

6696
internal List<ModuleDesc> _referencedModules;
67-
internal bool _typeWasNotFoundInAssemblyNorBaseLibrary;
6897

6998
internal TypeDesc Resolve(TypeName typeName)
7099
{
@@ -136,8 +165,6 @@ private TypeDesc GetSimpleType(TypeName typeName)
136165
return type;
137166
}
138167
}
139-
140-
_typeWasNotFoundInAssemblyNorBaseLibrary = true;
141168
}
142169

143170
if (_throwIfNotFound)

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,13 @@ internal bool TryResolveTypeNameAndMark(string typeName, in DiagnosticContext di
8989

9090
List<ModuleDesc> referencedModules = new();
9191
TypeDesc foundType = CustomAttributeTypeNameParser.GetTypeByCustomAttributeTypeNameForDataFlow(typeName, callingModule, diagnosticContext.Origin.MemberDefinition!.Context,
92-
referencedModules, out bool typeWasNotFoundInAssemblyNorBaseLibrary);
92+
referencedModules, needsAssemblyName, out bool failedBecauseNotFullyQualified);
9393
if (foundType == null)
9494
{
95-
if (needsAssemblyName && typeWasNotFoundInAssemblyNorBaseLibrary)
96-
diagnosticContext.AddDiagnostic(DiagnosticId.TypeWasNotFoundInAssemblyNorBaseLibrary, typeName);
97-
95+
if (failedBecauseNotFullyQualified)
96+
{
97+
diagnosticContext.AddDiagnostic(DiagnosticId.TypeNameIsNotAssemblyQualified, typeName);
98+
}
9899
type = default;
99100
return false;
100101
}

src/coreclr/tools/aot/ILCompiler.Trimming.Tests/TestCasesRunner/AssemblyChecker.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
using Mono.Cecil;
1313
using Mono.Cecil.Cil;
1414
using Mono.Linker.Tests.Cases.Expectations.Assertions;
15+
using Mono.Linker.Tests.Cases.Expectations.Helpers;
1516
using Mono.Linker.Tests.Extensions;
1617
using Xunit;
1718
using MetadataType = Internal.TypeSystem.MetadataType;

src/libraries/System.ObjectModel/tests/TrimmingTests/TypeDescriptionProviderAttributeCtorTest.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class Program
1414
/// </summary>
1515
static int Main(string[] args)
1616
{
17-
TypeDescriptionProviderAttribute attr = new TypeDescriptionProviderAttribute("Program+MyTypeDescriptionProvider");
17+
TypeDescriptionProviderAttribute attr = new TypeDescriptionProviderAttribute("Program+MyTypeDescriptionProvider, project");
1818
if (!RunTest(attr))
1919
{
2020
return -1;

src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/DebuggerTypeProxyAttributeTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public DebuggerProxy(MyClass instance)
5353
}
5454
}
5555

56-
[DebuggerTypeProxy("Program+MyClassWithProxyStringProxy")]
56+
[DebuggerTypeProxy("Program+MyClassWithProxyStringProxy, project")]
5757
public class MyClassWithProxyString
5858
{
5959
public string Name { get; set; }

src/libraries/System.Runtime/tests/System.Runtime.Tests/TrimmingTests/DebuggerVisualizerAttributeTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ public DebuggerVisualizerObjectSource(MyClass instance)
113113
}
114114
}
115115

116-
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer")]
117-
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer2", "Program+MyClassWithVisualizerStringVisualizerObjectSource")]
116+
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer, project")]
117+
[DebuggerVisualizer("Program+MyClassWithVisualizerStringVisualizer2, project", "Program+MyClassWithVisualizerStringVisualizerObjectSource, project")]
118118
public class MyClassWithVisualizerString
119119
{
120120
public string Name { get; set; }

src/mono/msbuild/apple/build/AppleBuild.LocalBuild.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737
<PropertyGroup Condition="'$(EnableAggressiveTrimming)' == 'true'">
3838
<!-- Suppress trimming warnings as these are tests -->
3939
<SuppressTrimAnalysisWarnings>true</SuppressTrimAnalysisWarnings>
40-
<NoWarn>$(NoWarn);IL2103;IL2105;IL2025;IL2111</NoWarn>
40+
<NoWarn>$(NoWarn);IL2103;IL2025;IL2111;IL2122</NoWarn>
4141
</PropertyGroup>
4242

4343
<!-- 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

0 commit comments

Comments
 (0)