Clojure

Cannot resolve public generic method from package-private base class

Details

  • Type: Defect Defect
  • Status: Open Open
  • Priority: Minor Minor
  • Resolution: Unresolved
  • Affects Version/s: Release 1.3, Release 1.4, Release 1.5
  • Fix Version/s: None
  • Component/s: None
  • Labels:

Description

The Clojure compiler cannot resolve a public generic method inherited from a package-private base class.

Instructions to reproduce:

  • In package P1
    • Define a package-private class A with generic type parameters
    • Define a public method M in A using generic types in either its arguments or return value
    • Define a public class B which extends A
  • In package P2
    • Construct an instance of B
    • Invoke B.M()

This is valid in Java. In Clojure, invoking B.M produces a reflection warning, followed by the error "java.lang.IllegalArgumentException: Can't call public method of non-public class." No amount of type-hinting prevents the warning or the error.

Attachment clj-1243-demo1.tar.gz contains sample code and script to demonstrate the problem.

Examples of Java projects which use public methods in package-private classes:

Activity

Stuart Sierra made changes -
Field Original Value New Value
Description The Clojure compiler cannot resolve a public generic method inherited from a package-private base class.

Instructions to reproduce:

* In package P1
** Define a package-private class A with generic type parameters
** Define a public method M in A using generic types in either its arguments or return value
** Define a public class B which extends A
* In package P2
** Construct an instance of B
** Invoke B.M()

This is valid in Java. In Clojure, invoking B.M produces a reflection warning, followed by the error "java.lang.IllegalArgumentException: Can't call public method of non-public class." No amount of type-hinting prevents the warning or the error.
The Clojure compiler cannot resolve a public generic method inherited from a package-private base class.

Instructions to reproduce:

* In package P1
** Define a package-private class A with generic type parameters
** Define a public method M in A using generic types in either its arguments or return value
** Define a public class B which extends A
* In package P2
** Construct an instance of B
** Invoke B.M()

This is valid in Java. In Clojure, invoking B.M produces a reflection warning, followed by the error "java.lang.IllegalArgumentException: Can't call public method of non-public class." No amount of type-hinting prevents the warning or the error.

Attachment clj-1243-demo1.tar.gz contains sample code and script to demonstrate the problem.
Attachment clj-1243-demo1.tar.gz [ 12085 ]
Stuart Sierra made changes -
Description The Clojure compiler cannot resolve a public generic method inherited from a package-private base class.

Instructions to reproduce:

* In package P1
** Define a package-private class A with generic type parameters
** Define a public method M in A using generic types in either its arguments or return value
** Define a public class B which extends A
* In package P2
** Construct an instance of B
** Invoke B.M()

This is valid in Java. In Clojure, invoking B.M produces a reflection warning, followed by the error "java.lang.IllegalArgumentException: Can't call public method of non-public class." No amount of type-hinting prevents the warning or the error.

Attachment clj-1243-demo1.tar.gz contains sample code and script to demonstrate the problem.
The Clojure compiler cannot resolve a public generic method inherited from a package-private base class.

Instructions to reproduce:

* In package P1
** Define a package-private class A with generic type parameters
** Define a public method M in A using generic types in either its arguments or return value
** Define a public class B which extends A
* In package P2
** Construct an instance of B
** Invoke B.M()

This is valid in Java. In Clojure, invoking B.M produces a reflection warning, followed by the error "java.lang.IllegalArgumentException: Can't call public method of non-public class." No amount of type-hinting prevents the warning or the error.

Attachment clj-1243-demo1.tar.gz contains sample code and script to demonstrate the problem.

Examples of Java projects which use public methods in package-private classes:

