Deprecate typesafe variadic class arguments (#20673)

This commit is contained in:
Dennis 2025-02-16 21:35:11 +01:00 committed by GitHub
parent 0131a00173
commit 961862c455
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 53 additions and 50 deletions

View file

@ -0,0 +1,40 @@
Typesafe variadic class parameters have been deprecated
This obscure feature allowed a limited form of implicit construction:
---
void check(bool x, Exception e...)
{
if (!x)
throw e;
}
void main(string[] args)
{
check(args.length > 1, "missing argument");
}
---
However, few uses of this feature have been found, and one project was actually mistakenly using it instead of the more common Typesafe variadic array parameter.
Considering D doesn't support implicit construction and already has a confusing amount of different variadic parameter forms, it was decided to remove this feature.
As a corrective action, either call the constructor in the callee:
---
void check(string msg)
{
if (!x)
throw new Exception(msg);
}
---
Or let the caller construct the class instance:
---
void check(bool x, Exception e);
void main(string[] args)
{
check(args.length > 1, new Exception("missing argument"));
}
---

View file

@ -2493,10 +2493,17 @@ Type typeSemantic(Type type, Loc loc, Scope* sc)
errors = true;
}
const bool isTypesafeVariadic = i + 1 == dim &&
tf.parameterList.varargs == VarArg.typesafe &&
(t.isTypeDArray() || t.isTypeClass());
if (isTypesafeVariadic)
const bool isTypesafeVariadic = i + 1 == dim && tf.parameterList.varargs == VarArg.typesafe;
const bool isStackAllocatedVariadic = isTypesafeVariadic && (t.isTypeDArray() || t.isTypeClass());
if (isTypesafeVariadic && t.isTypeClass())
{
// Deprecated in 2.111, kept as a legacy feature for compatibility (currently no plan to turn it into an error)
.deprecation(loc, "typesafe variadic parameters with a `class` type (`%s %s...`) are deprecated",
t.isTypeClass().sym.ident.toChars(), fparam.toChars());
}
if (isStackAllocatedVariadic)
{
/* typesafe variadic arguments are constructed on the stack, so must be `scope`
*/
@ -2518,7 +2525,7 @@ Type typeSemantic(Type type, Loc loc, Scope* sc)
}
}
if (isTypesafeVariadic)
if (isStackAllocatedVariadic)
{
/* This is because they can be constructed on the stack
* https://dlang.org/spec/function.html#typesafe_variadic_functions

View file

@ -1,7 +1,6 @@
/* TEST_OUTPUT:
---
fail_compilation/test22023.d(102): Error: typesafe variadic function parameter `a` of type `int[]` cannot be marked `return`
fail_compilation/test22023.d(107): Error: typesafe variadic function parameter `c` of type `test22023.C` cannot be marked `return`
---
*/
@ -14,13 +13,3 @@ ref int f(return int[] a ...)
{
return a[2];
}
ref int g(return C c ...)
{
return c.x;
}
class C
{
int x;
}

View file

@ -1,6 +1,7 @@
/* REQUIRED_ARGS: -preview=dip1000
* TEST_OUTPUT:
---
fail_compilation/test22818.d(102): Deprecation: typesafe variadic parameters with a `class` type (`C c...`) are deprecated
fail_compilation/test22818.d(104): Error: scope parameter `c` may not be returned
---
*/

View file

@ -83,39 +83,6 @@ void test3()
printf("%d\n", i);
}
/*********************************************************/
class Foo4
{
int a;
float f;
double d;
this(int a, float f, double d)
{
this.a = a;
this.f = f;
this.d = d;
}
}
int sum4(Foo4 f ...)
{
return cast(int)(f.a + f.f + f.d);
}
void test4()
{
int i;
Foo4 foo = new Foo4(1, 2f, 3.0);
i = sum4(foo);
assert(i == 1+2+3);
i = sum4(4, 5f, 6.0);
assert(i == 4+5+6);
printf("%d\n", i);
}
/*********************************************************/
@ -139,7 +106,6 @@ int main()
test1();
test2();
test3();
test4();
test5();
printf("Success\n");