Skip to content

Commit a4f1e74

Browse files
authored
Preserve all InternalsVisibleTo attributes in ILLink Trimmer (#98910)
Removes previous special handling to only keep IVT attributes for assemblies that were resolvable and marked at link time. This behaviour could cause a noticeable difference in behaviour at runtime without emitting any trim analysis warnings while providing no mechanism to retain the attributes. The removal of these attributes provides only a neglible size reduction. Fixes #92582
1 parent af05e76 commit a4f1e74

File tree

6 files changed

+49
-56
lines changed

6 files changed

+49
-56
lines changed

src/tools/illink/src/linker/Linker.Steps/MarkStep.cs

Lines changed: 5 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ protected LinkContext Context {
6262
protected Queue<(MethodDefinition, DependencyInfo, MessageOrigin)> _methods;
6363
protected Dictionary<MethodDefinition, MarkScopeStack.Scope> _virtual_methods;
6464
protected Queue<AttributeProviderPair> _assemblyLevelAttributes;
65-
readonly List<AttributeProviderPair> _ivt_attributes;
6665
protected Queue<(AttributeProviderPair, DependencyInfo, MarkScopeStack.Scope)> _lateMarkedAttributes;
6766
protected List<(TypeDefinition, MarkScopeStack.Scope)> _typesWithInterfaces;
6867
protected HashSet<AssemblyDefinition> _dynamicInterfaceCastableImplementationTypesDiscovered;
@@ -222,7 +221,6 @@ public MarkStep ()
222221
_methods = new Queue<(MethodDefinition, DependencyInfo, MessageOrigin)> ();
223222
_virtual_methods = new Dictionary<MethodDefinition, MarkScopeStack.Scope> ();
224223
_assemblyLevelAttributes = new Queue<AttributeProviderPair> ();
225-
_ivt_attributes = new List<AttributeProviderPair> ();
226224
_lateMarkedAttributes = new Queue<(AttributeProviderPair, DependencyInfo, MarkScopeStack.Scope)> ();
227225
_typesWithInterfaces = new List<(TypeDefinition, MarkScopeStack.Scope)> ();
228226
_dynamicInterfaceCastableImplementationTypesDiscovered = new HashSet<AssemblyDefinition> ();
@@ -288,42 +286,6 @@ protected virtual void Complete ()
288286
}
289287
}
290288

291-
bool ProcessInternalsVisibleAttributes ()
292-
{
293-
bool marked_any = false;
294-
foreach (var attr in _ivt_attributes) {
295-
296-
var provider = attr.Provider;
297-
Debug.Assert (attr.Provider is ModuleDefinition or AssemblyDefinition);
298-
var assembly = (provider is ModuleDefinition module) ? module.Assembly : provider as AssemblyDefinition;
299-
300-
using var assemblyScope = ScopeStack.PushLocalScope (new MessageOrigin (assembly));
301-
302-
if (!Annotations.IsMarked (attr.Attribute) && IsInternalsVisibleAttributeAssemblyMarked (attr.Attribute)) {
303-
MarkCustomAttribute (attr.Attribute, new DependencyInfo (DependencyKind.AssemblyOrModuleAttribute, attr.Provider));
304-
marked_any = true;
305-
}
306-
}
307-
308-
return marked_any;
309-
310-
bool IsInternalsVisibleAttributeAssemblyMarked (CustomAttribute ca)
311-
{
312-
System.Reflection.AssemblyName an;
313-
try {
314-
an = new System.Reflection.AssemblyName ((string) ca.ConstructorArguments[0].Value);
315-
} catch {
316-
return false;
317-
}
318-
319-
var assembly = Context.GetLoadedAssembly (an.Name!);
320-
if (assembly == null)
321-
return false;
322-
323-
return Annotations.IsMarked (assembly.MainModule);
324-
}
325-
}
326-
327289
static bool TypeIsDynamicInterfaceCastableImplementation (TypeDefinition type)
328290
{
329291
if (!type.IsInterface || !type.HasInterfaces || !type.HasCustomAttributes)
@@ -416,8 +378,7 @@ void Process ()
416378
ProcessMarkedPending () ||
417379
ProcessLazyAttributes () ||
418380
ProcessLateMarkedAttributes () ||
419-
MarkFullyPreservedAssemblies () ||
420-
ProcessInternalsVisibleAttributes ()) ;
381+
MarkFullyPreservedAssemblies ()) ;
421382

422383
ProcessPendingTypeChecks ();
423384
}
@@ -1169,6 +1130,9 @@ protected virtual bool ShouldMarkCustomAttribute (CustomAttribute ca, ICustomAtt
11691130
case "System.Runtime.InteropServices.InterfaceTypeAttribute":
11701131
case "System.Runtime.InteropServices.GuidAttribute":
11711132
return true;
1133+
// May be implicitly used by the runtime
1134+
case "System.Runtime.CompilerServices.InternalsVisibleToAttribute":
1135+
return true;
11721136
}
11731137

