diff --git a/src/HotChocolate/Core/src/Types/Types/Descriptors/ArgumentDescriptorBase~1.cs b/src/HotChocolate/Core/src/Types/Types/Descriptors/ArgumentDescriptorBase~1.cs
index 7712256736a..ee4b8b40131 100644
--- a/src/HotChocolate/Core/src/Types/Types/Descriptors/ArgumentDescriptorBase~1.cs
+++ b/src/HotChocolate/Core/src/Types/Types/Descriptors/ArgumentDescriptorBase~1.cs
@@ -39,21 +39,15 @@ protected void Deprecated(string? reason)
///
protected void Deprecated()
- {
- Configuration.DeprecationReason = DirectiveNames.Deprecated.Arguments.DefaultReason;
- }
+ => Configuration.DeprecationReason = DirectiveNames.Deprecated.Arguments.DefaultReason;
- ///
- protected void Description(string value)
- {
- Configuration.Description = value;
- }
+ ///
+ protected void Description(string? value)
+ => Configuration.Description = value;
///
public void Type() where TInputType : IInputType
- {
- Type(typeof(TInputType));
- }
+ => Type(typeof(TInputType));
///
/// Sets the type of the argument
@@ -71,6 +65,8 @@ public void Type() where TInputType : IInputType
///
public void Type(Type type)
{
+ ArgumentNullException.ThrowIfNull(type);
+
var typeInfo = Context.TypeInspector.CreateTypeInfo(type);
if (typeInfo.IsSchemaType && !typeInfo.IsInputType())
@@ -133,7 +129,7 @@ public void Type(ITypeNode typeNode)
Configuration.SetMoreSpecificType(typeNode, TypeContext.Input);
}
- ///
+ ///
public void DefaultValue(IValueNode? value)
{
Configuration.DefaultValue = value ?? NullValueNode.Default;
@@ -150,6 +146,11 @@ public void DefaultValue(object? value)
}
else
{
+ if (TryCoerceEnumUnderlyingValue(value, out var enumValue))
+ {
+ value = enumValue;
+ }
+
var type = Context.TypeInspector.GetType(value.GetType());
Configuration.SetMoreSpecificType(type, TypeContext.Input);
Configuration.RuntimeDefaultValue = value;
@@ -168,4 +169,32 @@ public void Directive(TDirective directiveInstance) where TDirective
///
public void Directive(string name, params ArgumentNode[] arguments)
=> Configuration.AddDirective(name, arguments);
+
+ private bool TryCoerceEnumUnderlyingValue(object value, out object enumValue)
+ {
+ enumValue = default!;
+
+ if (Configuration.Type is not ExtendedTypeReference typeReference)
+ {
+ return false;
+ }
+
+ var clrType = Nullable.GetUnderlyingType(typeReference.Type.Source)
+ ?? typeReference.Type.Source;
+
+ if (!clrType.IsEnum)
+ {
+ return false;
+ }
+
+ var underlyingType = Enum.GetUnderlyingType(clrType);
+
+ if (value.GetType() != underlyingType)
+ {
+ return false;
+ }
+
+ enumValue = Enum.ToObject(clrType, value);
+ return true;
+ }
}
diff --git a/src/HotChocolate/Core/src/Types/Types/Descriptors/Contracts/IArgumentDescriptor.cs b/src/HotChocolate/Core/src/Types/Types/Descriptors/Contracts/IArgumentDescriptor.cs
index 9ecf394194e..e2a7a64a814 100644
--- a/src/HotChocolate/Core/src/Types/Types/Descriptors/Contracts/IArgumentDescriptor.cs
+++ b/src/HotChocolate/Core/src/Types/Types/Descriptors/Contracts/IArgumentDescriptor.cs
@@ -1,5 +1,3 @@
-#nullable disable
-
using HotChocolate.Language;
using HotChocolate.Types.Descriptors.Configurations;
@@ -26,7 +24,7 @@ public interface IArgumentDescriptor
///
///
///
- IArgumentDescriptor Deprecated(string reason);
+ IArgumentDescriptor Deprecated(string? reason);
///
/// Marks the argument as deprecated
@@ -65,7 +63,7 @@ public interface IArgumentDescriptor
///
///
/// The description
- IArgumentDescriptor Description(string value);
+ IArgumentDescriptor Description(string? value);
///
/// Sets the type of the argument
@@ -149,7 +147,7 @@ IArgumentDescriptor Type(TInputType inputType)
///
///
///
- IArgumentDescriptor DefaultValue(IValueNode value);
+ IArgumentDescriptor DefaultValue(IValueNode? value);
///
/// Sets the default value of this argument
@@ -166,7 +164,7 @@ IArgumentDescriptor Type(TInputType inputType)
///
///
///
- IArgumentDescriptor DefaultValue(object value);
+ IArgumentDescriptor DefaultValue(object? value);
///
/// Sets a directive on the argument
diff --git a/src/HotChocolate/Core/test/Types.Tests/Types/Issue7040ReproTests.cs b/src/HotChocolate/Core/test/Types.Tests/Types/Issue7040ReproTests.cs
new file mode 100644
index 00000000000..1fe6d11aab1
--- /dev/null
+++ b/src/HotChocolate/Core/test/Types.Tests/Types/Issue7040ReproTests.cs
@@ -0,0 +1,30 @@
+namespace HotChocolate.Types;
+
+public class Issue7040ReproTests
+{
+ [Fact]
+ public void Enum_DefaultValueAttribute_With_Integer_Default_Does_Not_Downgrade_To_Int()
+ {
+ SchemaBuilder.New()
+ .AddInputObjectType()
+ .ModifyOptions(o => o.StrictValidation = false)
+ .Create()
+ .MatchSnapshot();
+ }
+
+ public class InputWithEnumIntDefault
+ {
+ // The F# compiler boxes enum values as their underlying type when passed
+ // to attribute constructors that accept object. So []
+ // in F# arrives at runtime as [DefaultValue(0)] rather than [DefaultValue(MyEnum.Value1)].
+ // We use the integer literal here to reproduce that behavior in C#.
+ [DefaultValue(0)]
+ public Issue7040Enum Enum { get; set; }
+ }
+
+ public enum Issue7040Enum
+ {
+ Value1 = 0,
+ Value2 = 1
+ }
+}