clojure

kuzmin_m 2026-04-08T14:36:18.700149Z

Inherited public methods from package-private superclass are not callable via Clojure interop. I hit this with Google’s https://github.com/google/mug library. The https://google.github.io/mug/apidocs/com/google/mu/util/StringFormat.html#format(java.lang.Object,java.lang.Object) is declared as public final on AbstractStringFormat, which is package-private. StringFormat is public and https://github.com/google/mug/blob/master/mug/src/main/java/com/google/mu/util/StringFormat.java#L86 it. In Java this works fine — javac emits invokevirtual on the public subclass. In Clojure, all three interop paths fail: 1. Type-hinted call (.format ^StringFormat fmt "a" "b") -> No matching method format found taking 2 args 2. Method reference ^[Object Object] StringFormat/.format -> IllegalAccessError: failed to access class AbstractStringFormat 3. No type hint (reflection) (.format fmt "a" "b") -> same as #1 java.lang.reflect.Method works fine — StringFormat.class.getMethod("format", Object, Object) finds and invokes it without issues. This looks like https://clojure.atlassian.net/browse/CLJ-1243 (open since 2013). Repro script in thread.

kuzmin_m 2026-04-08T14:36:41.719399Z

#!/bin/sh
#_(
DEPS='{:deps {com.google.mug/mug {:mvn/version "9.9.9"}}}'
exec clojure -Sdeps "$DEPS" -M "$0" "$@"
)

;; 

(import '(com.google.mu.util StringFormat))

(def fmt (StringFormat. "{a}/{b}"))

(println "=== 1 ===")
(try
  (eval '(.format ^StringFormat fmt "a" "b"))
  (catch Throwable e
    (println (str "  " (.getClass e) ": " (.getMessage e)))))

(println "=== 2 ===")
(try
  (eval '(let [f ^[Object Object] StringFormat/.format]
           (f fmt "a" "b")))
  (catch Throwable e
    (println (str "  " (.getClass e) ": " (.getMessage (or (.getCause e) e))))))

(println)
(println "=== 3 ===")
(try
  (let [result (.format fmt "a" "b")]
    (println (str "  result: " result)))
  (catch Throwable e
    (println (str "  " (.getClass e) ": " (.getMessage e)))))

(println)
(println "=== 4  ===")
(let [m (-> StringFormat (.getMethod "format" (into-array Class [Object Object])))]
  (.setAccessible m true)
  (println (str "  result: " (.invoke m fmt (object-array ["a" "b"])))))

2026-04-08T15:41:17.283379Z

I suspect that the way to type hint it would actually be to hint it with the AbstractStringFormat package-private class...

2026-04-08T15:41:32.325739Z

But ofc since it's package private that may cause issues.

borkdude 2026-04-08T15:18:36.979139Z

Somebody asked for DXML-75 to be fixed in babashka's built-in clojure.data.xml but I don't want to lean on other people's forks if the upstream can be fixed. @alexmiller Any chance this will be looked at soon-ish? https://clojure.atlassian.net/browse/DXML-75

RAMart 2026-04-09T09:38:41.064609Z

ℹ️ New patch file attached, https://clojure.atlassian.net/browse/DXML-75 updated.

🤞 3
🎉 2
Alex Miller (Clojure team) 2026-04-09T15:45:38.109989Z

https://clojurians.slack.com/archives/C06MAR553/p1775749510702949

🙇 1
🎉 2
borkdude 2026-04-09T15:46:31.407849Z

thanks!

Alex Miller (Clojure team) 2026-04-09T15:47:03.692189Z

thanks for making it non-breaking :)

🍻 1
💝 2
Alex Miller (Clojure team) 2026-04-08T16:32:56.445699Z

I dropped a comment there, not sure if OP is available to look at it. It seems like the patch could be made non-breaking and that would be better, then I would not have a problem merging

borkdude 2026-04-08T16:38:14.135689Z

Cc @ramart