11741138
TypeDefinition? type = Context.Resolve (attr_type);
@@ -1546,10 +1510,7 @@ bool ProcessLazyAttributes ()
15461510
if (IsAttributeRemoved (customAttribute, resolved.DeclaringType) && Annotations.GetAction (CustomAttributeSource.GetAssemblyFromCustomAttributeProvider (assemblyLevelAttribute.Provider)) == AssemblyAction.Link)
15471511
continue;
15481512

1549-
if (customAttribute.AttributeType.IsTypeOf ("System.Runtime.CompilerServices", "InternalsVisibleToAttribute") && !Annotations.IsMarked (customAttribute)) {
1550-
_ivt_attributes.Add (assemblyLevelAttribute);
1551-
continue;
1552-
} else if (!ShouldMarkTopLevelCustomAttribute (assemblyLevelAttribute, resolved)) {
1513+
if (!ShouldMarkTopLevelCustomAttribute (assemblyLevelAttribute, resolved)) {
15531514
skippedItems.Add (assemblyLevelAttribute);
15541515
continue;
15551516
}

src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/TestCaseUtils.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ private static IEnumerable<string> GetTestDependencies (string testCaseDir, Synt
9090
switch (attributeName) {
9191
case "SetupCompileBefore": {
9292
var arrayExpression = args["#1"];
93-
if (arrayExpression is not (ArrayCreationExpressionSyntax or ImplicitArrayCreationExpressionSyntax))
93+
if (arrayExpression is not (ArrayCreationExpressionSyntax or ImplicitArrayCreationExpressionSyntax or CollectionExpressionSyntax))
9494
throw new InvalidOperationException ();
9595
foreach (var sourceFile in args["#1"].DescendantNodes ().OfType<LiteralExpressionSyntax> ())
9696
yield return Path.Combine (testCaseDir, LinkerTestBase.GetStringFromExpression (sourceFile));

src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/AttributesTests.g.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,12 @@ public Task IVTUnused ()
123123
return RunTest (allowMissingWarnings: true);
124124
}
125125

126+
[Fact]
127+
public Task IVTUnusedKeptWhenKeepingUsedAttributesOnly ()
128+
{
129+
return RunTest (allowMissingWarnings: true);
130+
}
131+
126132
[Fact]
127133
public Task IVTUsed ()
128134
{
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#if IVT
2+
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo ("missing")]
3+
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo ("test-with-key, PublicKey=00240000")]
4+
#endif
5+
6+
namespace Mono.Linker.Tests.Cases.Attributes.Dependencies;
7+
8+
public class IVTUnusedLib;
Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
11
using System.Runtime.CompilerServices;
2+
using Mono.Linker.Tests.Cases.Attributes.Dependencies;
23
using Mono.Linker.Tests.Cases.Expectations.Assertions;
34
using Mono.Linker.Tests.Cases.Expectations.Metadata;
45

5-
#if IVT
6-
[assembly: InternalsVisibleTo ("missing")]
7-
[assembly: InternalsVisibleTo ("test-with-key, PublicKey=00240000")]
6+
namespace Mono.Linker.Tests.Cases.Attributes;
87

9-
#endif
10-
11-
namespace Mono.Linker.Tests.Cases.Attributes
8+
[SetupCompileBefore ("lib.dll", ["Dependencies/IVTUnused_Lib.cs"], defines: ["IVT"])]
9+
[KeptAssembly ("lib.dll")]
10+
[KeptTypeInAssembly ("lib.dll", typeof(IVTUnusedLib))]
11+
[KeptAttributeInAssembly ("lib.dll", typeof (InternalsVisibleToAttribute))]
12+
class IVTUnused
1213
{
13-
[Define ("IVT")]
14-
class IVTUnused
14+
static void Main ()
1515
{
16-
static void Main ()
17-
{
18-
}
16+
_ = new IVTUnusedLib ();
1917
}
2018
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
using System.Runtime.CompilerServices;
2+
using Mono.Linker.Tests.Cases.Attributes.Dependencies;
3+
using Mono.Linker.Tests.Cases.Expectations.Assertions;
4+
using Mono.Linker.Tests.Cases.Expectations.Metadata;
5+
6+
namespace Mono.Linker.Tests.Cases.Attributes;
7+
8+
[SetupCompileBefore ("lib.dll", ["Dependencies/IVTUnused_Lib.cs"], defines: ["IVT"])]
9+
[KeptAssembly ("lib.dll")]
10+
[KeptTypeInAssembly ("lib.dll", typeof(IVTUnusedLib))]
11+
[KeptAttributeInAssembly ("lib.dll", typeof (InternalsVisibleToAttribute))]
12+
13+
[SetupLinkerArgument("--used-attrs-only", "true")]
14+
class IVTUnusedKeptWhenKeepingUsedAttributesOnly
15+
{
16+
static void Main ()
17+
{
18+
_ = new IVTUnusedLib ();
19+
}
20+
}

0 commit comments

Comments
 (0)