mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
91 lines
2.8 KiB
D
91 lines
2.8 KiB
D
// PERMUTE_ARGS:
|
|
|
|
struct A(T) { ~this() {} }
|
|
class C { A!int[1] array; }
|
|
|
|
void test14838() pure nothrow @nogc @safe
|
|
{
|
|
C c;
|
|
c.__xdtor(); // C.~this() will also be inferred to
|
|
// pure nothrow @nogc @safe
|
|
|
|
A!int[1] array;
|
|
// scope destructor call does not cause attribute violation.
|
|
}
|
|
|
|
// ----
|
|
|
|
/*
|
|
* This is a reduced test case comes from std.container.Array template,
|
|
* to fix the semantic analysis order issue for correct destructor attribute inference.
|
|
*
|
|
* Before the bugfix:
|
|
* 1. StructDeclaration('Array!int').semantic() instantiates
|
|
* RangeT!(Array!int) at the `alias Range = ...;`, but
|
|
* StructDeclaration('RangeT!(Array!int)').semantic() exits
|
|
* with sizeok == SIZEOKfwd, because the size of _outer_ field is not yet determined.
|
|
* 2. StructDeclaration('Array!int').semantic() succeeds to determine the size
|
|
* (sizeok = SIZEOKdone).
|
|
* 3. StructDeclaration('Array!int').buildOpAssign() will generate opAssign because
|
|
* Array!int._data field has identity opAssign member function.
|
|
* 4. The semantic3 will get called for the generated opAssign, then
|
|
* 6-1. Array!int.~this() semantic3, and
|
|
* 6-2. RefCounted!(Array!int.Payload).~this() semantic3
|
|
* will also get called to infer their attributes.
|
|
* 5. In RefCounted!(Array!int.Payload).~this(), destroy(t) will be instantiated.
|
|
* At that, TemplateInstance.expandMembers() will invoke runDeferredSemantic()
|
|
* and it will re-run StructDeclaration('RangeT!(Array!int)').semantic().
|
|
* 6. StructDeclaration('RangeT!(Array!int)').semantic() determines the size
|
|
* (sizeok = SIZEOKdone). Then, it will generate identity opAssign and run its semantic3.
|
|
* It will need to infer RangeT!(Array!int).~this() attribute, then it requires the
|
|
* correct attribute of Array!int.~this().
|
|
*
|
|
* However, the Array!int.~this() attribute is not yet determined! [bug]
|
|
* -> it's wongly handled as impure/system/throwable/gc-able.
|
|
*
|
|
* -> then, the attribute inference results for
|
|
* RangeT!(Array!int).~this() and Array!int.~this() will be incorrect.
|
|
*
|
|
* After the bugfix:
|
|
* In 6, StructDeclaration('RangeT!(Array!int)').semantic() will check that:
|
|
* all base struct types of the instance fields have completed addition of
|
|
* special functions (dtor, opAssign, etc).
|
|
* If not, it will defer the completion of its semantic pass.
|
|
*/
|
|
|
|
void destroy14838(S)(ref S s) if (is(S == struct))
|
|
{
|
|
s.__xdtor();
|
|
}
|
|
|
|
struct RefCounted14838(T)
|
|
{
|
|
~this()
|
|
{
|
|
T t;
|
|
.destroy14838(t);
|
|
}
|
|
|
|
void opAssign(typeof(this) rhs) {}
|
|
}
|
|
|
|
struct RangeT14838(A)
|
|
{
|
|
A[1] _outer_;
|
|
}
|
|
|
|
struct Array14838(T)
|
|
{
|
|
struct Payload
|
|
{
|
|
~this() {}
|
|
}
|
|
RefCounted14838!Payload _data;
|
|
|
|
alias Range = RangeT14838!Array14838;
|
|
}
|
|
|
|
class Test14838
|
|
{
|
|
Array14838!int[1] field;
|
|
}
|