Deprecate traits(isVirtualFunction) and traits(getVirtualFunctions) (#14802)

This commit is contained in:
Razvan Nitu 2023-01-20 16:11:37 +08:00 committed by GitHub
parent 35abfc4a9f
commit 636e61ea4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 70 additions and 72 deletions

View file

@ -0,0 +1,11 @@
Deprecate `traits(isVirtualFunction)` and `traits(getVirtualFunctions)`
Up until this release, D had both `traits(isVirtualFunction)` and `traits(isVirtualMethod)`
(and their coressponding `traits(get...)` counterpart). The differenrcte between the two is
that `isVirtualFunction` returns true for `final` methods that do not override anything. This
is in contradiction with the D spec which states that `final` functions that do not override
other functions cannot be virtual. `isVirtualMethod` correctly returns `false` in that case.
Starting with this release, both `traits(isVirtualFunction)` and `traits(getVirtualFunctions)`
are deprecated. If the behavior of `traits(isVirtualFunction)` is desired, it can be achieved by
`traits(isVirtualMethod, f) || (traits(isFinalFunction, f) && !traits(isOverrideFunction, f))`.

View file

@ -634,6 +634,10 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
} }
if (e.ident == Id.isVirtualFunction) if (e.ident == Id.isVirtualFunction)
{ {
// @@@DEPRECATED2.121@@@
// Deprecated in 2.101 - Can be removed from 2.121
e.deprecation("`traits(isVirtualFunction)` is deprecated. Use `traits(isVirtualMethod)` instead");
if (dim != 1) if (dim != 1)
return dimError(1); return dimError(1);
@ -995,6 +999,13 @@ Expression semanticTraits(TraitsExp e, Scope* sc)
if (errors < global.errors) if (errors < global.errors)
e.error("`%s` cannot be resolved", eorig.toChars()); e.error("`%s` cannot be resolved", eorig.toChars());
if (e.ident == Id.getVirtualFunctions)
{
// @@@DEPRECATED2.121@@@
// Deprecated in 2.101 - Can be removed from 2.121
e.deprecation("`traits(getVirtualFunctions)` is deprecated. Use `traits(getVirtualMethods)` instead");
}
/* Create tuple of functions of ex /* Create tuple of functions of ex
*/ */
auto exps = new Expressions(); auto exps = new Expressions();

View file

@ -14,11 +14,6 @@ class Foo
{ {
auto dg = &f; auto dg = &f;
} }
foreach (f; __traits(getVirtualFunctions, typeof(this), "bar"))
{
auto dg = &f;
}
} }
uint bar() { return 0; } uint bar() { return 0; }

View file

@ -0,0 +1,20 @@
// REQUIRED_ARGS: -de
/*
TEST_OUTPUT:
---
fail_compilation/deprecate_getVirtualFunctions.d(18): Deprecation: `traits(isVirtualFunction)` is deprecated. Use `traits(isVirtualMethod)` instead
fail_compilation/deprecate_getVirtualFunctions.d(19): Deprecation: `traits(getVirtualFunctions)` is deprecated. Use `traits(getVirtualMethods)` instead
---
*/
class A
{
void fun() {}
}
void main()
{
auto a = __traits(isVirtualFunction, A.fun);
foreach(f; __traits(getVirtualFunctions, A, "fun")) {}
}

View file

@ -8,4 +8,4 @@ fail_compilation/fail19076.d(11): Error: `(I).V` cannot be resolved
interface P { } interface P { }
interface I : P { } interface I : P { }
auto F = __traits(getVirtualFunctions, I, "V"); auto F = __traits(getVirtualMethods, I, "V");

View file

