From 2fbd4be5ac3a34e95f967d8563afbd36a2495254 Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Thu, 12 Feb 2026 21:15:46 +1000 Subject: [PATCH 1/2] Fix up default value for in parameters Fix up calling a method with an `in` parameter modifier and the `default` value. Currently this only works for primitive types and `default` whereas other types need special handling to be called. --- .../engine/runtime/Binding/Binders.cs | 6 ++++++ .../engine/Basic/CLRBinding.Tests.ps1 | 21 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/System.Management.Automation/engine/runtime/Binding/Binders.cs b/src/System.Management.Automation/engine/runtime/Binding/Binders.cs index 5913c98829b..18980eabf52 100644 --- a/src/System.Management.Automation/engine/runtime/Binding/Binders.cs +++ b/src/System.Management.Automation/engine/runtime/Binding/Binders.cs @@ -7201,6 +7201,12 @@ internal static Expression InvokeMethod(MethodBase mi, DynamicMetaObject target, var argValue = parameters[i].DefaultValue; if (argValue == null) { + if (parameterType.IsByRef) + { + // parameters with the in modifier are ByRef, if they don't have a default value + // we need to get the Default on the element type. + parameterType = parameterType.GetElementType(); + } argExprs[i] = Expression.Default(parameterType); } else if (!parameters[i].HasDefaultValue && parameterType != typeof(object) && argValue == Type.Missing) diff --git a/test/powershell/engine/Basic/CLRBinding.Tests.ps1 b/test/powershell/engine/Basic/CLRBinding.Tests.ps1 index 98a05d8518e..cb23fa168db 100644 --- a/test/powershell/engine/Basic/CLRBinding.Tests.ps1 +++ b/test/powershell/engine/Basic/CLRBinding.Tests.ps1 @@ -27,6 +27,12 @@ public class TestClass public static string StaticWithOptionalExpected() => StaticWithOptional(); public static string StaticWithOptional([Optional] string value) => value; + public static int PrimitiveTypeWithInDefault(in int value = default) => value; + + public static Guid ValueTypeWithInDefault(in Guid value = default) => value; + + public static string RefTypeWithInDefault(in string value = default) => value; + public object InstanceWithDefaultExpected() => InstanceWithDefault(); public object InstanceWithDefault(object value = null) => value; @@ -101,6 +107,21 @@ public class TestClassCstorWithOptional $actual | Should -Be $expected } + It "Binds to static method with primitive type with in modifier and default argument" { + $actual = [CLRBindingTests.TestClass]::PrimitiveTypeWithInDefault() + $actual | Should -Be 0 + } + + It "Binds to static method with value type with in modifier and default argument" { + $actual = [CLRBindingTests.TestClass]::ValueTypeWithInDefault() + $actual | Should -Be ([Guid]::Empty) + } + + It "Binds to static method with ref type with in modifier and default argument" { + $actual = [CLRBindingTests.TestClass]::RefTypeWithInDefault() + $null -eq $actual | Should -BeTrue + } + It "Binds to instance method with default argument" { $c = [CLRBindingTests.TestClass]::new() From 1f53d856f8368a8ba169c77a98d5fc494027f3c7 Mon Sep 17 00:00:00 2001 From: Jordan Borean Date: Thu, 12 Feb 2026 21:36:12 +1000 Subject: [PATCH 2/2] Update src/System.Management.Automation/engine/runtime/Binding/Binders.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../engine/runtime/Binding/Binders.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/System.Management.Automation/engine/runtime/Binding/Binders.cs b/src/System.Management.Automation/engine/runtime/Binding/Binders.cs index 18980eabf52..027c4886380 100644 --- a/src/System.Management.Automation/engine/runtime/Binding/Binders.cs +++ b/src/System.Management.Automation/engine/runtime/Binding/Binders.cs @@ -7203,8 +7203,9 @@ internal static Expression InvokeMethod(MethodBase mi, DynamicMetaObject target, { if (parameterType.IsByRef) { - // parameters with the in modifier are ByRef, if they don't have a default value - // we need to get the Default on the element type. + // When the default value is null for a ByRef parameter (e.g. an optional `in` parameter + // using `default`), expression trees cannot create Expression.Default for the T& type. + // In that case we switch to the element type and use Default(TElement) instead. parameterType = parameterType.GetElementType(); } argExprs[i] = Expression.Default(parameterType);