Bug 13372 – traits parent does not work on eponymous templates

Status
NEW
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2014-08-24T18:11:39Z
Last change time
2024-12-13T18:24:50Z
Assigned to
No Owner
Creator
Ellery Newcomer
Blocks
14149
See also
https://issues.dlang.org/show_bug.cgi?id=12496
Moved to GitHub: dmd#18873 →

Comments

Comment #0 by ellery-newcomer — 2014-08-24T18:11:39Z
Passing an instantiated eponymous function template to __traits(parent,) yields a symbol that points to the function passed in. In G in the following code, I'm seeing this behavior: f __traits(parent, f) ------ ---------------------- a tok b!int.c __T1bTiZ t!int t code: import std.typetuple; int a(int i) { return i; } template b(T) { int c(T t) { return 1; } } int t(T)(T g) { return 1; } template G(alias f) { static assert(is(typeof(f) == function)); pragma(msg, __traits(identifier, f)); alias Parent = TypeTuple!(__traits(parent, f))[0]; pragma(msg, __traits(identifier, Parent)); static assert(!is(typeof(Parent) == typeof(f)), "I'm my own parent?"); } void main(){ alias y = G!(a); alias z = G!(t!int); // fails in here }
Comment #1 by slavo5150 — 2015-01-25T05:55:55Z
Looks like this might be the same as Issue 12496
Comment #2 by b2.temp — 2016-11-05T16:16:38Z
========= import std.meta; template Parent(T) { alias Parent = AliasSeq!(__traits(parent, T))[0]; } unittest { class A(T){} static assert(A!int.stringof != Parent!(A!int).stringof); } ========= yields: Error: static assert ("A!int" != "A!int") is false the longer form ========= import std.meta; template Parent(T) { alias Parent = AliasSeq!(__traits(parent, T))[0]; } unittest { template B(T){class B{}} alias T = B!int; static assert(is(T)); static assert(T.stringof != Parent!T.stringof); } ========= yields: Error: static assert ("B!int" != "B!int") is false too.
Comment #3 by b2.temp — 2016-11-05T18:06:52Z
Strangely enough this bug can lead to think that we can detect an eponymous template: ========== template isTemplateInstance(alias T : Base!Args, alias Base, Args...) { enum isTemplateInstance = is(typeof(T)); } template isTemplateInstance(T : Base!Args, alias Base, Args...) { enum isTemplateInstance = is(T); } template isTemplateInstance(T) { enum isTemplateInstance = false; } template isTemplateInstance(alias T) { enum isTemplateInstance = isTemplateInstance!(typeof(T)); } template isEponymousTemplate(T) { static if (is(T == class) || is(T == interface) || is(T == struct) || is(T == union)) { enum p = __traits(parent, T).stringof == T.stringof; enum isEponymousTemplate = p && isTemplateInstance!T; } else enum isEponymousTemplate = false; } unittest { class A(T){} struct B(T){} static assert(isEponymousTemplate!(A!int)); static assert(isEponymousTemplate!(B!int)); static assert(!isEponymousTemplate!int); template C(T) { class C{} } static assert(isEponymousTemplate!(C!int)); } unittest { template A(T) { class A{} } static assert(isEponymousTemplate!(A!int)); template B(T) { class A{} } static assert(!isEponymousTemplate!(B!int.A)); class C(T){} static assert(!isEponymousTemplate!int); A!int a; static assert(isEponymousTemplate!a); } ========== Indeed we can detect it but we can't get the parent ! What's happen is that "isEponymousTemplate" yield true for an eponymous template because the template itself points to its argument !
Comment #4 by slavo5150 — 2018-01-29T07:51:05Z
(In reply to Basile B. from comment #2) > ========= > import std.meta; > > template Parent(T) > { > alias Parent = AliasSeq!(__traits(parent, T))[0]; > } > > unittest > { > class A(T){} > static assert(A!int.stringof != Parent!(A!int).stringof); > } > ========= > > yields: Error: static assert ("A!int" != "A!int") is false > > > the longer form > > ========= > import std.meta; > > template Parent(T) > { > alias Parent = AliasSeq!(__traits(parent, T))[0]; > } > > unittest > { > template B(T){class B{}} > alias T = B!int; > static assert(is(T)); > static assert(T.stringof != Parent!T.stringof); > } > ========= > > yields: Error: static assert ("B!int" != "B!int") is false These two tests now pass in v2.078.1
Comment #5 by destructionator — 2020-05-24T17:24:28Z
Here's something related I just came upon: template wrap(string foo) { enum wrap = foo; } pragma(msg, __traits(parent, wrap!"lol")); // says lol pragma(msg, __traits(parent, __traits(parent, wrap!"lol"))); // says argument "lol" has no parent So in the first one, it appears it evaluates to the outer template which is then instantly evaluated back to the enum literal. Then the second one sees the literal and says literals have no parents. Quite bizarre indeed.
Comment #6 by robert.schadek — 2024-12-13T18:24:50Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18873 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB