Welcome! Please see the About page for a little more info on how this works.

0 votes
in Clojure by
closed by

Problem:
When making java calls (or inlined functions), if both args and param are primitive, no widening conversion is used to locate the proper overloaded method/constructor.

Examples:

`user=> (Integer. (byte 0))
java.lang.IllegalArgumentException: No matching ctor found for class java.lang.Integer (NO_SOURCE_FILE:0)

The above occurs because there is no Integer(byte) constructor, though it should match on Integer(int).

user=> (bit-shift-left (byte 1) 1)
Reflection warning, NO_SOURCE_PATH:3 - call to shiftLeft can't be resolved.
2` In the above, a call is made via reflection to Numbers.shiftLeft(Object, Object) and its associated auto-boxing, instead of directly to the perfectly adequate Numbers.shiftLeft(long, int). Workarounds:
Explicitly casting to the formal type. Ancillary benefits of fixing:
It would also reduce the amount of method overloading, e.g., RT.intCast(char), intCast(byte), intCast(short), could all be removed, since such calls would pass to RT.intCast(int).
closed with the note: Fixed as a side effect of CLJ-2843 in 1.11.3 and 1.12.0-alpha10

26 Answers

0 votes
by

Comment made by: redinger

This work is too big to take into the 1.3 beta right now. We'll revisit for a future release.

0 votes
by

Comment made by: ataggart

To better facilitate understanding of the changes, I've broken them up into two patches, each with a number of isolable, incremental commits:

reorg-reflector.patch: Moves the reflection/invocation code from Compiler to Reflector, and eliminates redundant code. The result is a single code base for resolving methods/constructors, which will allow for altering that mechanism without excess external coordination. This contains no behaviour changes.

prim-conversion.patch: Depends on the above. Alters the method/constructor resolution process:
more consistent with java resolution, especially when calling pre-1.5 APIs
adds support for widening conversion of primitive numerics of the same category (this is more strict than java, and more clojuresque)
* adds support for wildcard matches at compile-time (i.e., you don't need to type-hint every arg to avoid reflection).

This also provides a base to add further features, e.g., CLJ-666.

0 votes
by

Comment made by: ataggart

It's documented in situ, but here are the conversion rules that the reflector uses to find methods:

  1. By Type:
    **** object to ancestor type
    • primitive to a wider primitive of the same numeric category (new)
  2. Boxing:
    • boxed number to its primitive
    • boxed number to a wider primitive of the same numeric category (new for Short and Byte args)
      **** primitive to its boxed value
    • primitive to Number or Object (new)
  3. Casting:
    • long to int
    • double to float
0 votes
by

Comment made by: ataggart

prim-conversion-update-1.patch applies to current master.

0 votes
by

Comment made by: ataggart

Created CLJ-792 for the reflector reorg.

0 votes
by

Comment made by: stuart.sierra

prim-conversion-update-1.patch does not apply as of f5bcf64.

Is CLJ-792 now a prerequisite of this ticket?

0 votes
by

Comment made by: ataggart

Yes, after the original patch was deemed "too big".

After this much time with no action from TPTB, feel free to kill both tickets.

0 votes
by

Comment made by: jafingerhut

Again, not sure if this is any help, but I've tested starting from Clojure head as of Feb 20, 2012, applying clj-792-reorg-reflector-patch2.txt attached to CLJ-792, and then applying clj-445-prim-conversion-update-2-patch.txt attached to this ticket, and the result compiles and passes all but 2 tests. I don't know whether those failures are easy to fix or not, or whether issues may have been introduced with these patches.

0 votes
by

Comment made by: bronsa

As of 1.7.0-alpha5 the two examples in the ticket description run without exceptions/reflection-warnings

user=> (set! *warn-on-reflection* true) true user=> (bit-shift-left (byte 1) 1) 2 user=> (Integer. (byte 0)) 0

0 votes
by

Comment made by: fl00r

Hi!

`
(Integer. (Long. 1))

=> 1

(Long. (Integer. 1))

=> Exception

`

https://github.com/clojure/clojure/pull/59

0 votes
by
Reference: https://clojure.atlassian.net/browse/CLJ-445 (reported by ataggart)
...