Bug 8542 – crosstalk between template instantiations

Status
RESOLVED
Resolution
WORKSFORME
Severity
normal
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-08-12T12:41:00Z
Last change time
2013-02-03T19:24:48Z
Keywords
rejects-valid
Assigned to
nobody
Creator
timon.gehr

Comments

Comment #0 by timon.gehr — 2012-08-12T12:41:55Z
With DMD 2.060, the following code compiles and runs correctly with dmd -version=A and dmd -version=B, but it fails to compile with dmd -version=A -version=B The code should compile and run correctly even when both version specifiers are set. import std.stdio, std.algorithm, std.range, std.bigint; template Apply(alias a,T...){ alias a!T Apply; } auto fun(T)(T n, T function(T) i, T function(T) d){ return (z=>((T delegate(T,T) delegate(T delegate(T delegate(T,T),T,T)) AOY) =>((m,e)=>reduce!((a,b)=>AOY((f,a,b)=>z(a)?b:i(f(d(a), b)))(a,b))(zip([(T[] a)=>a.map!((T x)=>m(i(i(n)),x)).array,(T[] a)=>a.map!((T x)=>m(i(i(i(n))),x)).array,delegate(T[] a)=>a.map! (a=>a).array].map!(a=>&Apply!(map!a,T[][])),[[i(n),i(i(n)),i(i(i(n))), i(i(i(i(n)))),i(i(i(i(i(n))))),i(i(i(i(i(i(n))))))], [i(i(i(i(i(n))))),i(i(i(i(i(i(n)))))),i(i(i(i(i(i(i(n))))))),i(i(i(i(i(i(i(i(n)))))))), i(i(i(i(i(i(i(i(i(n))))))))),i(i(i(i(n))))],[e(n,i(n)),e(i(n),i(i(n))),e(i(i(n)),i(n))]] ).map!(t=>t[0](t[1].map!(a=>[a,i(a),m(a,i(i(n)))]).array)).joiner.map!(a=>zip(a,retro(a)) .map!(t=>AOY((f,a,b)=>z(a)?b:i(f(d(a),b)))(t[0],t[1]))).joiner.chain(repeat( i(i(i(i(i(i(i(i(i(i(i(i(n))))))))))))).map!(a=>AOY ((f,a,b)=>z(b)?a:f(d(a),d(b)))(a,i(i(i(i(i(i(i(i(i(i(i(i(i(n))))))))))) )))).take(1))))((T a,T b)=>AOY((f,a,b)=>z(a)?n:AOY((g,a,b)=>z(a)? b:i(g(d(a),b)))(b,f(d(a),b)))(a,b),AOY((h,a,b)=>z(a)?z(b)?i(n):n:z(b)?n:h(d(a),d(b)))))( (a){struct S{ T delegate(T,T) delegate(S) r; } return ((x)=>x(S(x)))((S x)=>(T u,T v)=>a(x.r(x),u,v)); }))((T a)=>a==n); } void main(){ version(A) assert(fun(0,(int a)=>a+1,(int a)=>a-1)==1337); static inc(int[] a){ if(!a.length) return [1]; if(a[0]<0) return a[0..$-1]; return a~(a[$-1]+1); } static dec(int[] a){ if(!a.length) return [-1]; if(a[0]>0) return a[0..$-1]; return a~(a[$-1]-1); } version(B) assert(fun((int[]).init,&inc,&dec).equal(iota(1,1338))); }
Comment #1 by timon.gehr — 2012-08-12T12:45:44Z
importing std.bigint is not required to reproduce.
Comment #2 by bearophile_hugs — 2012-08-12T15:52:31Z
Are you able to minimize (and reformat in a human way) it a little?
Comment #3 by deadalnix — 2012-08-17T08:04:37Z
import std.algorithm, std.range; template Apply(alias a,T...){ alias a!T Apply; } auto fun(T)(T n, T function(T) i, T function(T) ){ (z=>(T delegate(T,T) delegate(T delegate(T delegate(T,T),T,T)) AOY) =>((m,e)=>reduce!((a,b)=>AOY((f,a,b)=>z?b:i(a))(a,b))(zip([(T[] a)=>a.map!(x=>m(n,x))].map!(a=>&Apply!(map!a,T[][])),[[n]]).map!(t=>t[0](t[1].map!(a=>[a]).array)).joiner.map!(a=>zip(a,retro(a)).map!(t=>AOY((f,a,b)=>z?b:i(a))(t[0],t[1]))).joiner.chain))((T a,T b)=>AOY((f,a,b)=>z?n:AOY((g,a,b)=>z?b:i(a))(b,f(a,b)))(a,b),AOY))((T a)=>a==n); } void main(){ version(A) fun(0,(int a)=>a+1,(int a)=>a-1); static inc(int[] a){ return a; } static dec(int[] a){ return a; } version(B) fun((int[]).init,&inc,&dec); } I reduced it to that. I fail to got further.
Comment #4 by hsteoh — 2012-10-16T17:24:02Z
Here's a somewhat simpler case: auto cprod(R1,R2)(R1 A, R2 B) { return zip(sequence!"n"(cast(size_t)0), A.save, B.save, repeat(A), repeat(B)) .map!(function(a) => chain( zip(repeat(a[1]), take(a[4].save,a[0])), zip(take(a[3].save,a[0]+1), repeat(a[2])) )).joiner; } void main() { auto A = sequence!"2*n"(0); auto B = sequence!"2*n+1"(0); auto AB = cprod(A,B); auto C = sequence!"100+n"(0); auto D = sequence!"200+n"(0); auto CD = cprod(C,D); } Produces the error: Error: function test3.cprod!(Sequence!("2*n",Tuple!(int)),Sequence!("2*n+1",Tuple!(int))).cprod.map!(__ funcliteral2).map!(Zip!(Sequence!("n",Tuple!(uint)),Sequence!("100+n",Tuple!(int)),Sequence!("200+n",Tupl e!(int)),Repeat!(Sequence!("100+n",Tuple!(int))),Repeat!(Sequence!("200+n",Tuple!(int))))).map is a neste d function and cannot be accessed from test3.cprod!(Sequence!("100+n",Tuple!(int)),Sequence!("200+n",Tupl e!(int))).cprod Commenting out either the first three lines (A, B, AB) or the second three lines (C, D, CD) makes the problem go away.
Comment #5 by Jesse.K.Phillips+D — 2012-10-19T11:23:02Z
I may have duplicated this issue: http://d.puremagic.com/issues/show_bug.cgi?id=8850
Comment #6 by hsteoh — 2013-01-03T21:39:09Z
Here's an unexpected data point: I discovered that this bug may be linked to the -property compiler flag. To reproduce this odd effect, checkout the code from: https://github.com/D-Programming-Language/phobos/pull/856, build Phobos without unittest, then check the output of the following commands (I tested this on Linux/64): 1) This one compiles just fine: dmd -unittest -m64 std/algorithm.d generated/linux/debug/64/emptymain.d -of/tmp/x 2) This one produces a whole bunch of template crosstalk errors: dmd -property -unittest -m64 std/algorithm.d generated/linux/debug/64/emptymain.d -of/tmp/x
Comment #7 by hsteoh — 2013-01-03T21:43:08Z
Hmm, the -property effect also happens with the simpler test case I posted earlier in comment 4: $ dmd test.d $ # Compiled successfully $ dmd -property test.d test.d(5): Error: no property 'map' for type 'Zip!(Sequence!("n", Tuple!(ulong)), Sequence!("2*n", Tuple!(int)), Sequence!("2*n+1", Tuple!(int)), Repeat!(Sequence!("2*n", Tuple!(int))), Repeat!(Sequence!("2*n+1", Tuple!(int))))' test.d(17): Error: template instance test.cprod!(Sequence!("2*n", Tuple!(int)), Sequence!("2*n+1", Tuple!(int))) error instantiating test.d(5): Error: no property 'map' for type 'Zip!(Sequence!("n", Tuple!(ulong)), Sequence!("100+n", Tuple!(int)), Sequence!("200+n", Tuple!(int)), Repeat!(Sequence!("100+n", Tuple!(int))), Repeat!(Sequence!("200+n", Tuple!(int))))' test.d(21): Error: template instance test.cprod!(Sequence!("100+n", Tuple!(int)), Sequence!("200+n", Tuple!(int))) error instantiating $
Comment #8 by hsteoh — 2013-01-03T21:49:54Z
Actually, nevermind that. I just realized that -property requires () for map and joiner because they aren't declared with @property (and UFCS does not alleviate the need for parentheses). The sad thing, though, is that my reduced test case no longer produces template crosstalk in git HEAD. :-(
Comment #9 by hsteoh — 2013-01-03T22:01:51Z
Hmph. It seems that Timon's original code also compiles fine in git head (without -property). With -property it fails, but seems the reason is that -property requires functions like map and joiner to have trailing parentheses (). The template crosstalk problem seems to have gone away.
Comment #10 by hsteoh — 2013-01-03T22:28:37Z
git bisect appears to indicate that it was dmd commit 688f7ce593eef75997a2b8f2527d3cd9338692aa that fixed this issue.
Comment #11 by bugzilla — 2013-01-03T23:46:02Z
Then we can resolve this as WORKSFORME.
Comment #12 by github-bugzilla — 2013-02-03T19:24:48Z