D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 14346 - is-expression dependent on instantiation order
Summary: is-expression dependent on instantiation order
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86_64 Linux
: P1 normal
Assignee: No Owner
URL:
Keywords: wrong-code
Depends on:
Blocks:
 
Reported: 2015-03-26 15:59 UTC by Marc Schütz
Modified: 2022-02-14 15:46 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Marc Schütz 2015-03-26 15:59:47 UTC
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 Ketmar Dark 2015-03-26 23:19:30 UTC
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 Ketmar Dark 2015-03-26 23:19:54 UTC
ah. `usize` is simply an alias for `size_t`. sorry.
Comment 3 ag0aep6g 2015-04-25 20:58:28 UTC
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 RazvanN 2022-02-14 15:46:01 UTC
(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.