[Issue 1818] New: storage class in type tuples is discarded for function and delegate declarations

d-bugmail at puremagic.com d-bugmail at puremagic.com
Tue Feb 5 10:12:37 PST 2008


http://d.puremagic.com/issues/show_bug.cgi?id=1818

           Summary: storage class in type tuples is discarded for function
                    and delegate declarations
           Product: D
           Version: 2.010
          Platform: PC
        OS/Version: All
            Status: NEW
          Keywords: wrong-code, spec
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla at digitalmars.com
        ReportedBy: kamm-removethis at incasoftware.de


Type tuples do contain storage class information when obtained via is(func
argstuple == function) or std.traits.ParameterTypeTuple. However, this
information is discarded if the tuple is used for a function declaration even
though the ParameterTypeTuple retains the storage class sometimes.

void foo(ref int i) { ++i; }
void bar(ParameterTypeTuple!(foo) f) { foo(f); }

void main() {
  int i = 0;
  foo(i);
  bar(i);
  writefln(i); // prints 1
}

// but incorrectly:

pragma(msg, ParameterTypeTuple!(foo).stringof); // prints "(ref int)"
pragma(msg, ParameterTypeTuple!(bar).stringof); // prints "(ref int)"


I think the frontend code responsible for this misbehaviour is func.c around
line 760. There the storage class of the tuple is propagated to each of the
tuple members, replacing existing storage classes.

Fixing this bug will allow compile-time reflection and manipulation of
parameter storage classes. It would still be impossible to create type tuples
containing non-default storage classes directly, but using code similar to this
will allow indirect manipulation via argument tuples:

template appendArg(X, T...) {
    alias ParameterTypeTuple!(void delegate(T, X)) appendArg;
}

template appendRefArg(X, T...) {
    alias ParameterTypeTuple!(void delegate(T, ref X)) appendRefArg;
}

alias appendRefArg!(int) refint;
alias appendArg!(real, refint) refint_real;
alias appendRefArg!(long, refint_real) refint_real_outlong;

pragma(msg, refint.stringof ~ " " ~ refint_real.stringof ~ " " ~
refint_real_outlong.stringof);
// current output: (ref int) (int, real) (int, real, ref long)
// desired output: (ref int) (ref int, real) (ref int, real, ref long)


Consequently this would also allow the implementation of the identity function
template that Andrei recommended as a testcase a while back:

ReturnType!(func) ident(alias func)(ParameterTypeTuple!(func) args) { return
func(args); }

Currently this fails for functions with arguments using non-default storage
classes. 


Finally, this change might break some code that expects storage classes to be
lost. It also interacts with bugs 1411 and 1424.


-- 



More information about the Digitalmars-d-bugs mailing list