Skip to content

Commit

Permalink
Stop generating unresolvable type forwarders (dotnet#854)
Browse files Browse the repository at this point in the history
Filter the list of type forwarders down to the types that we're actually generating. This makes it possible to call Assembly.GetExportedTypes on things like mscorlib without getting exceptions.
  • Loading branch information
MichalStrehovsky authored Mar 25, 2021
1 parent 92d54cc commit 4564ad6
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
using Debug = System.Diagnostics.Debug;
using EcmaModule = Internal.TypeSystem.Ecma.EcmaModule;
using CustomAttributeHandle = System.Reflection.Metadata.CustomAttributeHandle;
using ExportedTypeHandle = System.Reflection.Metadata.ExportedTypeHandle;

namespace ILCompiler
{
Expand Down Expand Up @@ -260,6 +261,25 @@ public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle)
return _parent._reflectableAttributes.Contains(new ReflectableCustomAttribute(module, caHandle));
}

public bool GeneratesMetadata(EcmaModule module, ExportedTypeHandle exportedTypeHandle)
{
try
{
// We'll possibly need to do something else here if we ever use this MetadataManager
// with compilation modes that generate multiple metadata blobs.
// (Multi-module or .NET Native style shared library.)
// We are currently missing type forwarders pointing to the other blobs.
var targetType = (MetadataType)module.GetObject(exportedTypeHandle);
return GeneratesMetadata(targetType);
}
catch (TypeSystemException)
{
// No harm in generating a forwarder that didn't resolve.
// We'll get matching behavior at runtime.
return true;
}
}

public bool IsBlocked(MetadataType typeDef)
{
return _blockingPolicy.IsBlocked(typeDef);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -728,6 +728,23 @@ public bool GeneratesMetadata(EcmaModule module, CustomAttributeHandle caHandle)
return _factory.CustomAttributeMetadata(new ReflectableCustomAttribute(module, caHandle)).Marked;
}

public bool GeneratesMetadata(EcmaModule module, ExportedTypeHandle exportedTypeHandle)
{
try
{
// Generate the forwarder only if we generated the target type.
// If the target type is in a different compilation group, assume we generated it there.
var targetType = (MetadataType)module.GetObject(exportedTypeHandle);
return GeneratesMetadata(targetType) || !_factory.CompilationModuleGroup.ContainsType(targetType);
}
catch (TypeSystemException)
{
// No harm in generating a forwarder that didn't resolve.
// We'll get matching behavior at runtime.
return true;
}
}

public bool IsBlocked(MetadataType typeDef)
{
return _blockingPolicy.IsBlocked(typeDef);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ public interface IMetadataPolicy
/// </summary>
bool GeneratesMetadata(Cts.Ecma.EcmaModule module, Ecma.CustomAttributeHandle customAttribute);

/// <summary>
/// Returns true if an exported type entry should generate <see cref="TypeForwarder"/> metadata.
/// </summary>
bool GeneratesMetadata(Cts.Ecma.EcmaModule module, Ecma.ExportedTypeHandle exportedType);

/// <summary>
/// Returns true if a type should be blocked from generating any metadata.
/// Blocked interfaces are skipped from interface lists, and custom attributes referring to
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ private void HandleTypeForwarders(Cts.Ecma.EcmaModule module)
{
foreach (var exportedTypeHandle in module.MetadataReader.ExportedTypes)
{
if (!_policy.GeneratesMetadata(module, exportedTypeHandle))
{
continue;
}

Ecma.ExportedType exportedType = module.MetadataReader.GetExportedType(exportedTypeHandle);
if (exportedType.IsForwarder || exportedType.Implementation.Kind == Ecma.HandleKind.ExportedType)
{
Expand Down

0 comments on commit 4564ad6

Please sign in to comment.