* Netty, see [AbstractBootstrap.java|https://github.com/netty/netty/blob/ca0018279754557576bb2ecc17d209c2b6874609/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java#L152] for one example
* [jfager/functional-critbit|https://github.com/jfager/functional-critbit]
Stuart Sierra made changes -
Description The Clojure compiler cannot resolve a public generic method inherited from a package-private base class.

Instructions to reproduce:

* In package P1
** Define a package-private class A with generic type parameters
** Define a public method M in A using generic types in either its arguments or return value
** Define a public class B which extends A
* In package P2
** Construct an instance of B
** Invoke B.M()

This is valid in Java. In Clojure, invoking B.M produces a reflection warning, followed by the error "java.lang.IllegalArgumentException: Can't call public method of non-public class." No amount of type-hinting prevents the warning or the error.

Attachment clj-1243-demo1.tar.gz contains sample code and script to demonstrate the problem.

Examples of Java projects which use public methods in package-private classes:

* Netty, see [AbstractBootstrap.java|https://github.com/netty/netty/blob/ca0018279754557576bb2ecc17d209c2b6874609/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java#L152] for one example
* [jfager/functional-critbit|https://github.com/jfager/functional-critbit]
The Clojure compiler cannot resolve a public generic method inherited from a package-private base class.

Instructions to reproduce:

* In package P1
** Define a package-private class A with generic type parameters
** Define a public method M in A using generic types in either its arguments or return value
** Define a public class B which extends A
* In package P2
** Construct an instance of B
** Invoke B.M()

This is valid in Java. In Clojure, invoking B.M produces a reflection warning, followed by the error "java.lang.IllegalArgumentException: Can't call public method of non-public class." No amount of type-hinting prevents the warning or the error.

Attachment clj-1243-demo1.tar.gz contains sample code and script to demonstrate the problem.

Examples of Java projects which use public methods in package-private classes:

* [Netty|http://netty.io/] 4
** See [AbstractBootstrap.java|https://github.com/netty/netty/blob/ca0018279754557576bb2ecc17d209c2b6874609/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java#L152]
* [jfager/functional-critbit|https://github.com/jfager/functional-critbit]
** See [AbstractCritBitTree.java|https://github.com/jfager/functional-critbit/blob/abb927d7e93ad21eaf75da339c27220f2cfdc222/src/main/java/io/prelink/critbit/AbstractCritBitTree.java#L305]
** Example: {{(.get (io.prelink.critbit.CritBitTree. (org.ardverk.collection.DefaultKeyAnalyzer.)) nil)}}
Hide
Stuart Sierra added a comment - - edited

It is also not possible to call the method reflectively from Java.

This may be a bug in Java reflection: JDK-4283544

But why does it only happen on generic methods?

Show
Stuart Sierra added a comment - - edited It is also not possible to call the method reflectively from Java. This may be a bug in Java reflection: JDK-4283544 But why does it only happen on generic methods?
Hide
Stuart Sierra added a comment -

According to Rich Hickey, the presence of bridge methods is unspecified and inconsistent across JDK versions.

A possible solution is to use ASM to examine the bytecode of third-party Java classes, instead of the reflection API. That way the Clojure compiler would have access to the same information as the Java compiler.

Show
Stuart Sierra added a comment - According to Rich Hickey, the presence of bridge methods is unspecified and inconsistent across JDK versions. A possible solution is to use ASM to examine the bytecode of third-party Java classes, instead of the reflection API. That way the Clojure compiler would have access to the same information as the Java compiler.
Stuart Sierra made changes -
Description The Clojure compiler cannot resolve a public generic method inherited from a package-private base class.

Instructions to reproduce:

* In package P1
** Define a package-private class A with generic type parameters
** Define a public method M in A using generic types in either its arguments or return value
** Define a public class B which extends A
* In package P2
** Construct an instance of B
** Invoke B.M()

This is valid in Java. In Clojure, invoking B.M produces a reflection warning, followed by the error "java.lang.IllegalArgumentException: Can't call public method of non-public class." No amount of type-hinting prevents the warning or the error.

Attachment clj-1243-demo1.tar.gz contains sample code and script to demonstrate the problem.

Examples of Java projects which use public methods in package-private classes:

* [Netty|http://netty.io/] 4
** See [AbstractBootstrap.java|https://github.com/netty/netty/blob/ca0018279754557576bb2ecc17d209c2b6874609/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java#L152]
* [jfager/functional-critbit|https://github.com/jfager/functional-critbit]
** See [AbstractCritBitTree.java|https://github.com/jfager/functional-critbit/blob/abb927d7e93ad21eaf75da339c27220f2cfdc222/src/main/java/io/prelink/critbit/AbstractCritBitTree.java#L305]
** Example: {{(.get (io.prelink.critbit.CritBitTree. (org.ardverk.collection.DefaultKeyAnalyzer.)) nil)}}
The Clojure compiler cannot resolve a public generic method inherited from a package-private base class.

Instructions to reproduce:

* In package P1
** Define a package-private class A with generic type parameters
** Define a public method M in A using generic types in either its arguments or return value
** Define a public class B which extends A
* In package P2
** Construct an instance of B
** Invoke B.M()

This is valid in Java. In Clojure, invoking B.M produces a reflection warning, followed by the error "java.lang.IllegalArgumentException: Can't call public method of non-public class." No amount of type-hinting prevents the warning or the error.

Attachment clj-1243-demo1.tar.gz contains sample code and script to demonstrate the problem.

Examples of Java projects which use public methods in package-private classes:

* [Netty|http://netty.io/] 4
** See [AbstractBootstrap.java|https://github.com/netty/netty/blob/ca0018279754557576bb2ecc17d209c2b6874609/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java#L152] and [issue #1780|https://github.com/netty/netty/issues/1780]
* [jfager/functional-critbit|https://github.com/jfager/functional-critbit]
** See [AbstractCritBitTree.java|https://github.com/jfager/functional-critbit/blob/abb927d7e93ad21eaf75da339c27220f2cfdc222/src/main/java/io/prelink/critbit/AbstractCritBitTree.java#L305]
** Example: {{(.get (io.prelink.critbit.CritBitTree. (org.ardverk.collection.DefaultKeyAnalyzer.)) nil)}}
Alex Miller made changes -
Labels interop
Alex Miller made changes -
Description The Clojure compiler cannot resolve a public generic method inherited from a package-private base class.

Instructions to reproduce:

* In package P1
** Define a package-private class A with generic type parameters
** Define a public method M in A using generic types in either its arguments or return value
** Define a public class B which extends A
* In package P2
** Construct an instance of B
** Invoke B.M()

This is valid in Java. In Clojure, invoking B.M produces a reflection warning, followed by the error "java.lang.IllegalArgumentException: Can't call public method of non-public class." No amount of type-hinting prevents the warning or the error.

Attachment clj-1243-demo1.tar.gz contains sample code and script to demonstrate the problem.

Examples of Java projects which use public methods in package-private classes:

* [Netty|http://netty.io/] 4
** See [AbstractBootstrap.java|https://github.com/netty/netty/blob/ca0018279754557576bb2ecc17d209c2b6874609/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java#L152] and [issue #1780|https://github.com/netty/netty/issues/1780]
* [jfager/functional-critbit|https://github.com/jfager/functional-critbit]
** See [AbstractCritBitTree.java|https://github.com/jfager/functional-critbit/blob/abb927d7e93ad21eaf75da339c27220f2cfdc222/src/main/java/io/prelink/critbit/AbstractCritBitTree.java#L305]
** Example: {{(.get (io.prelink.critbit.CritBitTree. (org.ardverk.collection.DefaultKeyAnalyzer.)) nil)}}
The Clojure compiler cannot resolve a public generic method inherited from a package-private base class.

Instructions to reproduce:

* In package P1
** Define a package-private class A with generic type parameters
** Define a public method M in A using generic types in either its arguments or return value
** Define a public class B which extends A
* In package P2
** Construct an instance of B
** Invoke B.M()

This is valid in Java. In Clojure, invoking B.M produces a reflection warning, followed by the error "java.lang.IllegalArgumentException: Can't call public method of non-public class." No amount of type-hinting prevents the warning or the error.

Attachment clj-1243-demo1.tar.gz contains sample code and script to demonstrate the problem.

Examples of Java projects which use public methods in package-private classes:

* [Netty|http://netty.io/] 4
** See [AbstractBootstrap.java|https://github.com/netty/netty/blob/ca0018279754557576bb2ecc17d209c2b6874609/transport/src/main/java/io/netty/bootstrap/AbstractBootstrap.java#L152] and [issue #1780|https://github.com/netty/netty/issues/1780] and Clojure ticket CLJ-1183
* [jfager/functional-critbit|https://github.com/jfager/functional-critbit]
** See [AbstractCritBitTree.java|https://github.com/jfager/functional-critbit/blob/abb927d7e93ad21eaf75da339c27220f2cfdc222/src/main/java/io/prelink/critbit/AbstractCritBitTree.java#L305]
** Example: {{(.get (io.prelink.critbit.CritBitTree. (org.ardverk.collection.DefaultKeyAnalyzer.)) nil)}}
Hide
Andy Fingerhut added a comment -

CLJ-1183 was closed as a duplicate of this one. Mentioning it here in case anyone working on this ticket wants to follow the link to it and read discussion or test cases described there.

Show
Andy Fingerhut added a comment - CLJ-1183 was closed as a duplicate of this one. Mentioning it here in case anyone working on this ticket wants to follow the link to it and read discussion or test cases described there.

People

Vote (0)
Watch (1)

Dates

  • Created:
    Updated: