<< Back to previous view

[CLJ-884] Reflector error messages can be improved when no matching method is found. Created: 27/Nov/11  Updated: 18/Apr/14  Resolved: 18/Apr/14

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

Type: Enhancement Priority: Major
Reporter: Rahul Pilani Assignee: Unassigned
Resolution: Duplicate Votes: 1
Labels: errormsgs
Environment:

All


Attachments: Text File diff.patch    
Patch: Code

 Description   

When accessing a java method with an arity mismatch or a mismatched parameter type, Reflector.java returns the following error on REPL:
IllegalArgumentException No matching method found: xyz for class com.abc.MyClass

eventhough method xyz might exist on MyClass, but was being called with the wrong number of arguments.

Attached is a patch that fixes that problem.



 Comments   
Comment by Andy Fingerhut [ 22/Mar/12 8:47 PM ]

diff.patch of Nov 27, 2011 does not apply cleanly to latest master version of Clojure code (using "patch -p1 < diff.patch", at least). It is preferred by Clojure team that patches are in git format-patch format. Instructions for producing such a patch are given at http://clojure.org/patches

Rahul, are you planning to sign a Clojure Contributor Agreement? Without that, this code cannot be included in Clojure, unless a contributor reimplements it on their own.

Comment by Andy Fingerhut [ 23/Mar/12 1:14 AM ]

In private communication with the patch author today, he expressed an interest in submitting a signed CA so this patch can be considered for inclusion in Clojure.

Comment by Kevin Downey [ 17/Apr/14 10:48 PM ]

it has been two years, is there a CA to go with this patch yet?

Comment by Andy Fingerhut [ 18/Apr/14 2:01 AM ]

The patch author has not submitted a CA – their name is not listed at http://clojure.org/contributing

Everyone else is free to submit a patch if they wish.

Comment by Alex Miller [ 18/Apr/14 7:40 AM ]

I think CLJ-1130 is the same issue and it is much farther along in the process.





[CLJ-698] class accessible from deftype method bodies is not suitable for instance?, ... Created: 28/Dec/10  Updated: 18/Apr/14  Resolved: 18/Apr/14

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

Type: Defect Priority: Major
Reporter: Herwig Hochleitner Assignee: Unassigned
Resolution: Completed Votes: 0
Labels: deftype

Approval: Ok

 Description   

Example interaction: http://pastebin.com/cTdUCKfp
Which directly contradicts documentation for deftype

In the method bodies, the (unqualified) name can be used to name the class (for calls to new, instance? etc).



 Comments   
Comment by Stuart Halloway [ 29/Dec/10 12:45 PM ]

The problem occurs in 1.2 but is fixed on master. Leaving in backlog in case we ever cut another 1.2 release--if not, then mark as fixed.

Comment by Alex Miller [ 18/Apr/14 7:32 AM ]

Apparently fixed in 1.3.





[CLJ-1276] Can't make a dispatch map containing forward-declared fns Created: 09/Oct/13  Updated: 18/Apr/14  Resolved: 18/Apr/14

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.6
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Alex Coventry Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None

Attachments: File unbound-eg.tgz    

 Description   

If from (ns tst2) you try to call tst1/c, which calls tst1/f via dispatch map which was defined when tst1/f was forward declared, you get an "unbound fn" error. E.g.

user=> (dorun (map eval 
                   '[(ns tst1) 
                     (declare f) 
                     (def d {:k f}) 
                     (defn c [] ((d :k)))
                     (defn f [] :success)
                     (ns tst2 (:require [tst1]))
                     (tst1/c)]))

