From e60db076d7966c18b678378b188e6ce6896403d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Strehovsk=C3=BD?= Date: Fri, 2 Aug 2024 09:48:54 +0200 Subject: [PATCH] Emit instantiated types as external references if possible (#105816) Fixes #105397. The repro case hits an interesting problem in native layout - we emit the `IEnumerable>` type as a constructed type, however the components of it are only generated as necessary. Because native layout expresses it as a decomposed instantiation, we're not able to find the type because the component of it is not constructed and we don't really keep track of those. This can be fixed by simply not generating types as composed out of various components. --- .../Compiler/DependencyAnalysis/EETypeNode.cs | 1 + .../NativeLayoutVertexNode.cs | 2 +- .../SmokeTests/UnitTests/Generics.cs | 26 +++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) 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 4abea8187b583..3d07c1c0068e8 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/EETypeNode.cs @@ -91,6 +91,7 @@ public EETypeNode(NodeFactory factory, TypeDesc type) else if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) Debug.Assert((this is CanonicalEETypeNode) || (this is NecessaryCanonicalEETypeNode)); + Debug.Assert(!type.IsGenericParameter); Debug.Assert(!type.IsRuntimeDeterminedSubtype); _type = type; _optionalFieldsNode = new EETypeOptionalFieldsNode(this); diff --git a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs index 16ef36907af6a..eca454ffeb712 100644 --- a/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs +++ b/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/NativeLayoutVertexNode.cs @@ -232,7 +232,7 @@ internal sealed class NativeLayoutMethodLdTokenVertexNode : NativeLayoutMethodEn protected override string GetName(NodeFactory factory) => "NativeLayoutMethodLdTokenVertexNode_" + factory.NameMangler.GetMangledMethodName(_method); public NativeLayoutMethodLdTokenVertexNode(NodeFactory factory, MethodDesc method) - : base(factory, method, 0) + : base(factory, method, method.IsRuntimeDeterminedExactMethod || method.IsGenericMethodDefinition ? 0 : MethodEntryFlags.CreateInstantiatedSignature) { } diff --git a/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs b/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs index e39a42c9ba29d..63959b548613c 100644 --- a/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs +++ b/src/tests/nativeaot/SmokeTests/UnitTests/Generics.cs @@ -58,6 +58,7 @@ internal static int Run() Test99198Regression.Run(); Test102259Regression.Run(); Test104913Regression.Run(); + Test105397Regression.Run(); TestInvokeMemberCornerCaseInGenerics.Run(); TestRefAny.Run(); TestNullableCasting.Run(); @@ -3629,6 +3630,31 @@ public static void Run() } } + class Test105397Regression + { + interface IEnumerable { } + + interface ITest + { + TReturn UsingDatabaseResult(TState state, Func @using); + } + class Test : ITest + { + public TReturn UsingDatabaseResult(TState state, Func @using) + { + return default; + } + } + + struct GenStruct { } + + public static void Run() + { + ITest t = new Test(); + t.UsingDatabaseResult>>, int>(null, (x, y) => 1); + } + } + class TestInvokeMemberCornerCaseInGenerics { class Generic