Skip to content

Commit 1d48e7b

Browse files
committed
Fix error caused by looking for framework assemblies with a closed generic type.
1 parent 87f4297 commit 1d48e7b

File tree

2 files changed

+52
-90
lines changed

2 files changed

+52
-90
lines changed

Clojure/Clojure/Lib/ClrTypeSpec2.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,6 +923,12 @@ private string MaybeAddBackquoteArity(IClrTypeIdentifier name)
923923
public static Type GetTypeFromName(string name, Namespace ns = null)
924924
{
925925
ClrTypeSpec spec = Parse(name);
926+
return GetTypeFromParsedName(spec);
927+
928+
}
929+
930+
public static Type GetTypeFromParsedName(ClrTypeSpec spec, Namespace ns = null)
931+
{
926932
if (spec is null)
927933
return null;
928934
return spec.Resolve(

Clojure/Clojure/Lib/RT.cs

Lines changed: 46 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -2811,7 +2811,7 @@ public int GetHashCode(AssemblyName obj)
28112811
#if (NET48_OR_GREATER || !NETFRAMEWORK)
28122812
var trustedAssemblies = AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES") as string;
28132813
#else
2814-
var trustedAssemblies = "";
2814+
var trustedAssemblies = "";
28152815
#endif
28162816
if (!string.IsNullOrEmpty(trustedAssemblies))
28172817
{
@@ -2826,69 +2826,6 @@ public int GetHashCode(AssemblyName obj)
28262826
return names;
28272827
});
28282828

2829-
2830-
2831-
// // Cache for all runtime library assembly names, loaded once on demand.
2832-
// private static readonly Lazy<List<AssemblyName>> _runtimeAssemblyNames = new(() =>
2833-
// {
2834-
// var names = new List<AssemblyName>();
2835-
2836-
// try
2837-
// {
2838-
// // DependencyContext.Default can be null in some scenarios (like unit tests or static initializers).
2839-
// // Loading the context from a known assembly is more robust.
2840-
2841-
// var entryAssembly = Assembly.GetEntryAssembly() ?? typeof(RT).Assembly;
2842-
// var context = Microsoft.Extensions.DependencyModel.DependencyContext.Load(entryAssembly);
2843-
2844-
// if (context != null)
2845-
// {
2846-
// foreach (var lib in context.RuntimeLibraries)
2847-
// {
2848-
// foreach (var assembly in lib.RuntimeAssemblyGroups.SelectMany(g => g.AssetPaths))
2849-
// {
2850-
// try
2851-
// {
2852-
// var name = new AssemblyName(Path.GetFileNameWithoutExtension(assembly));
2853-
// names.Add(name);
2854-
// }
2855-
// catch { }
2856-
// }
2857-
// }
2858-
// }
2859-
// }
2860-
// catch { }
2861-
2862-
// // Also include shared runtime libraries from TRUSTED_PLATFORM_ASSEMBLIES
2863-
// try
2864-
// {
2865-
//#if (NET48_OR_GREATER || !NETFRAMEWORK)
2866-
// var trustedAssemblies = AppContext.GetData("TRUSTED_PLATFORM_ASSEMBLIES") as string;
2867-
//#else
2868-
// var trustedAssemblies = "";
2869-
//#endif
2870-
// if (!string.IsNullOrEmpty(trustedAssemblies))
2871-
// {
2872-
// var paths = trustedAssemblies.Split(Path.PathSeparator);
2873-
// foreach (var path in paths)
2874-
// {
2875-
// try
2876-
// {
2877-
// var name = AssemblyName.GetAssemblyName(path);
2878-
// if (!names.Any(n => n.Name == name.Name))
2879-
// {
2880-
// names.Add(name);
2881-
// }
2882-
// }
2883-
// catch { }
2884-
// }
2885-
// }
2886-
// }
2887-
// catch { }
2888-
2889-
// return names;
2890-
// });
2891-
28922829
internal static readonly char[] _triggerTypeChars = ['`', ',', '[', '&', '*'];
28932830

28942831
public static Type classForName(string p)
@@ -2952,50 +2889,69 @@ internal static Type classForName(string p, Namespace ns, bool canCallClrTypeSpe
29522889
}
29532890
}
29542891