IllegalStateException Attempting to call unbound fn: #'tst1/f  clojure.lang.Var$Unbound.throwArity (Var.java:43)
tst2=> (clojure.repl/pst *e)
IllegalStateException Attempting to call unbound fn: #'tst1/f
	clojure.lang.Var$Unbound.throwArity (Var.java:43)
	tst1/c (NO_SOURCE_FILE:5)
	tst2/eval25 (NO_SOURCE_FILE:8)
	clojure.lang.Compiler.eval (Compiler.java:6642)
	clojure.lang.Compiler.eval (Compiler.java:6605)
	clojure.core/eval (core.clj:2883)
	clojure.core/map/fn--4222 (core.clj:2513)
	clojure.lang.LazySeq.sval (LazySeq.java:40)
	clojure.lang.LazySeq.seq (LazySeq.java:49)
	clojure.lang.RT.seq (RT.java:484)
	clojure.core/seq (core.clj:133)
	clojure.core/dorun (core.clj:2811)


 Comments   
Comment by Alex Coventry [ 09/Oct/13 10:43 PM ]

TEttinger pointed out on IRC that the forms in the example run without error if you wrap them in a (do) block. Here is an example using files. Relevant code is in src/unbound_eg/tst[12].clj. Example output shown below.

http://clojure-log.n01se.net/date/2013-10-09.html#23:52

lap% lein repl
nREPL server started on port 50125 on host 127.0.0.1
REPL-y 0.2.1
Clojure 1.5.1
Docs: (doc function-name-here)
(find-doc "part-of-name-here")
Source: (source function-name-here)
Javadoc: (javadoc java-object-or-class-here)
Exit: Control+D or (exit) or (quit)

user=> (require '[unbound-eg.tst2 :as t2])

IllegalStateException Attempting to call unbound fn: #'unbound-eg.tst1/f clojure.lang.Var$Unbound.throwArity (Var.java:43)
user=> (pst)
IllegalStateException Attempting to call unbound fn: #'unbound-eg.tst1/f
clojure.lang.Var$Unbound.throwArity (Var.java:43)
unbound-eg.tst1/c (tst1.clj:4)
unbound-eg.tst2/eval2233 (tst2.clj:3)
clojure.lang.Compiler.eval (Compiler.java:6619)
clojure.lang.Compiler.load (Compiler.java:7064)
clojure.lang.RT.loadResourceScript (RT.java:370)
clojure.lang.RT.loadResourceScript (RT.java:361)
clojure.lang.RT.load (RT.java:440)
clojure.lang.RT.load (RT.java:411)
clojure.core/load/fn--5018 (core.clj:5530)
clojure.core/load (core.clj:5529)
clojure.core/load-one (core.clj:5336)
nil

Comment by Kevin Downey [ 18/Apr/14 12:23 AM ]

this is just a fact of clojure's compilation model and how vars work.

a var is a little mutable cell

(declare foo) declares that a mutable cell exists with the name foo, it doesn't contain a value

foo then gets the value of the mutable cell (which has none)

(defn foo [] 1) then sets the value of the cell named foo to the function created from (fn [] 1)

Comment by Alex Miller [ 18/Apr/14 7:29 AM ]

I agree with Kevin - this is expected behavior.





[CLJ-1124] for-as Created: 10/Dec/12  Updated: 18/Apr/14  Resolved: 18/Apr/14

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: None

Type: Enhancement Priority: Minor
Reporter: Yongqian Li Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None


 Description   

A common pattern in programming is building up some data structure step by step:

In Python:

x = {0: 1}
for item in stuff:
    x[item] = item * x.get(item - 1, 0)

etc.

In an imperative for loop this is easy since we have easy access to the "current" data structure being built up.

I propose the addition of a function for-as similar to as-> except the value of the last loop iteration is bound to the name.

So we can write the above as:

(last (for-as [x {0 1}]
        [item stuff]
  (assoc x item (* item (get x (- item 1) 0)))))

An (un-optimized) implementation might be something like:

(defmacro reduce-for [[res init] for-seq-exprs body-expr]
  `(reduce #(%2 %1) ~init
    (for ~for-seq-exprs
      (fn [~res]
        ~body-expr))))

Note: reduce-for does not return a seq, instead it returns the result of the last loop body iteration.



 Comments   
Comment by Kevin Downey [ 18/Apr/14 1:30 AM ]

this is not super clear to me, but it seems like a request for a `for` like macro for reduce.

(reduce (fn [x item] (assoc x item (* item (get x (- item 1) 0)))) {0 1} stuff)
Comment by Alex Miller [ 18/Apr/14 7:18 AM ]

This case seems adequately handled by reduce or loop/recur. I don't think the proposal is compelling enough to consider adding to core.





[CLJ-1214] Compiler runs out of memory on a small snippet of code Created: 31/May/13  Updated: 18/Apr/14  Resolved: 18/Apr/14

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.5
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Praki Prakash Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: compiler
Environment:

Linux 3.2.0-39-generic


Attachments: File fubar.clj    

 Description   

Clojure compiler runs out of memory when loading the attached file. Transcript below.

$ java -cp ~/.m2/repository/org/clojure/clojure/1.5.1/clojure-1.5.1.jar:. clojure.main
Clojure 1.5.1
user=> (load "fubar")
OutOfMemoryError GC overhead limit exceeded  [trace missing]
user=> 

The file contents are:

  (ns fu.bar)

  (defn foo[l] (concat (drop-last l) (repeat (last l))))

  (def ^:const bar (foo [#(print "") #(println ";")]))

  bar

If I remove the metadata on bar, it works. Removal of namespace seems to fix it as well. Pretty strange.

Although I realize this code is not quite kosher, it would be nice to have the compiler deal with it.



 Comments   
Comment by Andy Fingerhut [ 01/Jun/13 7:40 PM ]

If you really do have 'bar' on a line by itself at the end of file fubar.clj, it seems you are asking it to evaluate the value of bar, which by the definitions is an infinite list, and will of course exhaust all available memory if you attempt to evaluate it.

It seems to me the more odd thing is not that it runs out of memory as shown, but that it does not run out of memory when you remove the metadata on bar.

What is the purpose of having 'bar' on a line by itself at the end of the file?

If I try this but remove 'bar' as the last line of the file, loading the file causes no errors regardless of whether there is metadata on bar's definition or not. It is strange that doing (load "fubar") followed by (first fu.bar/bar) seems to go into an infinite loop if the :const is there on bar, but quickly returns the correct answer if the metadata is removed.

Comment by Praki Prakash [ 01/Jun/13 8:40 PM ]

This code snippet is a minimal test case to show that the compiler runs out of memory. What I meant by "it works" was that the compiler doesn't run out of memory and successfully loads the file (or in my real code base, the namespace is compiled).

In my code, I use bar (or whatever the real thing is) as source of sequence of functions. The sole reference to bar is needed to trigger this issue. I believe that bar is not being fully evaluated here and thus no infinite loop. If I try to print it, yes, it will ultimately fail.

Comment by Praki Prakash [ 01/Jun/13 9:04 PM ]

Having thought about this a bit more, it seems to me that when bar is annotated with const, the compiler is trying to evaluate the associated expression which exhausts the heap? I have never looked at the compiler source and thus not sure if this is what is happening. If it is, then it seems like one should be really careful when adding metadata.

That still leaves the other question about the namespace requirement to cause memory exhaustion. I quite distinctly recall having to add the namespace when trying to come up with minimal test case to reproduce the bug.

If you think this is really user error, I would accept it

Comment by Andy Fingerhut [ 02/Jun/13 4:56 AM ]

It is not just any old metadata that causes this issue, only :const metadata. I tried testing with :const replaced with :dynamic and :private, and there was no problem.

This might shed some light on the issue: https://github.com/clojure/clojure/blob/master/changes.md#215-const-defs

It appears that ^:const is causing the compiler to evaluate the value at compile time. The value in your example is unbounded, so that can never complete.

Comment by Kevin Downey [ 17/Apr/14 10:39 PM ]

the problem is for complex objects :const results in the pr-str of the object being embedded in the bytecode, a pr-str of an infinite seq is going to blow the heap. I think the limits on the usage of :const are not well defined and instead of falling back on pr-str it should throw a compilation error for constants that are not jvm primitves or strings

Comment by Alex Miller [ 17/Apr/14 10:46 PM ]

There is support for handling a variety of other useful cases (core Clojure collections for example) as constant objects. And it is useful to allow code that is not constant but evaluates to a constant result (for creating data tables, etc). In the face of that, I'm not sure it's possible to bound this usefully without solving the halting problem. I'm tempted to just put this issue in the category of "don't do that".

Comment by Alex Miller [ 18/Apr/14 7:08 AM ]

After sleeping on it, I don't think this is worth working on (if there is anything that could even be done).





[CLJ-760] ClassNotFound when AOT compiling a self-referring deftype extended to a protocol Created: 18/Mar/11  Updated: 18/Apr/14  Resolved: 18/Apr/14

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: Release 1.2
Fix Version/s: None

Type: Defect Priority: Major
Reporter: Ryan Senior Assignee: Unassigned
Resolution: Not Reproducible Votes: 0
Labels: aot
Environment:

Clojure 1.2.0, 1.2.1, 1.3.0-alpha6, JDK 1.6.0_24, Ubuntu 10.10


Attachments: Text File stacktraces.txt    

 Description   

If I create a deftype that refers to itself in a protocol extension like below:

(ns type-test)

(defprotocol Foo
  (isa-foo [x]))

(deftype TypeTest []
  Foo
  (isa-foo [x]
           (instance? TypeTest x)))

And use that code via another namespace:

(ns test-type-user
  (:use [type-test :only (isa-foo)])
  (:import [type-test TypeTest]))

(isa-foo (TypeTest.))

When I try to AOT compile the test-type-user namespace with Clojure 1.2.0, I get java.lang.NoClassDefFoundError: compilestub/type-test/TypeTest (test_type_user.clj:5). Full stack trace attached. Running the same code on 1.2.1 and 1.3.0-alpha6 yielded the same exception with a slightly different error message (stacktrace for 1.2.1 is also in the attached file).

This came up in a test at Revelytix. We worked around this issue by not using instance? and instead comparing based on class name. Another workaround is to define the deftype and the extension separately (using extend-type or something similar). This problem also doesn't occur if the usage of the deftype and the definition of it are in the same namespace (i.e. if type-test and test-type-user were in the same file).



 Comments   
Comment by Alex Miller [ 18/Mar/11 10:27 AM ]

The first case where we saw this was actually in having a deftype implement a Java interface (not a protocol) and in that case you cannot extend the interface outside the deftype (although comparing based on class name of course works).

Comment by Kevin Downey [ 17/Apr/14 10:55 PM ]

I wonder if this could be a problem with the way the compiler does intrinsic magic for "instance?", there have been other bugs and significant changes to that part of the compiler in 2 years.

I am unable to reproduce this issue on clojure 1.6 or 1.5.1

Comment by Kevin Downey [ 17/Apr/14 10:57 PM ]

may be a dup of http://dev.clojure.org/jira/browse/CLJ-698

Comment by Alex Miller [ 18/Apr/14 7:03 AM ]

NR on Clojure 1.6.0.





[CLJ-1404] clojure.core/vals returns nil on an empty map instead of an empty sequence Created: 14/Apr/14  Updated: 14/Apr/14  Resolved: 14/Apr/14

Status: Closed
Project: Clojure
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Defect Priority: Trivial
Reporter: Satshabad Khalsa Assignee: Unassigned
Resolution: Declined Votes: 0
Labels: None


 Description   

Is this a bug? maybe I just don't understand. The documentation says: Returns a sequence of the map's values. Is nil a sequence?

This caused an unexpected nil to propagate through a bunch of list processing stuff.



 Comments   
Comment by Alex Miller [ 14/Apr/14 10:54 PM ]

An empty sequence is represented by nil, so this is consistent. For example: (seq (range 0)) => nil





Generated at Sun Apr 20 18:42:03 CDT 2014 using JIRA 4.4#649-r158309.