ClojureScript

Stack overflow regression for sequence xform applied to eduction

Details

  • Type: Defect Defect
  • Status: Closed Closed
  • Priority: Critical Critical
  • Resolution: Completed
  • Affects Version/s: 1.9.562
  • Fix Version/s: None
  • Component/s: None
  • Patch:
    Code and Test
  • Approval:
    Accepted

Description

There is a regression in the ability to use sequence to apply transducers to eductions that was introduced with 1.9.562.

In 1.9.542 and earlier,

(sequence (map str) (eduction [1]))
produced ("1").

Minimal repro:

$ java -jar cljs.jar -m cljs.repl.node
ClojureScript Node.js REPL server listening on 50609
To quit, type: :cljs/quit
cljs.user=> (sequence (map str) (eduction [1]))
repl:13
throw e__5525__auto__;
^

RangeError: Maximum call stack size exceeded
    at Function.cljs.core.TransformerIterator.create (/Users/mfikes/Downloads/.cljs_node_repl/.cljs_node_repl/cljs/core.js:13959:50)
    at cljs.core.Eduction.cljs$core$IIterable$_iterator$arity$1 (/Users/mfikes/Downloads/.cljs_node_repl/.cljs_node_repl/cljs/core.js:33244:38)
    at Object.cljs$core$_iterator [as _iterator] (/Users/mfikes/Downloads/.cljs_node_repl/.cljs_node_repl/cljs/core.js:3158:13)
    at Object.cljs$core$iter [as iter] (/Users/mfikes/Downloads/.cljs_node_repl/.cljs_node_repl/cljs/core.js:13554:18)
    at Function.cljs.core.TransformerIterator.create (/Users/mfikes/Downloads/.cljs_node_repl/.cljs_node_repl/cljs/core.js:13960:55)
    at cljs.core.Eduction.cljs$core$IIterable$_iterator$arity$1 (/Users/mfikes/Downloads/.cljs_node_repl/.cljs_node_repl/cljs/core.js:33244:38)
    at Object.cljs$core$_iterator [as _iterator] (/Users/mfikes/Downloads/.cljs_node_repl/.cljs_node_repl/cljs/core.js:3158:13)
    at Object.cljs$core$iter [as iter] (/Users/mfikes/Downloads/.cljs_node_repl/.cljs_node_repl/cljs/core.js:13554:18)
    at Function.cljs.core.TransformerIterator.create (/Users/mfikes/Downloads/.cljs_node_repl/.cljs_node_repl/cljs/core.js:13960:55)
    at cljs.core.Eduction.cljs$core$IIterable$_iterator$arity$1 (/Users/mfikes/Downloads/.cljs_node_repl/.cljs_node_repl/cljs/core.js:33244:38)

Activity

Hide
Mike Fikes added a comment -

CLJS-2034:

d93c4356e7ab78743ae66d8cffe8df54869f0be3 is the first bad commit
commit d93c4356e7ab78743ae66d8cffe8df54869f0be3
Author: António Nuno Monteiro <anmonteiro@gmail.com>
Date:   Fri May 12 13:39:37 2017 -0700

    CLJS-2034: Sequence and Eduction produce infinite loop in transducer that appends to the reduction

    The implementation of transducers in ClojureScript tracked an old counterpart in
    the Clojure codebase. This patch addresses the change introduced in the
    following commit to Clojure, which replaced `LazyTransformer` with
    `TransformerIterator`, effectively making the transducer behavior akin to the
    one in Clojure.

    https://github.com/clojure/clojure/commit/c47e1bbcfa227723df28d1c9e0a6df2bcb0fecc1

:040000 040000 001a34e8f941a2e1697299be2632143e3e191587 5a508a3162eb9eb1023c0c0cd9ff7ee9cf2ad733 M	src
Show
Mike Fikes added a comment - CLJS-2034:
d93c4356e7ab78743ae66d8cffe8df54869f0be3 is the first bad commit
commit d93c4356e7ab78743ae66d8cffe8df54869f0be3
Author: António Nuno Monteiro <anmonteiro@gmail.com>
Date:   Fri May 12 13:39:37 2017 -0700

    CLJS-2034: Sequence and Eduction produce infinite loop in transducer that appends to the reduction

    The implementation of transducers in ClojureScript tracked an old counterpart in
    the Clojure codebase. This patch addresses the change introduced in the
    following commit to Clojure, which replaced `LazyTransformer` with
    `TransformerIterator`, effectively making the transducer behavior akin to the
    one in Clojure.

    https://github.com/clojure/clojure/commit/c47e1bbcfa227723df28d1c9e0a6df2bcb0fecc1

