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 70935253717d..b95b3c9d4683 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs @@ -232,6 +232,8 @@ public sealed override IEnumerable GetConditionalSt if (maximallyConstructableType != this) { // EEType upgrading from necessary to constructed if some template instantation exists that matches up + // This ensures we don't end up having two EETypes in the system (one is this necessary type, and another one + // that was dynamically created at runtime). if (CanonFormTypeMayExist) { result.Add(new CombinedDependencyListEntry(maximallyConstructableType, factory.MaximallyConstructableType(_type.ConvertToCanonForm(CanonicalFormKind.Specific)), "Trigger full type generation if canonical form exists")); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs index 8986aeb7e0f3..43a6e027ba00 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/GenericTypesHashtableNode.cs @@ -46,7 +46,14 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false) Section nativeSection = nativeWriter.NewSection(); nativeSection.Place(hashtable); - foreach (var type in factory.MetadataManager.GetTypesWithEETypes()) + // We go over constructed EETypes only. The places that need to consult this hashtable at runtime + // all need constructed EETypes. Placing unconstructed EETypes into this hashtable could make us + // accidentally satisfy e.g. MakeGenericType for something that was only used in a cast. Those + // should throw MissingRuntimeArtifact instead. + // + // We already make sure "necessary" EETypes that could potentially be loaded at runtime through + // the dynamic type loader get upgraded to constructed EETypes at AOT compile time. + foreach (var type in factory.MetadataManager.GetTypesWithConstructedEETypes()) { // If this is an instantiated non-canonical generic type, add it to the generic instantiations hashtable if (!type.HasInstantiation || type.IsGenericDefinition || type.IsCanonicalSubtype(CanonicalFormKind.Any))