diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h
index b3d2d580cdf652..c1c492d1501106 100644
--- a/src/coreclr/inc/clrconfigvalues.h
+++ b/src/coreclr/inc/clrconfigvalues.h
@@ -710,7 +710,7 @@ RETAIL_CONFIG_DWORD_INFO(EXTERNAL_EnableRiscV64Zbb, W("EnableRiscV64
#endif
// Runtime-async
-RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RuntimeAsync, W("RuntimeAsync"), 0, "Enables runtime async method support")
+RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_RuntimeAsync, W("RuntimeAsync"), 1, "Enables runtime async method support")
///
/// Uncategorized
diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp
index 2b8643e922cb49..50a5d17043642c 100644
--- a/src/coreclr/vm/methodtablebuilder.cpp
+++ b/src/coreclr/vm/methodtablebuilder.cpp
@@ -3301,6 +3301,23 @@ MethodTableBuilder::EnumerateClassMethods()
}
}
+ // Vararg methods are not allowed to be marked MethodImpl.Async
+ // and even when they return Tasks they are still treated as NormalMethod.
+ if (returnKind != MethodReturnKind::NormalMethod)
+ {
+ if (MetaSig::IsVarArg(Signature(pMemberSignature, cMemberSignature)))
+ {
+ if (IsMiAsync(dwImplFlags))
+ {
+ BuildMethodTableThrowException(IDS_EE_VARARG_NOT_SUPPORTED);
+ }
+ else
+ {
+ returnKind = MethodReturnKind::NormalMethod;
+ }
+ }
+ }
+
//
// Create a new bmtMDMethod representing this method and add it to the
// declared method list.
diff --git a/src/tests/async/Directory.Build.targets b/src/tests/async/Directory.Build.targets
index 6804180057690e..f2d39cb6d975ff 100644
--- a/src/tests/async/Directory.Build.targets
+++ b/src/tests/async/Directory.Build.targets
@@ -9,10 +9,5 @@
true
-
-
- true
-
-
diff --git a/src/tests/async/varargs/varargs.cs b/src/tests/async/varargs/varargs.cs
new file mode 100644
index 00000000000000..4301dc92709099
--- /dev/null
+++ b/src/tests/async/varargs/varargs.cs
@@ -0,0 +1,80 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Threading.Tasks;
+using Xunit;
+
+public class Async2Varargs
+{
+ [Fact]
+ public static void TestTaskDirectCall()
+ {
+ TaskWithArglist(42, __arglist(100, 200)).Wait();
+ }
+
+ [Fact]
+ public static void TestTaskAwait()
+ {
+ TestTaskAwaitAsync().Wait();
+ }
+
+ private static async Task TestTaskAwaitAsync()
+ {
+ await TaskWithArglist(42, __arglist(100, 200));
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static Task TaskWithArglist(int fixedArg, __arglist)
+ {
+ Assert.Equal(42, fixedArg);
+
+ ArgIterator args = new ArgIterator(__arglist);
+ Assert.Equal(2, args.GetRemainingCount());
+
+ int arg1 = __refvalue(args.GetNextArg(), int);
+ int arg2 = __refvalue(args.GetNextArg(), int);
+
+ Assert.Equal(100, arg1);
+ Assert.Equal(200, arg2);
+
+ return Task.CompletedTask;
+ }
+
+ [Fact]
+ public static void TestValueTaskDirectCall()
+ {
+ int result = ValueTaskWithArglist(42, __arglist(100, 200)).Result;
+ Assert.Equal(342, result);
+ }
+
+ [Fact]
+ public static void TestValueTaskAwait()
+ {
+ TestValueTaskAwaitAsync().Wait();
+ }
+
+ private static async Task TestValueTaskAwaitAsync()
+ {
+ int result = await ValueTaskWithArglist(42, __arglist(100, 200));
+ Assert.Equal(342, result);
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private static ValueTask ValueTaskWithArglist(int fixedArg, __arglist)
+ {
+ Assert.Equal(42, fixedArg);
+
+ ArgIterator args = new ArgIterator(__arglist);
+ Assert.Equal(2, args.GetRemainingCount());
+
+ int arg1 = __refvalue(args.GetNextArg(), int);
+ int arg2 = __refvalue(args.GetNextArg(), int);
+
+ Assert.Equal(100, arg1);
+ Assert.Equal(200, arg2);
+
+ return new ValueTask(fixedArg + arg1 + arg2);
+ }
+}
diff --git a/src/tests/async/varargs/varargs.csproj b/src/tests/async/varargs/varargs.csproj
new file mode 100644
index 00000000000000..197767e2c4e249
--- /dev/null
+++ b/src/tests/async/varargs/varargs.csproj
@@ -0,0 +1,5 @@
+
+
+
+
+