[Issue 19407] New: Separate compilation breaks hasElaborateDestructor with recursive type
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Fri Nov 16 10:53:36 UTC 2018
https://issues.dlang.org/show_bug.cgi?id=19407
Issue ID: 19407
Summary: Separate compilation breaks hasElaborateDestructor
with recursive type
Product: D
Version: D2
Hardware: x86_64
OS: Linux
Status: NEW
Severity: normal
Priority: P1
Component: dmd
Assignee: nobody at puremagic.com
Reporter: atila.neves at gmail.com
The code below compiles fine together but fails when compiled separately:
--------
// app.d
import type;
--------
---------
// type.d
import std.meta;
import std.traits;
struct Sum(Types...) if(Types.length > 0) {
union {
static foreach(i, T; Types) {
import std.conv: text;
mixin(`T value` ~ i.text ~ `;`);
}
}
static if(anySatisfy!(hasElaborateDestructor, Types)) {
}
}
alias Type = Sum!(Pointer, Bool);
struct Bool{}
struct Pointer{
Type* pointee;
}
---------
% dmd -c app.d
/usr/include/dlang/dmd/std/traits.d(2678): Error: unable to determine fields of
Pointer because of forward references
/usr/include/dlang/dmd/std/traits.d(3760): Error: template instance
`std.traits.FieldTypeTuple!(Pointer)` error instantiating
/usr/include/dlang/dmd/std/meta.d(887): instantiated from here:
F!(Pointer)
/usr/include/dlang/dmd/std/meta.d(892): instantiated from here:
anySatisfy!(hasElaborateDestructor, Pointer)
type.d(12): instantiated from here: anySatisfy!(hasElaborateDestructor,
Pointer, Bool)
type.d(17): instantiated from here: Sum!(Pointer, Bool)
The error messages seems to suggest that it's impossible to use
`Fields!Pointer` but if the `static if` is removed and a `pragma(msg,
Fields!Pointer)` is added it works fine.
It seems to be a bizarre interaction between separate compilation, `anySatisfy`
and `hasElaborateDestructor`. Notably, just trying to call
`hasElaborateDestructor!Pointer` fails with the same error messages.
It's possible to write a new version of `hasElaborateDestructor` that can be
used on `Pointer`:
---------
template sumtypeHasElaborateDestructor(S)
{
import std.meta : anySatisfy;
import std.traits: hasMember, Fields, isStaticArray, Fields;
static if (isStaticArray!S && S.length)
{
enum bool sumtypeHasElaborateDestructor =
sumtypeHasElaborateDestructor!(typeof(S.init[0]));
}
else static if (is(S == struct))
{
alias fields = Fields!S;
template foo(int index = fields.length - 1) {
static if(index == 0)
enum foo = .sumtypeHasElaborateDestructor!(fields[0]);
else
enum foo = .sumtypeHasElaborateDestructor!(fields[index]) ||
foo!(index -1);
}
enum sumtypeHasElaborateDestructor = hasMember!(S, "__dtor")
|| .sumtypeAnySatisfy!(.sumtypeHasElaborateDestructor, fields);
//|| foo!();
//|| anySatisfy!(.sumtypeHasElaborateDestructor, Fields!S);
}
else
{
enum bool sumtypeHasElaborateDestructor = false;
}
}
template sumtypeAnySatisfy(alias F, T...) {
template helper(int index) {
static if(index == 0)
enum helper = F!(T[0]);
else
enum helper = F!(T[index]) || helper!(index -1);
}
static if(T.length == 0)
enum sumtypeAnySatisfy = false;
else
enum sumtypeAnySatisfy = helper!(T.length - 1);
}
---------
And `sumtypeHasElaborateDestuctor!Pointer` compiles. But...
`sumtypeAnySatisfy!(sumtypeHasElaborateDestructor, Types)` fails again with the
same error messages as the standard Phobos versions.
--
More information about the Digitalmars-d-bugs
mailing list