Bug 14346 – is-expression dependent on instantiation order

Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2015-03-26T15:59:47Z
Last change time
2022-02-14T15:46:01Z
Keywords
wrong-code
Assigned to
No Owner
Creator
Marc Schütz

Comments

Comment #0 by schuetzm — 2015-03-26T15:59:47Z
This is a really weird bug. Here's how far I could reduce it: struct Validate() { this(string ) { } } template isConvertibleToInstanceOf(alias From, alias To) { enum isConvertibleToInstanceOf = isConvertibleToInstanceOf!(typeof(From), To); } template isConvertibleToInstanceOf(From, alias To) { enum isConvertibleToInstanceOf = is(From : To!Args, Args...); } template Validation() { void validate() { // run validators for members foreach(member; __traits(allMembers, typeof(this))) { foreach(UDA; __traits(getAttributes, mixin(member))) { // THE FOLLOWING LINE IS MAGIC static if(isConvertibleToInstanceOf!(UDA, Validate)) { } // --------------------------- } } // run validators for entire object foreach(UDA; __traits(getAttributes, typeof(this))) { // THE RESULT OF THIS IS-EXPR DEPENDS ON THE LINE ABOVE: static if(isConvertibleToInstanceOf!(UDA, Validate)) pragma(msg, "isConvertibleToInstanceOf: ", typeof(UDA)); } } } struct EmbeddedType { } EmbeddedType Embedded; @Embedded class Address { @Validate!()("invalid country") string country; mixin Validation; } When the first `static if` is there, the `pragma` prints "isConvertibleToInstanceOf: EmbeddedType". But if it is removed or commented out, the `pragma` isn't called; evidently the second `static if` fails.
Comment #1 by ketmar — 2015-03-26T23:19:30Z
seems that there is some bug with template merging. change your template declarations to this: template isConvertibleToInstanceOf(alias From, alias To, usize dummy=__LINE__) template isConvertibleToInstanceOf(From, alias To, usize dummy=__LINE__) and you will never see pragma output from second `static if`.
Comment #2 by ketmar — 2015-03-26T23:19:54Z
ah. `usize` is simply an alias for `size_t`. sorry.
Comment #3 by ag0aep6g — 2015-04-25T20:58:28Z
Reduced further: ---- template typeOf(alias From) { alias typeOf = typeof(From); } string val; int embedded; void main() { foreach(UDA; Tuple!val) { pragma(msg, typeOf!UDA); /* prints "string", ok */ } foreach(UDA; Tuple!embedded) { /* THE RESULT OF THIS DEPENDS ON THE LINE ABOVE: */ pragma(msg, typeOf!UDA); /* prints "string", should print "int" */ } } alias Tuple(stuff ...) = stuff; ---- This is very similar to issue 14501.
Comment #4 by razvan.nitu1305 — 2022-02-14T15:46:01Z
(In reply to ag0aep6g from comment #3) > Reduced further: > > ---- > template typeOf(alias From) > { > alias typeOf = typeof(From); > } > > string val; > int embedded; > > void main() > { > foreach(UDA; Tuple!val) > { > pragma(msg, typeOf!UDA); /* prints "string", ok */ > } > foreach(UDA; Tuple!embedded) > { > /* THE RESULT OF THIS DEPENDS ON THE LINE ABOVE: */ > pragma(msg, typeOf!UDA); /* prints "string", should print "int" */ > } > } > > alias Tuple(stuff ...) = stuff; > ---- > > This is very similar to issue 14501. When running the above code the second pragma prints int as expected. It seems that this has been fixed.