2892+
29552893
// Try to load from runtime libraries if we have DependencyContext.
2894+
// We might use the parsed name again, so save it here for use now and below.
2895+
2896+
var parsedTypename = ClrTypeSpec.Parse(p);
2897+
29562898
{
29572899
// Split the type name to identify the namespace and simple name.
2958-
string namespaceName = null;
2959-
string typeName = p;
2960-
int lastDot = p.LastIndexOf('.');
2961-
if (lastDot > 0)
2900+
// If we get something like
2901+
// System.Collections.Concurrent.ConcurrentDictionary`2[System.Object,System.Object]
2902+
// we want to extract System.Collections.Concurrent as the namespace.
2903+
// Worst case: we do a ClrTypeSpec.Parse and extract the namespace from there.
2904+
// Easier, but I won't guarantee it: move forward as long as we don't run into back characters, then back up to the last dot.
2905+
2906+
string assemblyNameString = null;
2907+
2908+
if (!string.IsNullOrWhiteSpace(parsedTypename.AssemblyName))
2909+
assemblyNameString = parsedTypename.AssemblyName;
2910+
else
29622911
{
2963-
namespaceName = p.Substring(0, lastDot);
2964-
typeName = p.Substring(lastDot + 1);
2912+
var baseName = parsedTypename.Name.DisplayName; // Note: this does not include nested.
2913+
int lastDot = baseName.LastIndexOf('.');
2914+
if (lastDot > 0)
2915+
assemblyNameString = baseName.Substring(0, lastDot);
2916+
// If there is no dot, no point in moving forward. just leave assemblyNameString == null;].
29652917
}
29662918

2967-
if (!string.IsNullOrEmpty(namespaceName))
2919+
if (!string.IsNullOrEmpty(assemblyNameString))
29682920
{
29692921
var runtimeAssemblyNames = _runtimeAssemblyNames.Value;
29702922

2971-
var targetAssemblyName = new AssemblyName(namespaceName);
2972-
2973-
// try if the namespace directly matches the assembly name.
2974-
if (runtimeAssemblyNames.TryGetValue(targetAssemblyName, out var path))
2923+
try
29752924
{
2925+
var targetAssemblyName = new AssemblyName(assemblyNameString);
29762926

2977-
if (loadedAssemblies.Any(a => a.GetName().Name.Equals(namespaceName, StringComparison.OrdinalIgnoreCase)))
2927+
// try if the namespace directly matches the assembly name.
2928+
if (runtimeAssemblyNames.TryGetValue(targetAssemblyName, out var path))
29782929
{
2979-
// Skip if this assembly is already loaded.
2980-
}
2981-
else
2982-
{
2983-
NumRuntimeAssemblyLoads++;
2984-
var assy = string.IsNullOrWhiteSpace(path) ? Assembly.Load(targetAssemblyName) : Assembly.LoadFrom(path);
2985-
var type = assy.GetType(p, false);
2986-
if (type != null && (type.IsPublic || type.IsNestedPublic))
2930+
2931+
if (loadedAssemblies.Any(a => a.GetName().Name.Equals(assemblyNameString, StringComparison.OrdinalIgnoreCase)))
2932+
{
2933+
// Skip if this assembly is already loaded.
2934+
}
2935+
else
29872936
{
2988-
NumRuntimeAssemblyFinds++;
2989-
return type;
2937+
NumRuntimeAssemblyLoads++;
2938+
var assy = string.IsNullOrWhiteSpace(path) ? Assembly.Load(targetAssemblyName) : Assembly.LoadFrom(path);
2939+
var type = assy.GetType(p, false);
2940+
if (type != null && (type.IsPublic || type.IsNestedPublic))
2941+
{
2942+
NumRuntimeAssemblyFinds++;
2943+
return type;
2944+
}
29902945
}
29912946
}
29922947
}
2948+
catch
2949+
{
2950+
// Ignore failures to load assembly.
2951+
}
29932952
}
29942953
}
29952954

2996-
2997-
2998-
29992955
// Search by simple type name (slow path).
30002956
// At some point this became a no-op unless running on Mono, so I restricted it to that.
30012957
if (IsRunningOnMono)
@@ -3044,7 +3000,7 @@ internal static Type classForName(string p, Namespace ns, bool canCallClrTypeSpe
30443000

30453001
if (canCallClrTypeSpec)
30463002
{
3047-
var t1 = ClrTypeSpec.GetTypeFromName(p, ns);
3003+
var t1 = ClrTypeSpec.GetTypeFromParsedName(parsedTypename, ns);
30483004
if (t1 is not null)
30493005
{
30503006
NumParsing++;

0 commit comments

Comments
 (0)