:040000 040000 001a34e8f941a2e1697299be2632143e3e191587 5a508a3162eb9eb1023c0c0cd9ff7ee9cf2ad733 M	src
Hide
António Nuno Monteiro added a comment -

Attached patch with fix and test.

Show
António Nuno Monteiro added a comment - Attached patch with fix and test.
Hide
Mike Fikes added a comment -

I don't know if this is a bug or not, but with 1.9.542

cljs.user=> (iter (eduction [1 2 3]))
#object[cljs.core.SeqIter]

and after the patch:

cljs.user=> (iter (eduction [1 2 3]))
repl:13
throw e__8096__auto__;
^

Error: [object Object] is not ISeqable
    at Object.cljs$core$seq [as seq] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:4413:8)
    at Object.cljs$core$pr_sequential_writer [as pr_sequential_writer] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31431:14)
    at cljs.core.TransformerIterator.cljs$core$IPrintWithWriter$_pr_writer$arity$3 (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:32456:18)
    at Object.cljs$core$pr_writer_impl [as pr_writer_impl] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31612:12)
    at Object.cljs$core$pr_writer [as pr_writer] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31722:18)
    at Object.cljs$core$pr_seq_writer [as pr_seq_writer] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31726:11)
    at Object.cljs$core$pr_sb_with_opts [as pr_sb_with_opts] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31789:11)
    at Object.cljs$core$pr_str_with_opts [as pr_str_with_opts] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31803:63)
    at Function.cljs.core.pr_str.cljs$core$IFn$_invoke$arity$variadic (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31886:18)
    at Object.cljs$core$pr_str [as pr_str] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31882:25){

I wonder if there is some public code path where this would show up (as opposed to directly calling iter).

Show
Mike Fikes added a comment - I don't know if this is a bug or not, but with 1.9.542
cljs.user=> (iter (eduction [1 2 3]))
#object[cljs.core.SeqIter]
and after the patch:
cljs.user=> (iter (eduction [1 2 3]))
repl:13
throw e__8096__auto__;
^

Error: [object Object] is not ISeqable
    at Object.cljs$core$seq [as seq] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:4413:8)
    at Object.cljs$core$pr_sequential_writer [as pr_sequential_writer] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31431:14)
    at cljs.core.TransformerIterator.cljs$core$IPrintWithWriter$_pr_writer$arity$3 (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:32456:18)
    at Object.cljs$core$pr_writer_impl [as pr_writer_impl] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31612:12)
    at Object.cljs$core$pr_writer [as pr_writer] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31722:18)
    at Object.cljs$core$pr_seq_writer [as pr_seq_writer] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31726:11)
    at Object.cljs$core$pr_sb_with_opts [as pr_sb_with_opts] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31789:11)
    at Object.cljs$core$pr_str_with_opts [as pr_str_with_opts] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31803:63)
    at Function.cljs.core.pr_str.cljs$core$IFn$_invoke$arity$variadic (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31886:18)
    at Object.cljs$core$pr_str [as pr_str] (/Users/mfikes/Projects/clojurescript/.cljs_node_repl/.cljs_node_repl/cljs/core.js:31882:25){
I wonder if there is some public code path where this would show up (as opposed to directly calling iter).
Hide
António Nuno Monteiro added a comment -

`(iter (eduction [1 2 3]))` is now a TransformerIterator, which doesn't have a print method.

For comparison with Clojure:

user=> (clojure.lang.RT/iter (eduction [1 2 3]))
#object[clojure.lang.TransformerIterator 0x28adf451 "clojure.lang.TransformerIterator@28adf451"]
Show
António Nuno Monteiro added a comment - `(iter (eduction [1 2 3]))` is now a TransformerIterator, which doesn't have a print method. For comparison with Clojure:
user=> (clojure.lang.RT/iter (eduction [1 2 3]))
#object[clojure.lang.TransformerIterator 0x28adf451 "clojure.lang.TransformerIterator@28adf451"]

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated:
    Resolved: