@@ -630,11 +630,46 @@ Creates a mapped iterator. Uses `__map` if possible.
630630auto mapIterator (alias fun, Iterator)(Iterator iterator)
631631{
632632 static if (__traits(hasMember, Iterator, " __map" ))
633- return Iterator.__map! fun(iterator);
633+ {
634+ static if (is (Iterator : MapIterator! (Iter0, fun0), Iter0, alias fun0)
635+ && ! __traits(compiles, Iterator.__map! fun(iterator)))
636+ {
637+ // https://github.com/libmir/mir-algorithm/issues/111
638+ pragma (msg, __FUNCTION__ ~ " not coalescing chained map calls into a single lambda, possibly because of multiple embedded context pointers" );
639+ return MapIterator! (Iterator, fun)(iterator);
640+ }
641+ else
642+ return Iterator.__map! fun(iterator);
643+ }
634644 else
635645 return MapIterator! (Iterator, fun)(iterator);
636646}
637647
648+ @safe pure nothrow @nogc version(mir_test) unittest
649+ {
650+ // https://github.com/libmir/mir-algorithm/issues/111
651+ import mir.ndslice.topology : iota, map;
652+ import mir.functional : pipe;
653+
654+ static auto foo (T)(T x)
655+ {
656+ return x.map! (a => a + 1 );
657+ }
658+
659+ static auto bar (T)(T x)
660+ {
661+ return foo (x).map! (a => a + 2 );
662+ }
663+
664+ auto data = iota(5 );
665+ auto result = iota([5 ], 3 );
666+
667+ auto x = data.map! (a => a + 1 ).map! (a => a + 2 );
668+ assert (x == result);
669+
670+ auto y = bar(data);
671+ assert (y == result);
672+ }
638673
639674/+ +
640675`BytegroupIterator` is used by $(SUBREF topology, Bytegroup) and $(SUBREF topology, bytegroup).
0 commit comments