[Issue 1807] New: ENHANCEMENT: Let IFTI "see through" templates to simple aliases

d-bugmail at puremagic.com d-bugmail at puremagic.com
Fri Jan 25 23:04:13 PST 2008


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

           Summary: ENHANCEMENT: Let IFTI "see through" templates to simple
                    aliases
           Product: D
           Version: 2.010
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla at digitalmars.com
        ReportedBy: webmaster at villagersonline.com


I was writing a program recently where I was passing around deeply nested
delegates, so I wrote a template alias to represent the type.  (Without it, it
was nearly impossible to use the correct amount of nested delegates.)

My program uses IFTI heavily, and what I found out was that as soon as I
implemented the template aliasing, my IFTI didn't work anymore.

After a bit of thinking, I realized that, in general, IFTI can't dive into
templates and speculate about what they might be, since each template instance
could represent an infinite number of types.  It's an impossible search.  But
in my special case, the search is linear, and can easily be accomplished.

My request: when a template function uses some type-expression which includes
an instantiation of a template, and there is only one version of that template,
and that template just has a single alias (or typedef, maybe?), then replace
the template reference with the alias, and use that to compute IFTI.

EXAMPLE CODE:

template wrap(T)
{
  alias void delegate(T*) wrap;
}

alias void delegate(int*) wrap_int;

void Foo1(T)(void delegate(T*)) {}
void Foo2(T)(wrap!(T))          {}
void Foo3   (wrap_int)          {}

void delegate(T*) Bar1(T)( T  arg) { return null; }
wrap!(T)          Bar2(T)( T  arg) { return null; }
wrap_int          Bar3   (int arg) { return null; }

void main()
{
  int i;
  Foo1(Bar1(i));
  Foo1(Bar2(i));
  Foo1(Bar3(i));
// these three have IFTI failures because the only way
// figure out the parameter T for template function Foo2
// is to realize that wrap!(T) is a template alias, and
// it seems that DMD doesn't realize that.
//
//  Foo2(Bar1(i));
//  Foo2(Bar2(i));
//  Foo2(Bar3(i));
  Foo3(Bar1(i));
  Foo3(Bar2(i));
  Foo3(Bar3(i));
}

END EXAMPLE CODE

My analysis: IFTI works quite well with delegates (see Foo1).  IFTI also works
quite well with aliases (DMD looks right through the alias, see Foo3).  IFTI
doesn't work when the alias is inside a template.  What I'm suggesting is that
DMD should look at the Foo2 function and realize that the type
  wrap!(T)
while a template expression, will always be equivalent to
  void delegate(T*)
due to the fact that:
  1) There is only declartion of the template
  2) The declaration only includes a single alias

Once DMD knows that Foo2 is actually
    void Foo2(T)(void delegate(T*)) {}
IFTI should work quite nicely.

Also note, BTW, that this transformation should happen on any number of
expressions in the function declaration, it should recurse, and it should be OK
if the template parameter is a tuple.  See my background code below.



BACKGROUND - A SNIPPET OF THE ACTUAL CODE WHERE I FOUND THIS PROBLEM:

template RegisterFor_mailbox(TPL...)
{
  alias void delegate(TPL) RegisterFor_mailbox;
}

template RegisterFor_retval(TPL...)
{
  alias void delegate(RegisterFor_mailbox!(TPL)) RegisterFor_retval;
}

RegisterFor_retval!()
RegisterFor_char()
                (Registry reg,char c)
{
  ...
}

// this function supports chaining of registrations, in this case chaining an
// IDENTIFIER to a pre-existing chain

RegisterFor_retval!(IDENTIFIER,TPL)
RegisterFor_IDENTIFIER(TPL...)
                      (Registry reg,
                       RegisterFor_retval!(TPL) chain)
{
  ...
}

void main()
{
  Registry reg = <whatever>;

  // as explained below, I currently have to explicitly instantiate these
  // function calls.  I'd like IFTI to do it for me, as I show here:
  RegisterFor_char      (reg, '{',  // my code also has chain-to-char
  RegisterFor_IDENTIFIER(reg,
  RegisterFor_IDENTIFIER(reg,
  RegisterFor_char      (reg, '}'))))
  (delegate void(IDENTIFIER id1,IDENTIFIER id2)
   {
     <mailbox code resides here>
   });
}

// in a chain, the deepest element (the last in the chain) should be easy to
// IFTI; the return value from that is one of the args for the next-deepest,
// and if IFTI worked the way I hoped, then that would allow us to IFTI the
// next-deepest, and so on up the chain.

END BACKGROUND CODE

You can see from the above that if I had to replace all of my nice
RegisterFor_retval!(...) expressions with the actual delegate code, the
complexity shoots through the roof.  (I have even worse places in my code.  In
one place, I have a paramter to a function which is
function-pointer-taking-delegate-argument-returning-delegate-nested-3-deep-deepest-delegate-taking-pointer-to-struct-argument.)

It's very hard to live without these aliases.  So right now, I am forcing the
calling code specifically choose the template parameters.  That's ugly.


-- 



More information about the Digitalmars-d-bugs mailing list