Manuel K�nig <> changed:

           What    |Removed                     |Added
                 CC|                            |

--- Comment #4 from Manuel K�nig <> 2010-10-09 12:33:07 PDT ---
I just rediscovered this bug and reported it on the ldc bugtracker first, see . It's a frontend bug, and only
happens when you pass more than one argument to the template. I will copy my
findings here (using ldc to compile, but the result is the same with dmd v2.049
and v1.056).

There are various bugs with the "..." syntax for creating tuples, but I think
they all root back to types being errously converted to singletons of itself
when the number of arguments is >= 2.

// file tup_bug.d
template TupleBug(values...)
    alias values[0] v0;
    alias values[0][0][0][0][0] chain;

    pragma(msg, "values:    ", values);
    pragma(msg, "v0:        ", v0);
    pragma(msg, "values[0]: ", values[0]);
    pragma(msg, "chain:     ", chain);

pragma(msg, "-- TupleBug!(int):");
alias TupleBug!(int) _;

pragma(msg, "\n-- TupleBug!(int, \"foo\"):");
alias TupleBug!(int, "foo") _0;

void main() {}

Output of ldc 0.9.2 is

$ldc tup_bug.d
-- TupleBug!(int):
values:    (int)
v0:        int
values[0]: int
chain:     int[0LU][0LU][0LU][0LU]

-- TupleBug!(int, "foo"):
values:    tuple((int),"foo")
v0:        (int)
values[0]: int
chain:     (int)

Expected output for TupleBug?!(int, "foo"):

values:    tuple(int,"foo")
v0:        int
values[0]: int
chain:     int[0LU][0LU][0LU][0LU]

The output for TupleBug?!(int) is ok, but when the number of parameters is 2 or
greater, then all types T in the parameter list are implicitly converted to a
singleton tuple (T), as can be seen here in case of T=int. Even worse, you can
not index the singleton tuple, it just returns a copy of itself, which is
evident when looking at the output of chain.

In TupleBug?!(int), chain is a multidimensional array, which is correct. But in
TupleBug?!(int, "foo"), the output of chain is just (int).

I also think the usage of tuple(...) and (...) in the output is inconsistend,
it seems like tuple(...) is used for tuples of length >= 2 and (...) is used
for singleton tuples only. I would use tuple(...) in both cases.


One really annoying consequence that's bugging me is that assigning names to
template parameters via aliasing is not possible:

// file tup_bug_consequence.d
struct TypeAndName(args...)
    alias args[0] type; // "..." bug => type = (args[0]), not args[0]
    const char[] name = args[1];

template DeclVar(data)
    mixin("data.type "";");

void main()
    mixin DeclVar!(TypeAndName!(int, "foo"));

    pragma(msg, "foo:          ", foo);
    pragma(msg, "typeof(foo): ", typeof(foo));
    foo = 3;

I expect this to define "int foo;" inside main, but due to the "..." bug
described above, that doesn't work:

$ldc tup_bug_consequence.d
foo        : tuple(_foo_field_0)
typeof(foo): (int)
tup_bug_consequence.d(18): Error: foo is not an lvalue
tup_bug_consequence.d(18): Error: cannot implicitly convert expression (3) of
type int to (int)
tup_bug_consequence.d(18): Error: cannot cast int to (int)

This TypeAndName? construct is really useful for parsing template arguments of
the form (Type1, "name1", ..., TypeN, "nameN"), but as soon as you try to get
an alias to one of the types, everything breaks. A workaround is to always work
with the parameter tuple directly and don't alias its items, but then all your
templates are reduced to magic tuple indexing code that no one can understand.

Configure issuemail:
------- You are receiving this mail because: -------

Reply via email to