Clojure

Locals still cleared too aggressively on delay in specific cases

Details

  • Type: Defect Defect
  • Status: Closed Closed
  • Priority: Minor Minor
  • Resolution: Completed
  • Affects Version/s: Release 1.4
  • Fix Version/s: Release 1.6
  • Component/s: None
  • Labels:
    None

Description

This seems to be an extension of #CLJ-232. Locals are still cleared too aggressively in some specific instances: If the delay throws an exception when realized, and you dereference a local within the delay, the local may or may not be cleared depending on its need in the tail positions (without any obvious pattern). Examples of functions which works as intended and doesn't work as intended follows.

(def d (let [y (delay 0)]
         (delay (if (zero? @y) (/ 0 0) (/ @y 1))))) ; works properly

(def d (let [y (delay 0)]
         (delay (if (zero? @y) (/ 0 0) (/ 1 1))))) ; does not work properly

(def d (let [y (delay 0)]
         (delay (if (zero? @y) (/ @y 0) (/ 1 1))))) ; does not work properly

(def d (let [y (delay 0)]
         (delay (if (zero? @y) (/ @y 0) (/ @y 1))))) ; does not work properly

(def d (let [y (delay 0)]
         (delay @y (/ 0 0)))) ; does not work properly

(def d (let [y (delay 0)]
         (delay @y (/ 0 0) @y))) ; works properly

By "works", d will throw "ArithmeticException Divide by zero" every single time it is dereferenced. By "does not work", d will throw "ArithmeticException Divide by zero" on first dereferencing, but from second and onwards it will throw "NullPointerException [trace missing]".

Activity

Hide
Jean Niklas L'orange added a comment -

With Clojure 1.5.1, the trace is given and returns NullPointerException clojure.core/deref-future (core.clj:2NullPointerException clojure.core/deref-future (core.clj:2108)108), which refers to a .get call. The stacktrace reveals the following:

NullPointerException 
	clojure.core/deref-future (core.clj:2108)
	clojure.core/deref (core.clj:2129)
	user/fn--1/fn--4 (NO_SOURCE_FILE:2)
	clojure.lang.Delay.deref (Delay.java:33)
	clojure.core/deref (core.clj:2128)
	user/eval13 (NO_SOURCE_FILE:-1)
	clojure.lang.Compiler.eval (Compiler.java:6619)
	clojure.lang.Compiler.eval (Compiler.java:6582)
	clojure.core/eval (core.clj:2852)
	clojure.main/repl/read-eval-print--6588/fn--6591 (main.clj:259)
	clojure.main/repl/read-eval-print--6588 (main.clj:259)
	clojure.main/repl/fn--6597 (main.clj:277)
Show
Jean Niklas L'orange added a comment - With Clojure 1.5.1, the trace is given and returns NullPointerException clojure.core/deref-future (core.clj:2NullPointerException clojure.core/deref-future (core.clj:2108)108), which refers to a .get call. The stacktrace reveals the following:
NullPointerException 
	clojure.core/deref-future (core.clj:2108)
	clojure.core/deref (core.clj:2129)
	user/fn--1/fn--4 (NO_SOURCE_FILE:2)
	clojure.lang.Delay.deref (Delay.java:33)
	clojure.core/deref (core.clj:2128)
	user/eval13 (NO_SOURCE_FILE:-1)
	clojure.lang.Compiler.eval (Compiler.java:6619)
	clojure.lang.Compiler.eval (Compiler.java:6582)
	clojure.core/eval (core.clj:2852)
	clojure.main/repl/read-eval-print--6588/fn--6591 (main.clj:259)
	clojure.main/repl/read-eval-print--6588 (main.clj:259)
	clojure.main/repl/fn--6597 (main.clj:277)
Hide
Alex Miller added a comment -

This was fixed by CLJ-1175 which is now in 1.6.0-master. All of the given examples now work there.

Show
Alex Miller added a comment - This was fixed by CLJ-1175 which is now in 1.6.0-master. All of the given examples now work there.

People

Vote (0)
Watch (4)

Dates

  • Created:
    Updated:
    Resolved: