diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs index 1fda33a405bb7..1e35071174245 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Compilation.cs @@ -301,9 +301,16 @@ public ISymbolNode ComputeConstantLookup(ReadyToRunHelperId lookupKind, object t case ReadyToRunHelperId.TypeHandleForCasting: { var type = (TypeDesc)targetOfLookup; + + // We counter-intuitively ask for a constructed type symbol. This is needed due to IDynamicInterfaceCastable. + // If this cast happens with an object that implements IDynamicIntefaceCastable, user code will + // see a RuntimeTypeHandle representing this interface. + if (type.IsInterface) + return NodeFactory.MaximallyConstructableType(type); + if (type.IsNullable) - targetOfLookup = type.Instantiation[0]; - return NecessaryTypeSymbolIfPossible((TypeDesc)targetOfLookup); + type = type.Instantiation[0]; + return NecessaryTypeSymbolIfPossible(type); } case ReadyToRunHelperId.MethodDictionary: return NodeFactory.MethodGenericDictionary((MethodDesc)targetOfLookup); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs index 0d3f97754c8d8..4331b0dd5416a 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/ConstructedEETypeNode.cs @@ -31,6 +31,9 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact // relocs to nodes we emit. dependencyList.Add(factory.NecessaryTypeSymbol(_type), "NecessaryType for constructed type"); + if (_type is MetadataType mdType) + ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencyList, factory, mdType.Module); + DefType closestDefType = _type.GetClosestDefType(); if (_type.IsArray) @@ -66,6 +69,9 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact } } + // Ask the metadata manager if we have any dependencies due to the presence of the EEType. + factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencyList, factory, _type); + factory.InteropStubManager.AddInterestingInteropConstructedTypeDependencies(ref dependencyList, factory, _type); return dependencyList; diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs index beb16cf020085..f0e68ea0077bf 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs @@ -633,12 +633,16 @@ protected override DependencyList ComputeNonRelocationBasedDependencies(NodeFact } } - // Ask the metadata manager - // if we have any dependencies due to presence of the EEType. - factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type); + if (!ConstructedEETypeNode.CreationAllowed(_type)) + { + // If necessary MethodTable is the highest load level for this type, ask the metadata manager + // if we have any dependencies due to presence of the EEType. + factory.MetadataManager.GetDependenciesDueToEETypePresence(ref dependencies, factory, _type); - if (_type is MetadataType mdType) - ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencies, factory, mdType.Module); + // If necessary MethodTable is the highest load level, consider this a module use + if (_type is MetadataType mdType) + ModuleUseBasedDependencyAlgorithm.AddDependenciesDueToModuleUse(ref dependencies, factory, mdType.Module); + } if (_type.IsFunctionPointer) FunctionPointerMapNode.GetHashtableDependencies(ref dependencies, factory, (FunctionPointerType)_type); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs index d0f5ce91d6c3f..aa3883a2db509 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/InterfaceDispatchCellNode.cs @@ -71,7 +71,10 @@ public override IEnumerable GetStaticDependencies(NodeFacto result.Add(factory.ExternSymbol("RhpInitialDynamicInterfaceDispatch"), "Initial interface dispatch stub"); } - result.Add(factory.NecessaryTypeSymbol(_targetMethod.OwningType), "Interface type"); + // We counter-intuitively ask for a constructed type symbol. This is needed due to IDynamicInterfaceCastable. + // If this dispatch cell is ever used with an object that implements IDynamicIntefaceCastable, user code will + // see a RuntimeTypeHandle representing this interface. + result.Add(factory.ConstructedTypeSymbol(_targetMethod.OwningType), "Interface type"); return result; } @@ -88,7 +91,10 @@ public override void EncodeData(ref ObjectDataBuilder objData, NodeFactory facto objData.EmitPointerReloc(factory.ExternSymbol("RhpInitialDynamicInterfaceDispatch")); } - IEETypeNode interfaceType = factory.NecessaryTypeSymbol(_targetMethod.OwningType); + // We counter-intuitively ask for a constructed type symbol. This is needed due to IDynamicInterfaceCastable. + // If this dispatch cell is ever used with an object that implements IDynamicIntefaceCastable, user code will + // see a RuntimeTypeHandle representing this interface. + IEETypeNode interfaceType = factory.ConstructedTypeSymbol(_targetMethod.OwningType); if (factory.Target.SupportsRelativePointers) { if (interfaceType.RepresentsIndirectionCell) diff --git a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DeadCodeElimination.cs b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DeadCodeElimination.cs index c0c87c847995e..dbadaf5cd78de 100644 --- a/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DeadCodeElimination.cs +++ b/src/tests/nativeaot/SmokeTests/TrimmingBehaviors/DeadCodeElimination.cs @@ -322,7 +322,7 @@ public static void Run() Console.WriteLine(s_type == typeof(Never)); #if !DEBUG - ThrowIfPresentWithUsableMethodTable(typeof(TestTypeEquals), nameof(Never)); + ThrowIfPresent(typeof(TestTypeEquals), nameof(Never)); #endif } } @@ -371,7 +371,7 @@ public static void Run() // We only expect to be able to get rid of it when optimizing #if !DEBUG - ThrowIfPresentWithUsableMethodTable(typeof(TestBranchesInGenericCodeRemoval), nameof(Unused)); + ThrowIfPresent(typeof(TestBranchesInGenericCodeRemoval), nameof(Unused)); #endif ThrowIfNotPresent(typeof(TestBranchesInGenericCodeRemoval), nameof(Used));