This code does not compile:
T1[] find(T1, T2)(T1[] longer, T2[] shorter)
if (is(typeof(longer[0 .. 1] == shorter) : bool))
{
while (longer.length >= shorter.length) {
if (longer[0 .. shorter.length] == shorter) break;
longer = longer[1 .. $];
}
return longer;
}
unittest {
double[] d1 = [ 6.0, 1.5, 2.4, 3 ];
double[] d2 = [ 1.5, 2.4 ];
assert(find(d1, d2) == d1[1 .. $]);
}
(I believe I'd submitted this bug already. Please don't mark as duplicate so all TDPL-related errors stay together.)
Comment #1 by clugdbug — 2009-10-16T00:33:37Z
I've convinced myself that this isn't too difficult, but it contains a lot of subtlties. I don't have a complete patch, but I've got basic cases working. Basically in deduceFunctionTemplateMatch() you need to create variables for each of the parameters (by analogy to func.c line 904).
for (i = 0; i < nfparams; i++)
{
Argument *fparam = Argument::getNth(fparameters, i);
if (!fparam->ident) continue; // don't add it, if it has no name
Type *vtype = // get the type, not sure how to do this properly
... deal with pure, etc.
VarDeclaration *v = new VarDeclaration(loc, vtype, fparam->ident, NULL);
... set the storage class
v->semantic(paramscope);
if (!paramscope->insert(v)) error("parameter %s.%s is already defined", toChars(), v->toChars());
}
Not sure how to deal with deal with the different flavours of variadics, though.
I originally thought that in TemplateDeclaration::matchWithInstance() you'd be able avoid checking the constraint again if it's a function template, but you can't because of cases like:
T1[] find(T1, T2)(T1[] longer, T2[] shorter) if (false)
{
assert(0);
return longer;
}
void main() {
double[] d1 = [ 6.0, 1.5, 2.4, 3 ];
double[] d2 = [ 1.5, 2.4 ];
assert(find!(double, double)(d1, d2) == d1[1 .. $]); // THIS MUST NOT COMPILE.
}
So it needs to have the same thing, wrapped in a
FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
if (fd) {
...
}
Comment #2 by clugdbug — 2009-10-16T18:41:32Z
Created attachment 474
Patch against 2.035 svn 215
Comment #3 by clugdbug — 2009-10-16T18:44:16Z
Since the patch contains two nearly-identical parts they probably should be factored out into a function. But it works.
Test cases for the patch:
------
/ bug3379
T1[] find(T1, T2)(T1[] longer, T2[] shorter)
if (is(typeof(longer[0 .. 1] == shorter) ))
{
while (longer.length >= shorter.length) {
if (longer[0 .. shorter.length] == shorter) break;
longer = longer[1 .. $];
}
return longer;
}
// bug2983
auto max(T...)(T a)
if (T.length == 2
&& is(typeof(a[1] > a[0] ? a[1] : a[0]))
|| T.length > 2
&& is(typeof(max(max(a[0], a[1]), a[2 .. $])))) {
static if (T.length == 2) {
return a[1] > a[0] ? a[1] : a[0];
} else {
return max(max(a[0], a[1]), a[2 .. $]);
}
}
void main() {
assert(max(4, 5) == 5);
assert(max(3, 4, 5) == 5);
double[] d1 = [ 6.0, 1.5, 2.4, 3 ];
double[] d2 = [ 1.5, 2.4 ];
assert(find(d1, d2) == d1[1 .. $]);
}
void bad(T)(T x) if (is(T : idouble)) { }
static assert(!is(typeof(bad(17)))); // must be rejected
static assert(!is(typeof(bad!(int)(2)))); // reject even if types specified
static assert(is(typeof(bad(3.0i))));
void fun(T)(char a, T[] b...) if (is(typeof(b[0]>b[1]))) {}
static assert(is(typeof(fun('x', 3.0, 4.0, 5.0))));
Comment #4 by clugdbug — 2009-10-16T18:45:01Z
*** Issue 2983 has been marked as a duplicate of this issue. ***
Comment #5 by clugdbug — 2009-10-22T00:09:36Z
Created attachment 480
Revised patch against 2.035 svn 215.
My patch had a nasty segfault regression. Trivial though. The line:
FuncDeclaration *fd = onemember->toAlias()->isFuncDeclaration();
if (fd)
causes segfaults if either onemember or toAlias() returns NULL.
fd should be NULL in either of those cases.
Comment #6 by clugdbug — 2009-10-23T08:25:44Z
Unfortunately my patch still isn't complete. The way I'm setting the storage
class of the parameters sometimes interferes with the later code. This surpises
me since I thought that the paramscope->pop() would undo all changes.
Clearly, there's something about the compiler I don't yet understand.
Comment #7 by clugdbug — 2009-11-12T00:25:51Z
Created attachment 493
Patch against svn 241
I've moved the implementation to a separate function. I fixed a couple of bugs; it now compiles the Phobos test suite.
Currently, it only works with free functions; I've disabled it for templated member functions (enabling it causes internal compiler errors). There's probably something I need to do with the variable declarations to make it work.
Comment #8 by clugdbug — 2009-11-12T00:28:15Z
Created attachment 494
Test cases
Some test cases I've used. Includes tests which previously caused segfaults.
Comment #9 by clugdbug — 2009-11-13T00:19:54Z
Created attachment 495
Patch against svn 246.
I think I've finally nailed it.
Now works for member functions. I was inserting the symbols into the wrong scope (they need to be added into the function scope, not the struct scope).
Comment #10 by leandro.lucarella — 2009-11-22T14:32:03Z