Skip to content

Commit 55a83d6

Browse files
authored
Assembly resolving adjustments. (#90601)
* Fix a bug when SkipUnresolved=false. If TryResolve is called on a missing assembly, any subsequent Resolve calls for the same assembly will not result in an error. This is because there was a single unresolved assembly cache and once an assembly was in the list, no further errors would be reported. To fix this, I introduced a second cache. One for probing and one for not probing. * I don't think letting these caches be null is worth the complexity it adds. Make the caches readonly. * Open up Resolve for overriding. We need a way to hook in to the Resolve calls when a code path calls `Mono.Cecil.IAssemblyResolver.Resolve`
1 parent 9d747c9 commit 55a83d6

File tree

1 file changed

+18
-7
lines changed

1 file changed

+18
-7
lines changed

src/tools/illink/src/linker/Linker/AssemblyResolver.cs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ public class AssemblyResolver : IAssemblyResolver
4848
readonly List<MemoryMappedViewStream> _viewStreams = new ();
4949
readonly ReaderParameters _defaultReaderParameters;
5050

51-
HashSet<string>? _unresolvedAssemblies;
51+
readonly HashSet<string> _unresolvedAssembliesProbing = new ();
52+
readonly HashSet<string> _unresolvedAssemblies = new ();
5253
HashSet<string>? _reportedUnresolvedAssemblies;
5354

5455
public AssemblyResolver (LinkContext context)
@@ -69,6 +70,16 @@ public string GetAssemblyLocation (AssemblyDefinition assembly)
6970
throw new InternalErrorException ($"Assembly '{assembly}' was not loaded using ILLink resolver");
7071
}
7172

73+
/// <summary>
74+
/// We need to track unresolved assemblies separately when probing vs not probing.
75+
///
76+
/// This prevents a TryResolve call that fails to resolve an assembly from silencing a later Resolve call that fails to resolve the same
77+
/// assembly when SkipUnresolved is false.
78+
/// </summary>
79+
/// <param name="probing"></param>
80+
/// <returns>The known unresolved assemblies for probing mode or non probing mode</returns>
81+
HashSet<string> GetUnresolvedAssemblies (bool probing) => probing ? _unresolvedAssembliesProbing : _unresolvedAssemblies;
82+
7283
AssemblyDefinition? ResolveFromReferences (AssemblyNameReference name)
7384
{
7485
foreach (var reference in _references) {
@@ -92,7 +103,8 @@ public string GetAssemblyLocation (AssemblyDefinition assembly)
92103
if (AssemblyCache.TryGetValue (name.Name, out AssemblyDefinition? asm))
93104
return asm;
94105

95-
if (_unresolvedAssemblies?.Contains (name.Name) == true) {
106+
var unresolvedAssemblies = GetUnresolvedAssemblies (probing);
107+
if (unresolvedAssemblies.Contains (name.Name)) {
96108
if (!probing)
97109
ReportUnresolvedAssembly (name);
98110
return null;
@@ -104,12 +116,10 @@ public string GetAssemblyLocation (AssemblyDefinition assembly)
104116
asm ??= SearchDirectory (name);
105117

106118
if (asm == null) {
107-
_unresolvedAssemblies ??= new HashSet<string> ();
108-
109119
if (!probing)
110120
ReportUnresolvedAssembly (name);
111121

112-
_unresolvedAssemblies.Add (name.Name);
122+
unresolvedAssemblies.Add (name.Name);
113123
return null;
114124
}
115125

@@ -167,7 +177,7 @@ public AssemblyDefinition GetAssembly (string file)
167177
}
168178
}
169179

170-
public AssemblyDefinition? Resolve (AssemblyNameReference name)
180+
public virtual AssemblyDefinition? Resolve (AssemblyNameReference name)
171181
{
172182
return Resolve (name, probing: false);
173183
}
@@ -236,7 +246,8 @@ protected virtual void Dispose (bool disposing)
236246
}
237247

238248
AssemblyCache.Clear ();
239-
_unresolvedAssemblies?.Clear ();
249+
_unresolvedAssemblies.Clear ();
250+
_unresolvedAssembliesProbing.Clear ();
240251

241252
_reportedUnresolvedAssemblies?.Clear ();
242253

0 commit comments

Comments
 (0)