From d42f3547f21498924f4977b661872491c3e4d750 Mon Sep 17 00:00:00 2001 From: Michael Staib Date: Mon, 23 Mar 2026 00:23:13 +0000 Subject: [PATCH] Fix generic record struct input inference --- .../src/Types/Internal/TypeDiscoveryInfo.cs | 6 --- .../Configuration/TypeDiscovererTests.cs | 38 +++++++++++++++++++ .../Configuration/TypeDiscoveryTests.cs | 21 ++++++++++ ...ryTests.InferGenericRecordStructInput.snap | 12 ++++++ 4 files changed, 71 insertions(+), 6 deletions(-) create mode 100644 src/HotChocolate/Core/test/Types.Tests/Configuration/__snapshots__/TypeDiscoveryTests.InferGenericRecordStructInput.snap diff --git a/src/HotChocolate/Core/src/Types/Internal/TypeDiscoveryInfo.cs b/src/HotChocolate/Core/src/Types/Internal/TypeDiscoveryInfo.cs index b227c2bc429..eef8d783cf2 100644 --- a/src/HotChocolate/Core/src/Types/Internal/TypeDiscoveryInfo.cs +++ b/src/HotChocolate/Core/src/Types/Internal/TypeDiscoveryInfo.cs @@ -151,12 +151,6 @@ private static bool IsComplexTypeInternal( IsByRefLike: false }; - if (isComplexValueType && unresolvedType.IsGeneric) - { - var typeDefinition = unresolvedType.Definition; - return typeDefinition == typeof(KeyValuePair<,>); - } - return isComplexClass || isComplexValueType; } diff --git a/src/HotChocolate/Core/test/Types.Tests/Configuration/TypeDiscovererTests.cs b/src/HotChocolate/Core/test/Types.Tests/Configuration/TypeDiscovererTests.cs index 989582eac74..2cf41120ba5 100644 --- a/src/HotChocolate/Core/test/Types.Tests/Configuration/TypeDiscovererTests.cs +++ b/src/HotChocolate/Core/test/Types.Tests/Configuration/TypeDiscovererTests.cs @@ -1,5 +1,6 @@ #nullable disable +using System.Numerics; using HotChocolate.Types; using HotChocolate.Types.Descriptors; using HotChocolate.Utilities; @@ -253,6 +254,33 @@ public void Cannot_Infer_Multiple_Input_Type() }); } + [Fact] + public void Can_Infer_Generic_Record_Struct_Input_Type() + { + // arrange + var context = DescriptorContext.Create(); + var typeRegistry = new TypeRegistry(context.TypeInterceptor); + var typeLookup = new TypeLookup(context.TypeInspector, typeRegistry); + + var typeDiscoverer = new TypeDiscoverer( + context, + typeRegistry, + typeLookup, + new HashSet + { + _typeInspector.GetTypeRef( + typeof(QueryWithGenericRecordStructInput), + TypeContext.Output) + }, + new AggregateTypeInterceptor()); + + // act + var errors = typeDiscoverer.DiscoverTypes(); + + // assert + Assert.Empty(errors); + } + public class FooType : ObjectType { @@ -284,5 +312,15 @@ public class QueryWithInferError2 public string Foo(IMyArg o) => throw new NotImplementedException(); } + public class QueryWithGenericRecordStructInput + { + public string Foo(RangeSpec range) => throw new NotImplementedException(); + } + + public readonly record struct RangeSpec( + T? Min, + T? Max) + where T : struct, IComparable, IComparisonOperators; + public interface IMyArg; } diff --git a/src/HotChocolate/Core/test/Types.Tests/Configuration/TypeDiscoveryTests.cs b/src/HotChocolate/Core/test/Types.Tests/Configuration/TypeDiscoveryTests.cs index 50dbcdf269c..87fa2477031 100644 --- a/src/HotChocolate/Core/test/Types.Tests/Configuration/TypeDiscoveryTests.cs +++ b/src/HotChocolate/Core/test/Types.Tests/Configuration/TypeDiscoveryTests.cs @@ -1,3 +1,4 @@ +using System.Numerics; using HotChocolate.Types; namespace HotChocolate.Configuration; @@ -54,6 +55,16 @@ public void InferInputTypeWithComputedProperty() .MatchSnapshot(); } + [Fact] + public void InferGenericRecordStructInput() + { + SchemaBuilder.New() + .AddQueryType() + .Create() + .ToString() + .MatchSnapshot(); + } + [Fact] public void Custom_LocalDate_Should_Throw_SchemaException_When_Not_Bound() { @@ -167,6 +178,16 @@ public class QueryTypeWithComputedProperty public int Foo(InputTypeWithReadOnlyProperties arg) => arg.Property1; } + public class QueryTypeWithGenericRecordStructInput + { + public string Foo(RangeSpec range) => "bar"; + } + + public readonly record struct RangeSpec( + T? Min, + T? Max) + where T : struct, IComparable, IComparisonOperators; + public class QueryTypeWithCustomLocalDate { public LocalDate Foo() => new(); diff --git a/src/HotChocolate/Core/test/Types.Tests/Configuration/__snapshots__/TypeDiscoveryTests.InferGenericRecordStructInput.snap b/src/HotChocolate/Core/test/Types.Tests/Configuration/__snapshots__/TypeDiscoveryTests.InferGenericRecordStructInput.snap new file mode 100644 index 00000000000..f6197af715d --- /dev/null +++ b/src/HotChocolate/Core/test/Types.Tests/Configuration/__snapshots__/TypeDiscoveryTests.InferGenericRecordStructInput.snap @@ -0,0 +1,12 @@ +schema { + query: QueryTypeWithGenericRecordStructInput +} + +type QueryTypeWithGenericRecordStructInput { + foo(range: RangeSpecOfInt32Input!): String! +} + +input RangeSpecOfInt32Input { + min: Int + max: Int +}