Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 97b57d6

Browse files
committed
CLJ-2898 Add additional check to prevent FI conversion if object is both IFn and FI
1 parent fb22fd7 commit 97b57d6

File tree

2 files changed

+19
-4
lines changed

2 files changed

+19
-4
lines changed

src/jvm/clojure/lang/Compiler.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,7 +1651,7 @@ private static Class toInvokerParamType(Class c) {
16511651
* If targetClass is FI and has an adaptable functional method
16521652
* Find fn invoker method matching adaptable method of FI
16531653
* Emit bytecode for (expr is emitted):
1654-
* if(expr instanceof IFn)
1654+
* if(expr instanceof IFn && !(expr instanceof FI))
16551655
* invokeDynamic(targetMethod, fnInvokerImplMethod)
16561656
* Else emit nothing
16571657
*/
@@ -1686,15 +1686,18 @@ static boolean maybeEmitFIAdapter(ObjExpr objx, GeneratorAdapter gen, Expr expr,
16861686
try {
16871687
java.lang.reflect.Method fnInvokerMethod = FnInvokers.class.getMethod(invokerMethodName, invokerParams);
16881688

1689-
// if(exp instanceof IFn) { emitInvokeDynamic(targetMethod, fnInvokerMethod) }
1689+
// if not (expr instanceof IFn), go to end label
16901690
expr.emit(C.EXPRESSION, objx, gen);
16911691
gen.dup();
16921692
gen.instanceOf(ifnType);
1693-
1694-
// if not instanceof IFn, go to end
16951693
Label endLabel = gen.newLabel();
16961694
gen.ifZCmp(Opcodes.IFEQ, endLabel);
16971695

1696+
// if (expr instanceof FI), go to end label
1697+
gen.dup();
1698+
gen.instanceOf(samType);
1699+
gen.ifZCmp(Opcodes.IFNE, endLabel);
1700+
16981701
// else adapt fn invoker method as impl for target method
16991702
emitInvokeDynamicAdapter(gen, targetClass, targetMethod, FnInvokers.class, fnInvokerMethod);
17001703

test/clojure/test_clojure/java_interop.clj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -859,3 +859,15 @@
859859

860860
(testing "Static method accepting FI arg, provided overloaded static class FI"
861861
(is (= \S (FunctionalTester/staticMethodWithFIArg "Static" 0 FunctionalTester/getChar)))))
862+
863+
(deftest CLJ-2898-reified-objs-both-IFn-and-FI
864+
(let [tl (ThreadLocal/withInitial
865+
(reify
866+
java.util.function.Supplier
867+
(get [_] 100)
868+
869+
clojure.lang.IFn
870+
(applyTo [_ _] 201)
871+
(invoke [_] 200)))]
872+
;; should not be adapted and use Supplier.get() impl on tl
873+
(is (= 100 (.get tl)))))

0 commit comments

Comments
 (0)