digitalmars.D.bugs - [Issue 19407] New: Separate compilation breaks
- d-bugmail puremagic.com (106/106) Nov 16 2018 https://issues.dlang.org/show_bug.cgi?id=19407
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 puremagic.com Reporter: atila.neves 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. --
Nov 16 2018