@ -1,28 +1,29 @@
/* TEST_OUTPUT: /* TEST_OUTPUT:
--- ---
fail_compilation/test17096.d(28): Error: expected 1 arguments for `isPOD` but had 2 fail_compilation/test17096.d(29): Error: expected 1 arguments for `isPOD` but had 2
fail_compilation/test17096.d(29): Error: expected 1 arguments for `isNested` but had 2 fail_compilation/test17096.d(30): Error: expected 1 arguments for `isNested` but had 2
fail_compilation/test17096.d(30): Error: expected 1 arguments for `isVirtualFunction` but had 2 fail_compilation/test17096.d(31): Deprecation: `traits(isVirtualFunction)` is deprecated. Use `traits(isVirtualMethod)` instead
fail_compilation/test17096.d(31): Error: expected 1 arguments for `isVirtualMethod` but had 2 fail_compilation/test17096.d(31): Error: expected 1 arguments for `isVirtualFunction` but had 2
fail_compilation/test17096.d(32): Error: expected 1 arguments for `isAbstractFunction` but had 2 fail_compilation/test17096.d(32): Error: expected 1 arguments for `isVirtualMethod` but had 2
fail_compilation/test17096.d(33): Error: expected 1 arguments for `isFinalFunction` but had 2 fail_compilation/test17096.d(33): Error: expected 1 arguments for `isAbstractFunction` but had 2
fail_compilation/test17096.d(34): Error: expected 1 arguments for `isOverrideFunction` but had 2 fail_compilation/test17096.d(34): Error: expected 1 arguments for `isFinalFunction` but had 2
fail_compilation/test17096.d(35): Error: expected 1 arguments for `isStaticFunction` but had 2 fail_compilation/test17096.d(35): Error: expected 1 arguments for `isOverrideFunction` but had 2
fail_compilation/test17096.d(36): Error: expected 1 arguments for `isRef` but had 2 fail_compilation/test17096.d(36): Error: expected 1 arguments for `isStaticFunction` but had 2
fail_compilation/test17096.d(37): Error: expected 1 arguments for `isOut` but had 2 fail_compilation/test17096.d(37): Error: expected 1 arguments for `isRef` but had 2
fail_compilation/test17096.d(38): Error: expected 1 arguments for `isLazy` but had 2 fail_compilation/test17096.d(38): Error: expected 1 arguments for `isOut` but had 2
fail_compilation/test17096.d(39): Error: expected 1 arguments for `identifier` but had 2 fail_compilation/test17096.d(39): Error: expected 1 arguments for `isLazy` but had 2
fail_compilation/test17096.d(40): Error: expected 1 arguments for `getProtection` but had 2 fail_compilation/test17096.d(40): Error: expected 1 arguments for `identifier` but had 2
fail_compilation/test17096.d(41): Error: expected 1 arguments for `parent` but had 2 fail_compilation/test17096.d(41): Error: expected 1 arguments for `getProtection` but had 2
fail_compilation/test17096.d(42): Error: expected 1 arguments for `classInstanceSize` but had 2 fail_compilation/test17096.d(42): Error: expected 1 arguments for `parent` but had 2
fail_compilation/test17096.d(43): Error: expected 1 arguments for `allMembers` but had 2 fail_compilation/test17096.d(43): Error: expected 1 arguments for `classInstanceSize` but had 2
fail_compilation/test17096.d(44): Error: expected 1 arguments for `derivedMembers` but had 2 fail_compilation/test17096.d(44): Error: expected 1 arguments for `allMembers` but had 2
fail_compilation/test17096.d(45): Error: expected 1 arguments for `getAliasThis` but had 2 fail_compilation/test17096.d(45): Error: expected 1 arguments for `derivedMembers` but had 2
fail_compilation/test17096.d(46): Error: expected 1 arguments for `getAttributes` but had 2 fail_compilation/test17096.d(46): Error: expected 1 arguments for `getAliasThis` but had 2
fail_compilation/test17096.d(47): Error: expected 1 arguments for `getFunctionAttributes` but had 2 fail_compilation/test17096.d(47): Error: expected 1 arguments for `getAttributes` but had 2
fail_compilation/test17096.d(48): Error: expected 1 arguments for `getUnitTests` but had 2 fail_compilation/test17096.d(48): Error: expected 1 arguments for `getFunctionAttributes` but had 2
fail_compilation/test17096.d(49): Error: expected 1 arguments for `getVirtualIndex` but had 2 fail_compilation/test17096.d(49): Error: expected 1 arguments for `getUnitTests` but had 2
fail_compilation/test17096.d(50): Error: a single type expected for trait pointerBitmap fail_compilation/test17096.d(50): Error: expected 1 arguments for `getVirtualIndex` but had 2
fail_compilation/test17096.d(51): Error: a single type expected for trait pointerBitmap
--- ---
*/ */
enum b03 = __traits(isPOD, 1, 2); enum b03 = __traits(isPOD, 1, 2);

View file

@ -63,8 +63,6 @@ TmpPrm!(__traits(getMember, Foo, "MyInt")) tpt = TmpPrm!(__traits(getMember, Foo
int virtual(int p){return p;} int virtual(int p){return p;}
void test(this T)() void test(this T)()
{ {
alias vf = __traits(getVirtualFunctions, Class, "virtual");
assert(vf.length == 2);
alias vm = __traits(getVirtualMethods, Class, "virtual"); alias vm = __traits(getVirtualMethods, Class, "virtual");
assert(vm.length == 1); assert(vm.length == 1);
assert(vm[0](42) == 42); assert(vm[0](42) == 42);

View file

@ -312,14 +312,6 @@ void test9()
/********************************************************/ /********************************************************/
void test10()
{
assert(__traits(isVirtualFunction, C.bar) == true);
assert(__traits(isVirtualFunction, S.bar) == false);
}
/********************************************************/
void test11() void test11()
{ {
assert(__traits(isAbstractFunction, C.bar) == false); assert(__traits(isAbstractFunction, C.bar) == false);
@ -403,24 +395,6 @@ class D15
int foo(int) { return 2; } int foo(int) { return 2; }
} }
void test15()
{
D15 d = new D15();
assert(__traits(getVirtualFunctions, D15, "foo").length == 2);
assert(typeid(typeof(__traits(getVirtualFunctions, D15, "foo")[0])).toString()
== "void function()");
assert(typeid(typeof(__traits(getVirtualFunctions, D15, "foo")[1])).toString()
== "int function(int)");
alias typeof(__traits(getVirtualFunctions, D15, "foo")) b;
assert(typeid(b[0]).toString() == "void function()");
assert(typeid(b[1]).toString() == "int function(int)");
auto i = __traits(getVirtualFunctions, d, "foo")[1](1);
assert(i == 2);
}
/********************************************************/ /********************************************************/
struct S16 { } struct S16 { }
@ -714,14 +688,6 @@ interface AA
int YYY(); int YYY();
} }
class CC : AA
{
final int YYY() { return 4; }
}
static assert(__traits(isVirtualMethod, CC.YYY));
static assert(__traits(getVirtualMethods, CC, "YYY").length == 1);
class DD class DD
{ {
final int YYY() { return 4; } final int YYY() { return 4; }
@ -790,8 +756,6 @@ void test7858()
static assert(__traits(isFinalFunction, C.ffunc) == static assert(__traits(isFinalFunction, C.ffunc) ==
__traits(isFinalFunction, __traits(getOverloads, C, "ffunc")[0])); // NG __traits(isFinalFunction, __traits(getOverloads, C, "ffunc")[0])); // NG
static assert(__traits(isVirtualFunction, C.vfunc) ==
__traits(isVirtualFunction, __traits(getOverloads, C, "vfunc")[0])); // NG
static assert(__traits(isVirtualMethod, C.vfunc) == static assert(__traits(isVirtualMethod, C.vfunc) ==
__traits(isVirtualMethod, __traits(getOverloads, C, "vfunc")[0])); // NG __traits(isVirtualMethod, __traits(getOverloads, C, "vfunc")[0])); // NG
static assert(__traits(isAbstractFunction, C.afunc) == static assert(__traits(isAbstractFunction, C.afunc) ==
@ -1456,13 +1420,11 @@ int main()
test7(); test7();
test8(); test8();
test9(); test9();
test10();
test11(); test11();
test12(); test12();
test13(); test13();
test7123(); test7123();
test14(); test14();
test15();
test16(); test16();
test17(); test17();
test18(); test18();

View file

@ -654,7 +654,7 @@ if (func.length == 1 /*&& isCallable!func*/)
int test(int); int test(int);
int test() @property; int test() @property;
} }
alias ov = __traits(getVirtualFunctions, Overloads, "test"); alias ov = __traits(getVirtualMethods, Overloads, "test");
alias F_ov0 = FunctionTypeOf!(ov[0]); alias F_ov0 = FunctionTypeOf!(ov[0]);
alias F_ov1 = FunctionTypeOf!(ov[1]); alias F_ov1 = FunctionTypeOf!(ov[1]);
alias F_ov2 = FunctionTypeOf!(ov[2]); alias F_ov2 = FunctionTypeOf!(ov[2]);

View file

@ -1417,7 +1417,7 @@ class TypeInfo_Function : TypeInfo
int func(int a, int b); int func(int a, int b);
} }
alias functionTypes = typeof(__traits(getVirtualFunctions, C, "func")); alias functionTypes = typeof(__traits(getVirtualMethods, C, "func"));
assert(typeid(functionTypes[0]).toString() == "void function()"); assert(typeid(functionTypes[0]).toString() == "void function()");
assert(typeid(functionTypes[1]).toString() == "void function(int)"); assert(typeid(functionTypes[1]).toString() == "void function(int)");
assert(typeid(functionTypes[2]).toString() == "int function(int, int)"); assert(typeid(functionTypes[2]).toString() == "int function(int, int)");
@ -1431,7 +1431,7 @@ class TypeInfo_Function : TypeInfo
void func(int a); void func(int a);
} }
alias functionTypes = typeof(__traits(getVirtualFunctions, C, "func")); alias functionTypes = typeof(__traits(getVirtualMethods, C, "func"));
Object obj = typeid(functionTypes[0]); Object obj = typeid(functionTypes[0]);
assert(obj.opEquals(typeid(functionTypes[0]))); assert(obj.opEquals(typeid(functionTypes[0])));