diff --git a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs index 0e95901f271aca..64edd62deae985 100644 --- a/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs +++ b/src/tools/illink/src/linker/Linker.Steps/MarkStep.cs @@ -2733,22 +2733,16 @@ void MarkGenericArguments (IGenericInstance instance, MessageOrigin origin) { var arguments = instance.GenericArguments; - var generic_element = GetGenericProviderFromInstance (instance); - if (generic_element == null) - return; - - var parameters = generic_element.GenericParameters; - - if (arguments.Count != parameters.Count) - return; + IGenericParameterProvider? generic_element = GetGenericProviderFromInstance (instance); + Collection? parameters = generic_element?.GenericParameters; for (int i = 0; i < arguments.Count; i++) { var argument = arguments[i]; - var parameter = parameters[i]; + var parameter = parameters?[i]; var argumentTypeDef = MarkType (argument, new DependencyInfo (DependencyKind.GenericArgumentType, instance), origin); - if (Annotations.FlowAnnotations.RequiresGenericArgumentDataFlowAnalysis (parameter)) { + if (parameter is not null && Annotations.FlowAnnotations.RequiresGenericArgumentDataFlowAnalysis (parameter)) { // The only two implementations of IGenericInstance both derive from MemberReference Debug.Assert (instance is MemberReference); @@ -2762,7 +2756,7 @@ void MarkGenericArguments (IGenericInstance instance, MessageOrigin origin) _dependencyGraph.AddRoot (_nodeFactory.GetTypeIsRelevantToVariantCastingNode (argumentTypeDef), "Generic Argument"); - if (parameter.HasDefaultConstructorConstraint) + if (parameter?.HasDefaultConstructorConstraint == true) MarkDefaultConstructor (argumentTypeDef, new DependencyInfo (DependencyKind.DefaultCtorForNewConstrainedGenericArgument, instance), origin); } } diff --git a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/GenericsTests.g.cs b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/GenericsTests.g.cs index b61127a3e55423..7042a4ff54f540 100644 --- a/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/GenericsTests.g.cs +++ b/src/tools/illink/test/ILLink.RoslynAnalyzer.Tests/generated/ILLink.RoslynAnalyzer.Tests.Generator/ILLink.RoslynAnalyzer.Tests.TestCaseGenerator/GenericsTests.g.cs @@ -75,6 +75,12 @@ public Task OverrideWithAnotherVirtualMethodOfSameNameWithDifferentParameterType return RunTest (allowMissingWarnings: true); } + [Fact] + public Task UnresolvedGenerics () + { + return RunTest (allowMissingWarnings: true); + } + [Fact] public Task UsedOverloadedGenericMethodInGenericClassIsNotStripped () { diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Generics/Dependencies/UnresolvedGenericsLibrary.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Generics/Dependencies/UnresolvedGenericsLibrary.cs new file mode 100644 index 00000000000000..bd463eee0b47cc --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Generics/Dependencies/UnresolvedGenericsLibrary.cs @@ -0,0 +1,15 @@ +// Copyright (c) .NET Foundation and contributors. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics.CodeAnalysis; + +namespace Mono.Linker.Tests.Cases.Generics.Dependencies +{ + public class UnresolvedGenericsLibrary + { + public class GenericClass { } + + public static void GenericMethod () { } + } +} diff --git a/src/tools/illink/test/Mono.Linker.Tests.Cases/Generics/UnresolvedGenerics.cs b/src/tools/illink/test/Mono.Linker.Tests.Cases/Generics/UnresolvedGenerics.cs new file mode 100644 index 00000000000000..c8c688f2db3acf --- /dev/null +++ b/src/tools/illink/test/Mono.Linker.Tests.Cases/Generics/UnresolvedGenerics.cs @@ -0,0 +1,56 @@ +using System; +using System.Reflection; +using System.Runtime.CompilerServices; + +using Mono.Linker.Tests.Cases.Expectations.Assertions; +using Mono.Linker.Tests.Cases.Expectations.Metadata; +using Mono.Linker.Tests.Cases.Generics.Dependencies; + +namespace Mono.Linker.Tests.Cases.Generics +{ + [IgnoreTestCase ("Ignore in NativeAOT, see https://github.com/dotnet/runtime/issues/103843", IgnoredBy = Tool.NativeAot)] + [KeptAttributeAttribute (typeof (IgnoreTestCaseAttribute), By = Tool.Trimmer)] + [SetupCompileBefore ("UnresolvedGenericsLibrary.dll", new[] { "Dependencies/UnresolvedGenericsLibrary.cs" }, + removeFromLinkerInput: true)] + class UnresolvedGenerics + { + static void Main () + { + UnresolvedGenericType (); + UnresolvedGenericBaseType (); + UnresolvedGenericMethod (); + } + + [Kept] + class GenericTypeArgument { } + + [Kept] + static void UnresolvedGenericType () + { + new UnresolvedGenericsLibrary.GenericClass (); + } + + [Kept] + class BaseTypeGenericArgument { } + + [Kept] + [KeptMember (".ctor()")] + [KeptBaseType (typeof (UnresolvedGenericsLibrary.GenericClass))] + class HasBaseType : UnresolvedGenericsLibrary.GenericClass { } + + [Kept] + static void UnresolvedGenericBaseType () + { + new HasBaseType (); + } + + [Kept] + class GenericMethodArgument { } + + [Kept] + static void UnresolvedGenericMethod () + { + UnresolvedGenericsLibrary.GenericMethod (); + } + } +}