mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
Deprecate alias this for classes v2 (#14812)
This commit is contained in:
parent
1d19f710b2
commit
af7817b4ae
20 changed files with 89 additions and 324 deletions
8
changelog/dmd.deprecate-alias-this-for-classes.dd
Normal file
8
changelog/dmd.deprecate-alias-this-for-classes.dd
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
Alias this for classes is deprecated
|
||||||
|
|
||||||
|
Using `alias this` for classes has not been clearly specified and the lookup rules in such circumstances are not defined. As a consequence, various failures or crashes may appear when `alias this` is used in conjunction with classes. Starting with this release, `alias this` for classes is being deprecated. As an alternative, getter/setter methods may be used to replace the `alias this`. This can be generically handled by:
|
||||||
|
|
||||||
|
```d
|
||||||
|
static foreach(member, __traits(allMembers, LeClass))
|
||||||
|
mixin("ref auto " ~ member() { return $field_name." ~ member ~ "; }");
|
||||||
|
```
|
|
@ -317,6 +317,11 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @@@DEPRECATED_2.121@@@
|
||||||
|
// Deprecated in 2.101 - Can be removed in 2.121
|
||||||
|
if (ad.isClassDeclaration() || ad.isInterfaceDeclaration())
|
||||||
|
deprecation(dsym.loc, "alias this for classes/interfaces is deprecated");
|
||||||
|
|
||||||
assert(ad.members);
|
assert(ad.members);
|
||||||
Dsymbol s = ad.search(dsym.loc, dsym.ident);
|
Dsymbol s = ad.search(dsym.loc, dsym.ident);
|
||||||
if (!s)
|
if (!s)
|
||||||
|
|
|
@ -291,7 +291,21 @@ public:
|
||||||
|
|
||||||
/// Informations about the current context in the AST
|
/// Informations about the current context in the AST
|
||||||
Context context;
|
Context context;
|
||||||
alias context this;
|
|
||||||
|
// Generates getter-setter methods to replace the use of alias this
|
||||||
|
// This should be replaced by a `static foreach` once the gdc tester
|
||||||
|
// gets upgraded to version 10 (to support `static foreach`).
|
||||||
|
private extern(D) static string generateMembers()
|
||||||
|
{
|
||||||
|
string result = "";
|
||||||
|
foreach(member; __traits(allMembers, Context))
|
||||||
|
{
|
||||||
|
result ~= "ref auto " ~ member ~ "() { return context." ~ member ~ "; }\n";
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
mixin(generateMembers());
|
||||||
|
|
||||||
this(OutBuffer* fwdbuf, OutBuffer* donebuf, OutBuffer* buf) scope
|
this(OutBuffer* fwdbuf, OutBuffer* donebuf, OutBuffer* buf) scope
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
// https://issues.dlang.org/show_bug.cgi?id=21073
|
|
||||||
|
|
||||||
class C
|
|
||||||
{
|
|
||||||
auto internal() const
|
|
||||||
{
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
alias internal this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() pure
|
|
||||||
{
|
|
||||||
const c = new C;
|
|
||||||
auto r = cast(C)c;
|
|
||||||
}
|
|
|
@ -1,116 +0,0 @@
|
||||||
// https://issues.dlang.org/show_bug.cgi?id=21543
|
|
||||||
|
|
||||||
class B
|
|
||||||
{
|
|
||||||
Nullable!B data;
|
|
||||||
alias data this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void test1()
|
|
||||||
{
|
|
||||||
B b;
|
|
||||||
Nullable!B n;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Nullable(T)
|
|
||||||
{
|
|
||||||
T payload;
|
|
||||||
|
|
||||||
void opAssign()(T)
|
|
||||||
{
|
|
||||||
move(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
inout(T) get_() inout
|
|
||||||
{
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
alias get_ this;
|
|
||||||
}
|
|
||||||
|
|
||||||
// another version with chain of 3 alias this
|
|
||||||
|
|
||||||
struct C
|
|
||||||
{
|
|
||||||
Nullable2 data;
|
|
||||||
alias data this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void test2()
|
|
||||||
{
|
|
||||||
C c;
|
|
||||||
Nullable2 n2 = &c;
|
|
||||||
Nullable3 n3 = &c;
|
|
||||||
|
|
||||||
// these are to check a sane -vcg-ast output
|
|
||||||
fn1(c);
|
|
||||||
fn1(n2);
|
|
||||||
fn1(n3);
|
|
||||||
fn2(c);
|
|
||||||
fn2(n2);
|
|
||||||
fn2(n3);
|
|
||||||
fn3(c);
|
|
||||||
fn3(n2);
|
|
||||||
fn3(n3);
|
|
||||||
}
|
|
||||||
|
|
||||||
void fn1(C x) {}
|
|
||||||
|
|
||||||
void fn2(Nullable2 x) {}
|
|
||||||
|
|
||||||
void fn3(Nullable3 x) {}
|
|
||||||
|
|
||||||
struct Nullable2
|
|
||||||
{
|
|
||||||
Nullable3 payload;
|
|
||||||
|
|
||||||
this(C* c)
|
|
||||||
{
|
|
||||||
payload = Nullable3(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
void opAssign()(Nullable3)
|
|
||||||
{
|
|
||||||
move(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
inout(Nullable3) get_() inout
|
|
||||||
{
|
|
||||||
return payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
alias get_ this;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Nullable3
|
|
||||||
{
|
|
||||||
C* payload;
|
|
||||||
|
|
||||||
this(C* c)
|
|
||||||
{
|
|
||||||
payload = c;
|
|
||||||
}
|
|
||||||
|
|
||||||
void opAssign()(C)
|
|
||||||
{
|
|
||||||
move(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
inout(C) get_() inout
|
|
||||||
{
|
|
||||||
return *payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
alias get_ this;
|
|
||||||
}
|
|
||||||
|
|
||||||
T move(T)(ref T source)
|
|
||||||
{
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
|
|
||||||
T move(T)(T source)
|
|
||||||
{
|
|
||||||
return source;
|
|
||||||
}
|
|
|
@ -1,41 +0,0 @@
|
||||||
// https://issues.dlang.org/show_bug.cgi?id=5973
|
|
||||||
|
|
||||||
class A { int a = 1; }
|
|
||||||
class B { int b = 2; }
|
|
||||||
class C : A
|
|
||||||
{
|
|
||||||
B obj;
|
|
||||||
alias obj this;
|
|
||||||
this(){ obj = new B(); }
|
|
||||||
}
|
|
||||||
class X : C {}
|
|
||||||
|
|
||||||
class D
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
}
|
|
||||||
|
|
||||||
class E
|
|
||||||
{
|
|
||||||
D x;
|
|
||||||
alias x this;
|
|
||||||
}
|
|
||||||
|
|
||||||
class F : E
|
|
||||||
{
|
|
||||||
void test()
|
|
||||||
{
|
|
||||||
i = 5;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
auto c = new C();
|
|
||||||
assert(c.a == 1); // lookup C -> A, OK
|
|
||||||
assert(c.b == 2); // lookup C => B, OK
|
|
||||||
|
|
||||||
auto x = new X();
|
|
||||||
assert(x.a == 1); // lookup X -> C -> A, OK
|
|
||||||
assert(x.b == 2); // lookup X -> C => B, NG (Line 17)
|
|
||||||
}
|
|
|
@ -1,11 +0,0 @@
|
||||||
struct S {}
|
|
||||||
|
|
||||||
class C {
|
|
||||||
S s;
|
|
||||||
alias s this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main() {
|
|
||||||
auto c = new C;
|
|
||||||
auto p = cast(void*) c;
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
/*
|
|
||||||
TEST_OUTPUT:
|
|
||||||
---
|
|
||||||
fail_compilation/fail5851.d(11): Error: alias this is not reachable as `Foo` already converts to `object.Object`
|
|
||||||
---
|
|
||||||
*/
|
|
||||||
|
|
||||||
class Foo
|
|
||||||
{
|
|
||||||
Object o;
|
|
||||||
alias o this;
|
|
||||||
}
|
|
||||||
|
|
||||||
void main()
|
|
||||||
{
|
|
||||||
}
|
|
|
@ -1,7 +1,16 @@
|
||||||
/*
|
/*
|
||||||
TEST_OUTPUT:
|
TEST_OUTPUT:
|
||||||
---
|
---
|
||||||
|
runnable/aliasthis.d(103): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/aliasthis.d(291): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/aliasthis.d(292): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/aliasthis.d(294): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/aliasthis.d(465): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/aliasthis.d(466): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/aliasthis.d(477): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/aliasthis.d(1013): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
false
|
false
|
||||||
|
runnable/aliasthis.d(2100): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
[] = int
|
[] = int
|
||||||
[] = string
|
[] = string
|
||||||
[0] = int
|
[0] = int
|
||||||
|
@ -10,6 +19,7 @@ false
|
||||||
[] = int
|
[] = int
|
||||||
[1] = string
|
[1] = string
|
||||||
[0] = int
|
[0] = int
|
||||||
|
runnable/aliasthis.d(741): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
---
|
---
|
||||||
|
|
||||||
RUN_OUTPUT:
|
RUN_OUTPUT:
|
||||||
|
|
|
@ -4,6 +4,7 @@ TEST_OUTPUT:
|
||||||
true
|
true
|
||||||
g
|
g
|
||||||
&Test109S(&Test109S(<recursion>))
|
&Test109S(&Test109S(<recursion>))
|
||||||
|
runnable/interpret.d(3742): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
tfoo
|
tfoo
|
||||||
tfoo
|
tfoo
|
||||||
Crash!
|
Crash!
|
||||||
|
|
|
@ -1,3 +1,13 @@
|
||||||
|
/*
|
||||||
|
TEST_OUTPUT:
|
||||||
|
---
|
||||||
|
runnable/test17684.d(37): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/test17684.d(54): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/test17684.d(54): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/test17684.d(37): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
---
|
||||||
|
*/
|
||||||
|
|
||||||
struct StructField(T)
|
struct StructField(T)
|
||||||
{
|
{
|
||||||
static T Field;
|
static T Field;
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
// https://issues.dlang.org/show_bug.cgi?id=19782
|
// https://issues.dlang.org/show_bug.cgi?id=19782
|
||||||
|
|
||||||
|
/*
|
||||||
|
TEST_OUTPUT:
|
||||||
|
---
|
||||||
|
runnable/test19782.d(17): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
---
|
||||||
|
*/
|
||||||
|
|
||||||
class Inner
|
class Inner
|
||||||
{
|
{
|
||||||
int a;
|
int a;
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
// https://issues.dlang.org/show_bug.cgi?id=21039
|
// https://issues.dlang.org/show_bug.cgi?id=21039
|
||||||
|
|
||||||
|
/*
|
||||||
|
TEST_OUTPUT:
|
||||||
|
---
|
||||||
|
runnable/test21039.d(14): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
---
|
||||||
|
*/
|
||||||
|
|
||||||
class Inner {}
|
class Inner {}
|
||||||
|
|
||||||
class Outer {
|
class Outer {
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
// https://issues.dlang.org/show_bug.cgi?id=23234
|
// https://issues.dlang.org/show_bug.cgi?id=23234
|
||||||
|
|
||||||
|
/*
|
||||||
|
TEST_OUTPUT:
|
||||||
|
---
|
||||||
|
runnable/test23234.d(17): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
---
|
||||||
|
*/
|
||||||
|
|
||||||
class Bar
|
class Bar
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
// https://issues.dlang.org/show_bug.cgi?id=11294
|
// https://issues.dlang.org/show_bug.cgi?id=11294
|
||||||
|
|
||||||
|
/*
|
||||||
|
TEST_OUTPUT:
|
||||||
|
---
|
||||||
|
runnable/testaliascast.d(29): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/testaliascast.d(58): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
---
|
||||||
|
*/
|
||||||
|
|
||||||
string result;
|
string result;
|
||||||
|
|
||||||
extern(C) void rt_finalize(void *ptr, bool det=true);
|
extern(C) void rt_finalize(void *ptr, bool det=true);
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
REQUIRED_ARGS: -preview=rvaluerefparam
|
REQUIRED_ARGS: -preview=rvaluerefparam
|
||||||
TEST_OUTPUT:
|
TEST_OUTPUT:
|
||||||
---
|
---
|
||||||
|
runnable/testassign.d(802): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/testassign.d(808): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
\ S1 S2a S2b S3a S3b S4a S4b
|
\ S1 S2a S2b S3a S3b S4a S4b
|
||||||
- true true true true true true true
|
- true true true true true true true
|
||||||
Xa true true true true true true true
|
Xa true true true true true true true
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
module traits_getPointerBitmap;
|
module traits_getPointerBitmap;
|
||||||
|
|
||||||
import core.stdc.stdio;
|
import core.stdc.stdio;
|
||||||
|
@ -76,19 +75,6 @@ template pOff(T)
|
||||||
enum pOff = T.p.offsetof / bytesPerPtr;
|
enum pOff = T.p.offsetof / bytesPerPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
class C(T, aliasTo = void)
|
|
||||||
{
|
|
||||||
static if(!is(aliasTo == void))
|
|
||||||
{
|
|
||||||
aliasTo a;
|
|
||||||
alias a this;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t x;
|
|
||||||
T t = void;
|
|
||||||
void* p;
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
|
|
||||||
void _testType(T)(size_t[] expected)
|
void _testType(T)(size_t[] expected)
|
||||||
|
@ -118,21 +104,6 @@ void testType(T)(size_t[] expected)
|
||||||
// prepend string
|
// prepend string
|
||||||
sexp[0] = (expected[0] << tOff!(S!(T, string))) | (1 << pOff!(S!(T, string))) | 2; // arr ptr
|
sexp[0] = (expected[0] << tOff!(S!(T, string))) | (1 << pOff!(S!(T, string))) | 2; // arr ptr
|
||||||
_testType!(S!(T, string))(sexp);
|
_testType!(S!(T, string))(sexp);
|
||||||
|
|
||||||
// generate bit pattern for C!T
|
|
||||||
C!T ct = null;
|
|
||||||
size_t mutexBit = (RTInfoMark__Monitor ? 2 : 0);
|
|
||||||
size_t ctpOff = ct.p.offsetof / bytesPerPtr;
|
|
||||||
size_t cttOff = ct.t.offsetof / bytesPerPtr;
|
|
||||||
sexp[0] = (expected[0] << cttOff) | (1 << ctpOff) | mutexBit;
|
|
||||||
_testType!(C!(T))(sexp);
|
|
||||||
|
|
||||||
C!(T, string) cts = null;
|
|
||||||
size_t ctspOff = cts.p.offsetof / bytesPerPtr;
|
|
||||||
size_t ctstOff = cts.t.offsetof / bytesPerPtr;
|
|
||||||
// generate bit pattern for C!T
|
|
||||||
sexp[0] = (expected[0] << ctstOff) | (1 << ctspOff) | mutexBit | 0b1000; // arr ptr
|
|
||||||
_testType!(C!(T, string))(sexp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////
|
///////////////////////////////////////
|
||||||
|
|
|
@ -2,11 +2,14 @@
|
||||||
//
|
//
|
||||||
/* TEST_OUTPUT:
|
/* TEST_OUTPUT:
|
||||||
---
|
---
|
||||||
|
runnable/xtest46.d(165): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
Boo!double
|
Boo!double
|
||||||
Boo!int
|
Boo!int
|
||||||
true
|
true
|
||||||
int
|
int
|
||||||
!! immutable(int)[]
|
!! immutable(int)[]
|
||||||
|
runnable/xtest46.d(2932): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/xtest46.d(2964): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
int(int i, long j = 7L)
|
int(int i, long j = 7L)
|
||||||
long
|
long
|
||||||
C10390(C10390(C10390(<recursion>)))
|
C10390(C10390(C10390(<recursion>)))
|
||||||
|
@ -19,6 +22,7 @@ string[]
|
||||||
double[]
|
double[]
|
||||||
double[]
|
double[]
|
||||||
{}
|
{}
|
||||||
|
runnable/xtest46.d(4670): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
tuple("m")
|
tuple("m")
|
||||||
true
|
true
|
||||||
TFunction1: extern (C) void function()
|
TFunction1: extern (C) void function()
|
||||||
|
|
|
@ -3,11 +3,14 @@ REQUIRED_ARGS: -lowmem -Jrunnable -preview=rvaluerefparam
|
||||||
EXTRA_FILES: xtest46.d
|
EXTRA_FILES: xtest46.d
|
||||||
TEST_OUTPUT:
|
TEST_OUTPUT:
|
||||||
---
|
---
|
||||||
|
runnable/xtest46_gc.d-mixin-33(197): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
Boo!double
|
Boo!double
|
||||||
Boo!int
|
Boo!int
|
||||||
true
|
true
|
||||||
int
|
int
|
||||||
!! immutable(int)[]
|
!! immutable(int)[]
|
||||||
|
runnable/xtest46_gc.d-mixin-33(2964): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
|
runnable/xtest46_gc.d-mixin-33(2996): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
int(int i, long j = 7L)
|
int(int i, long j = 7L)
|
||||||
long
|
long
|
||||||
C10390(C10390(<recursion>))
|
C10390(C10390(<recursion>))
|
||||||
|
@ -20,6 +23,7 @@ string[]
|
||||||
double[]
|
double[]
|
||||||
double[]
|
double[]
|
||||||
{}
|
{}
|
||||||
|
runnable/xtest46_gc.d-mixin-33(4702): Deprecation: alias this for classes/interfaces is deprecated
|
||||||
tuple("m")
|
tuple("m")
|
||||||
true
|
true
|
||||||
TFunction1: extern (C) void function()
|
TFunction1: extern (C) void function()
|
||||||
|
|
|
@ -2927,25 +2927,6 @@ void clear(Value, Key)(Value[Key]* aa)
|
||||||
assert("k1" !in aa);
|
assert("k1" !in aa);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Issue 20559
|
|
||||||
@system unittest
|
|
||||||
{
|
|
||||||
static class Foo
|
|
||||||
{
|
|
||||||
int[string] aa;
|
|
||||||
alias aa this;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto v = new Foo();
|
|
||||||
v["Hello World"] = 42;
|
|
||||||
v.clear;
|
|
||||||
assert("Hello World" !in v);
|
|
||||||
|
|
||||||
// Test for T*
|
|
||||||
static assert(!__traits(compiles, (&v).clear));
|
|
||||||
static assert( __traits(compiles, (*(&v)).clear));
|
|
||||||
}
|
|
||||||
|
|
||||||
/***********************************
|
/***********************************
|
||||||
* Reorganizes the associative array in place so that lookups are more
|
* Reorganizes the associative array in place so that lookups are more
|
||||||
* efficient.
|
* efficient.
|
||||||
|
@ -4278,44 +4259,6 @@ void destroy(bool initialize = true, T)(T obj) if (is(T == interface))
|
||||||
destroy!true(new C());
|
destroy!true(new C());
|
||||||
}
|
}
|
||||||
|
|
||||||
@system unittest
|
|
||||||
{
|
|
||||||
// class with an `alias this`
|
|
||||||
class A
|
|
||||||
{
|
|
||||||
static int dtorCount;
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
dtorCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class B
|
|
||||||
{
|
|
||||||
A a;
|
|
||||||
alias a this;
|
|
||||||
this()
|
|
||||||
{
|
|
||||||
a = new A;
|
|
||||||
}
|
|
||||||
static int dtorCount;
|
|
||||||
~this()
|
|
||||||
{
|
|
||||||
dtorCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
auto b = new B;
|
|
||||||
assert(A.dtorCount == 0);
|
|
||||||
assert(B.dtorCount == 0);
|
|
||||||
destroy(b);
|
|
||||||
assert(A.dtorCount == 0);
|
|
||||||
assert(B.dtorCount == 1);
|
|
||||||
|
|
||||||
auto a = new A;
|
|
||||||
destroy(a);
|
|
||||||
assert(A.dtorCount == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@system unittest
|
@system unittest
|
||||||
{
|
{
|
||||||
interface I { }
|
interface I { }
|
||||||
|
@ -4529,43 +4472,6 @@ if (__traits(isStaticArray, T))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://issues.dlang.org/show_bug.cgi?id=19218
|
|
||||||
@system unittest
|
|
||||||
{
|
|
||||||
static struct S
|
|
||||||
{
|
|
||||||
static dtorCount = 0;
|
|
||||||
~this() { ++dtorCount; }
|
|
||||||
}
|
|
||||||
|
|
||||||
static interface I
|
|
||||||
{
|
|
||||||
ref S[3] getArray();
|
|
||||||
alias getArray this;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class C : I
|
|
||||||
{
|
|
||||||
static dtorCount = 0;
|
|
||||||
~this() { ++dtorCount; }
|
|
||||||
|
|
||||||
S[3] a;
|
|
||||||
alias a this;
|
|
||||||
|
|
||||||
ref S[3] getArray() { return a; }
|
|
||||||
}
|
|
||||||
|
|
||||||
C c = new C();
|
|
||||||
destroy(c);
|
|
||||||
assert(S.dtorCount == 3);
|
|
||||||
assert(C.dtorCount == 1);
|
|
||||||
|
|
||||||
I i = new C();
|
|
||||||
destroy(i);
|
|
||||||
assert(S.dtorCount == 6);
|
|
||||||
assert(C.dtorCount == 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// ditto
|
/// ditto
|
||||||
void destroy(bool initialize = true, T)(ref T obj)
|
void destroy(bool initialize = true, T)(ref T obj)
|
||||||
if (!is(T == struct) && !is(T == interface) && !is(T == class) && !__traits(isStaticArray, T))
|
if (!is(T == struct) && !is(T == interface) && !is(T == class) && !__traits(isStaticArray, T))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue