<< Back to previous view

[CLJ-996] alter-var-root + protocol function call results in StackOverflow Created: 16/May/12  Updated: 01/Mar/13  Resolved: 09/Nov/12

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.3, Release 1.4
Fix Version/s: None

Type: Defect Priority: Critical
Reporter: Dmitri Naumov Assignee: Unassigned
Resolution: Declined Votes: 1
Labels: None


The following code:

(ns example.core)

(defprotocol Foo
  (foo [x]))

(extend-protocol Foo
  Object (foo [x] x)
  nil (foo [x] nil))

(defn apply-foo [f]
  (fn [& args]
    (foo (apply f args))))

(alter-var-root #'assoc apply-foo)

takes forever to compile from emacs+swank. Running from lein repl results in following:

user=> (use 'example.core)
StackOverflowError   clojure.lang.ArrayChunk.<init> (ArrayChunk.java:28)

If delete the foo call from the apply-foo:

(defn apply-foo [f]
  (fn [& args]
    (apply f args)))

then code compiles and executes fine.

This is true not only for assoc, but also for conj, into and possibly some other functions. Note also that crashes was seen even when the protocol function is not called, but there is call to satisfies? in the apply-foo function (although it's not clear for me how to reproduce it). Tested on clojure 1.3 and 1.4.

Comment by Tassilo Horn [ 11/Oct/12 1:23 PM ]

Is this bug a fairly well-constructed joke? I guess so.

But this is what I think happens: You change the value of #'assoc to the function returned by apply-foo. The alter-var-root call executes (apply-foo assoc) because assoc is the current value of #'assoc, thus the new value of #'assoc is {{(fn [& args] (foo (apply assoc args)))}}. However, fn is a macro that expands to fn* and calls destructure which uses assoc!!! So now foo gets called, and probably there's another assoc call during protocol dispatch, and there you have your non-terminating recursion.

So the lesson is: Don't alter core functions unless you're exactly knowing what you do.

Comment by Stuart Sierra [ 09/Nov/12 8:42 AM ]

Not a bug. You can't alter core functions and expect things not to break.

Generated at Wed Jan 17 14:34:29 CST 2018 using JIRA 4.4#649-r158309.