From a109510ed38c71daf57b1571c4c74d4b0a9c9a23 Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 11 Mar 2025 09:08:24 -0400 Subject: [PATCH 01/10] wip --- src/jvm/clojure/lang/Compiler.java | 20 +++++++++++++------- test/clojure/test_clojure/param_tags.clj | 3 +-- test/java/clojure/test/SwissArmy.java | 3 ++- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 6324456fa1..d64d6b2c60 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -1260,7 +1260,7 @@ private static Set aritySet(Class c, String methodName, MethodKind kind) { // Returns a list of methods or ctors matching the name and kind given. // Otherwise, will throw if the information provided results in no matches - private static List methodsWithName(Class c, String methodName, MethodKind kind) { + public static List methodsWithName(Class c, String methodName, MethodKind kind) { if (kind == MethodKind.CTOR) { List ctors = Arrays.asList(c.getConstructors()); if(ctors.isEmpty()) @@ -4359,18 +4359,24 @@ static public Expr parse(C context, ISeq form) { (KeywordExpr) fexpr, target); } - // Preserving the existing static field bug that replaces a reference in parens with - // the field itself rather than trying to invoke the value in the field. This is - // an exception to the uniform Class/member qualification per CLJ-2806 ticket. - if(fexpr instanceof StaticFieldExpr) - return fexpr; - PersistentVector args = PersistentVector.EMPTY; for(ISeq s = RT.seq(form.next()); s != null; s = s.next()) { args = args.cons(analyze(context, s.first())); } + // Preserving the existing static field bug that replaces a reference in parens with + // the field itself rather than trying to invoke the value in the field. This is + // an exception to the uniform Class/member qualification per CLJ-2806 ticket. + if(fexpr instanceof StaticFieldExpr) + if(RT.count(args) == 0) + return fexpr; + else { + Class c = ((StaticFieldExpr)fexpr).c; + Symbol sym = Symbol.intern(c.getName(), ((StaticFieldExpr)fexpr).fieldName); + return toHostExpr(new QualifiedMethodExpr(c, sym), (String) SOURCE.deref(), lineDeref(), columnDeref(), tagOf(form), tailPosition, args); + } + if(fexpr instanceof QualifiedMethodExpr) return toHostExpr((QualifiedMethodExpr)fexpr, (String) SOURCE.deref(), lineDeref(), columnDeref(), tagOf(form), tailPosition, args); diff --git a/test/clojure/test_clojure/param_tags.clj b/test/clojure/test_clojure/param_tags.clj index fee2d1c53e..bb39c8cbc7 100644 --- a/test/clojure/test_clojure/param_tags.clj +++ b/test/clojure/test_clojure/param_tags.clj @@ -165,8 +165,7 @@ (case (:type m) :constructor (let [{:keys [expected actual]} (exercise-constructor m)] (is (instance? expected actual))) - :static (let [{:keys [expected actual]} (exercise-static-method m)] - (is (= expected actual))) + :static (let [{:keys [expected actual]} (exercise-static-method m)] (is (= expected actual))) :instance (let [{:keys [expected actual]} (exercise-instance-method m)] (is (= expected actual)))))) diff --git a/test/java/clojure/test/SwissArmy.java b/test/java/clojure/test/SwissArmy.java index 339c3723c4..235a5ceb3a 100644 --- a/test/java/clojure/test/SwissArmy.java +++ b/test/java/clojure/test/SwissArmy.java @@ -1,6 +1,7 @@ package clojure.test; public class SwissArmy { + public static String doppelganger = "static-field"; public String ctorId; public SwissArmy() {this.ctorId = "1";} @@ -36,4 +37,4 @@ public class SwissArmy { public static String staticArityOverloadMethod(int a, int b) {return "int-int";} public static String staticArityOverloadMethod(int a, int b, int c) {return "int-int-int";} public static String doppelganger(int a, int b, long c) {return "int-int-long";} -} \ No newline at end of file +} From 6973437cd9ce254de0a139e58a16c6d9ed40880b Mon Sep 17 00:00:00 2001 From: Fogus Date: Mon, 14 Apr 2025 10:05:56 -0400 Subject: [PATCH 02/10] Added regression test for CLJ-2899 --- src/jvm/clojure/lang/Compiler.java | 11 +++++++---- test/clojure/test_clojure/param_tags.clj | 12 +++++++++++- test/java/clojure/test/SwissArmy.java | 1 + 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index d64d6b2c60..072e0133db 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -4368,14 +4368,17 @@ static public Expr parse(C context, ISeq form) { // Preserving the existing static field bug that replaces a reference in parens with // the field itself rather than trying to invoke the value in the field. This is // an exception to the uniform Class/member qualification per CLJ-2806 ticket. - if(fexpr instanceof StaticFieldExpr) - if(RT.count(args) == 0) + if(fexpr instanceof StaticFieldExpr) { + Class c = ((StaticFieldExpr) fexpr).c; + String name = ((StaticFieldExpr) fexpr).fieldName; + + if (RT.count(args) == 0 && QualifiedMethodExpr.methodsWithName(c, name, QualifiedMethodExpr.MethodKind.STATIC).isEmpty()) return fexpr; else { - Class c = ((StaticFieldExpr)fexpr).c; - Symbol sym = Symbol.intern(c.getName(), ((StaticFieldExpr)fexpr).fieldName); + Symbol sym = Symbol.intern(c.getName(), name); return toHostExpr(new QualifiedMethodExpr(c, sym), (String) SOURCE.deref(), lineDeref(), columnDeref(), tagOf(form), tailPosition, args); } + } if(fexpr instanceof QualifiedMethodExpr) return toHostExpr((QualifiedMethodExpr)fexpr, (String) SOURCE.deref(), lineDeref(), columnDeref(), tagOf(form), tailPosition, args); diff --git a/test/clojure/test_clojure/param_tags.clj b/test/clojure/test_clojure/param_tags.clj index bb39c8cbc7..7118416afa 100644 --- a/test/clojure/test_clojure/param_tags.clj +++ b/test/clojure/test_clojure/param_tags.clj @@ -165,10 +165,20 @@ (case (:type m) :constructor (let [{:keys [expected actual]} (exercise-constructor m)] (is (instance? expected actual))) - :static (let [{:keys [expected actual]} (exercise-static-method m)] (is (= expected actual))) + :static (let [{:keys [expected actual]} (exercise-static-method m)] + (is (= expected actual))) :instance (let [{:keys [expected actual]} (exercise-instance-method m)] (is (= expected actual)))))) +(deftest field-shadows-method-CLJ-2899-regression + (is (= "static-field" clojure.test.SwissArmy/doppelganger)) + (is (= "" (clojure.test.SwissArmy/doppelganger))) ;; favor 0-arity call over unwrap static field bug + (is (= "int-int" (clojure.test.SwissArmy/.doppelganger (clojure.test.SwissArmy/new) (int 1) (int 2)))) + (is (= "int-int" (apply clojure.test.SwissArmy/.doppelganger (clojure.test.SwissArmy/new) (int 1) (int 2) []))) + ;; Can't distinguish field vs static method in value position + ;; (is (= "int-int-long" (apply clojure.test.SwissArmy/doppelganger (int 1) (int 2) (long 42) []))) + (is (= "int-int-long" (clojure.test.SwissArmy/doppelganger (int 1) (int 2) (long 42))))) + (defmacro arg-tags-called-in-macro [a-type b-type a b] `(^[~a-type ~b-type] SwissArmy/staticArityOverloadMethod ~a ~b)) diff --git a/test/java/clojure/test/SwissArmy.java b/test/java/clojure/test/SwissArmy.java index 235a5ceb3a..b563d85acb 100644 --- a/test/java/clojure/test/SwissArmy.java +++ b/test/java/clojure/test/SwissArmy.java @@ -37,4 +37,5 @@ public class SwissArmy { public static String staticArityOverloadMethod(int a, int b) {return "int-int";} public static String staticArityOverloadMethod(int a, int b, int c) {return "int-int-int";} public static String doppelganger(int a, int b, long c) {return "int-int-long";} + public static String doppelganger() {return "";} } From 552aad080fba6b5c9134008d112dc53773215d22 Mon Sep 17 00:00:00 2001 From: Fogus Date: Mon, 14 Apr 2025 10:34:35 -0400 Subject: [PATCH 03/10] not a field access if there are param-tags --- src/jvm/clojure/lang/Compiler.java | 6 ++++-- test/clojure/test_clojure/param_tags.clj | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 072e0133db..55cc4e0688 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -4372,7 +4372,9 @@ static public Expr parse(C context, ISeq form) { Class c = ((StaticFieldExpr) fexpr).c; String name = ((StaticFieldExpr) fexpr).fieldName; - if (RT.count(args) == 0 && QualifiedMethodExpr.methodsWithName(c, name, QualifiedMethodExpr.MethodKind.STATIC).isEmpty()) + if (RT.count(args) == 0 +// && ((form.first() instanceof Symbol) && (paramTagsOf((Symbol)form.first()) == null)) + && QualifiedMethodExpr.methodsWithName(c, name, QualifiedMethodExpr.MethodKind.STATIC).isEmpty()) return fexpr; else { Symbol sym = Symbol.intern(c.getName(), name); @@ -7838,7 +7840,7 @@ private static Expr analyzeSymbol(Symbol sym) { Class c = HostExpr.maybeClass(nsSym, false); if(c != null) { - if(Reflector.getField(c, sym.name, true) != null) + if((paramTagsOf(sym) == null) && (Reflector.getField(c, sym.name, true) != null)) return new StaticFieldExpr(lineDeref(), columnDeref(), c, sym.name, tag); else return new QualifiedMethodExpr(c, sym); diff --git a/test/clojure/test_clojure/param_tags.clj b/test/clojure/test_clojure/param_tags.clj index 7118416afa..dc148cf159 100644 --- a/test/clojure/test_clojure/param_tags.clj +++ b/test/clojure/test_clojure/param_tags.clj @@ -175,8 +175,9 @@ (is (= "" (clojure.test.SwissArmy/doppelganger))) ;; favor 0-arity call over unwrap static field bug (is (= "int-int" (clojure.test.SwissArmy/.doppelganger (clojure.test.SwissArmy/new) (int 1) (int 2)))) (is (= "int-int" (apply clojure.test.SwissArmy/.doppelganger (clojure.test.SwissArmy/new) (int 1) (int 2) []))) - ;; Can't distinguish field vs static method in value position + ;; Can't distinguish field vs static method in value position w/o param-tags ;; (is (= "int-int-long" (apply clojure.test.SwissArmy/doppelganger (int 1) (int 2) (long 42) []))) + (is (= "" (apply ^[] clojure.test.SwissArmy/doppelganger []))) (is (= "int-int-long" (clojure.test.SwissArmy/doppelganger (int 1) (int 2) (long 42))))) (defmacro arg-tags-called-in-macro From 9699878f69640885f36296c8baf61ec99c7366bc Mon Sep 17 00:00:00 2001 From: Fogus Date: Mon, 14 Apr 2025 12:04:46 -0400 Subject: [PATCH 04/10] Cleaning up comments --- src/jvm/clojure/lang/Compiler.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 55cc4e0688..66b4ba090e 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -4365,16 +4365,14 @@ static public Expr parse(C context, ISeq form) { args = args.cons(analyze(context, s.first())); } - // Preserving the existing static field bug that replaces a reference in parens with - // the field itself rather than trying to invoke the value in the field. This is - // an exception to the uniform Class/member qualification per CLJ-2806 ticket. if(fexpr instanceof StaticFieldExpr) { Class c = ((StaticFieldExpr) fexpr).c; String name = ((StaticFieldExpr) fexpr).fieldName; - if (RT.count(args) == 0 -// && ((form.first() instanceof Symbol) && (paramTagsOf((Symbol)form.first()) == null)) - && QualifiedMethodExpr.methodsWithName(c, name, QualifiedMethodExpr.MethodKind.STATIC).isEmpty()) + // Preserving the existing static field bug that replaces a reference in parens with + // the field itself rather than trying to invoke the value in the field. This is + // an exception to the uniform Class/member qualification per CLJ-2806 ticket. + if (RT.count(args) == 0 && QualifiedMethodExpr.methodsWithName(c, name, QualifiedMethodExpr.MethodKind.STATIC).isEmpty()) return fexpr; else { Symbol sym = Symbol.intern(c.getName(), name); From 2af7d086521546217102b1eb18af6a88f669e214 Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 13 May 2025 08:46:53 -0400 Subject: [PATCH 05/10] Modified to check field/method overloads in analyzeSymbol. QME.emit/eval checks for overloads and emits field or thunk. --- src/jvm/clojure/lang/Compiler.java | 81 ++++++++++++++++++------------ 1 file changed, 49 insertions(+), 32 deletions(-) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 66b4ba090e..21da7a0575 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -1165,12 +1165,17 @@ static class QualifiedMethodExpr implements Expr { private final String methodName; private final MethodKind kind; private final Class tagClass; + private final StaticFieldExpr fieldOverload; private enum MethodKind { CTOR, INSTANCE, STATIC } - public QualifiedMethodExpr(Class methodClass, Symbol sym){ + public QualifiedMethodExpr(Class methodClass, Symbol sym) { + this(methodClass, sym, null); + } + + public QualifiedMethodExpr(Class methodClass, Symbol sym, StaticFieldExpr fieldOL) { c = methodClass; methodSymbol = sym; tagClass = tagOf(sym) != null ? HostExpr.tagToClass(tagOf(sym)) : AFn.class; @@ -1187,18 +1192,28 @@ else if(sym.name.equals("new")) { kind = MethodKind.STATIC; methodName = sym.name; } + fieldOverload = fieldOL; } // Expr impl - invocation, convert to fn expr + private boolean overloadsField() { + return fieldOverload != null && paramTagsOf(methodSymbol) == null; + } @Override public Object eval() { - return buildThunk(C.EVAL, this).eval(); + if(overloadsField()) + return fieldOverload.eval(); + else + return buildThunk(C.EVAL, this).eval(); } @Override public void emit(C context, ObjExpr objx, GeneratorAdapter gen) { - buildThunk(context, this).emit(context, objx, gen); + if(overloadsField()) + fieldOverload.emit(context, objx, gen); + else + buildThunk(context, this).emit(context, objx, gen); } // Expr impl - method value, always an AFn @@ -1258,18 +1273,9 @@ private static Set aritySet(Class c, String methodName, MethodKind kind) { return res; } - // Returns a list of methods or ctors matching the name and kind given. - // Otherwise, will throw if the information provided results in no matches - public static List methodsWithName(Class c, String methodName, MethodKind kind) { - if (kind == MethodKind.CTOR) { - List ctors = Arrays.asList(c.getConstructors()); - if(ctors.isEmpty()) - throw noMethodWithNameException(c, methodName, kind); - return ctors; - } - + public static List methodOverloads(Class c, String methodName, MethodKind kind) { final Executable[] methods = c.getMethods(); - List res = Arrays.stream(methods) + return Arrays.stream(methods) .filter(m -> m.getName().equals(methodName)) .filter(m -> { switch(kind) { @@ -1279,6 +1285,19 @@ public static List methodsWithName(Class c, String methodName, Metho } }) .collect(Collectors.toList()); + } + + // Returns a list of methods or ctors matching the name and kind given. + // Otherwise, will throw if the information provided results in no matches + private static List methodsWithName(Class c, String methodName, MethodKind kind) { + if (kind == MethodKind.CTOR) { + List ctors = Arrays.asList(c.getConstructors()); + if(ctors.isEmpty()) + throw noMethodWithNameException(c, methodName, kind); + return ctors; + } + + List res = methodOverloads(c, methodName, kind); if(res.isEmpty()) throw noMethodWithNameException(c, methodName, kind); @@ -4115,7 +4134,7 @@ static Object sigTag(int argcount, Var v){ return tagOf(sig); } return null; - } + } public InvokeExpr(String source, int line, int column, Symbol tag, Expr fexpr, IPersistentVector args, boolean tailPosition) { this.source = source; @@ -4359,27 +4378,18 @@ static public Expr parse(C context, ISeq form) { (KeywordExpr) fexpr, target); } + // Preserving the existing static field bug that replaces a reference in parens with + // the field itself rather than trying to invoke the value in the field. This is + // an exception to the uniform Class/member qualification per CLJ-2806 ticket. + if(fexpr instanceof StaticFieldExpr) + return fexpr; + PersistentVector args = PersistentVector.EMPTY; for(ISeq s = RT.seq(form.next()); s != null; s = s.next()) { args = args.cons(analyze(context, s.first())); } - if(fexpr instanceof StaticFieldExpr) { - Class c = ((StaticFieldExpr) fexpr).c; - String name = ((StaticFieldExpr) fexpr).fieldName; - - // Preserving the existing static field bug that replaces a reference in parens with - // the field itself rather than trying to invoke the value in the field. This is - // an exception to the uniform Class/member qualification per CLJ-2806 ticket. - if (RT.count(args) == 0 && QualifiedMethodExpr.methodsWithName(c, name, QualifiedMethodExpr.MethodKind.STATIC).isEmpty()) - return fexpr; - else { - Symbol sym = Symbol.intern(c.getName(), name); - return toHostExpr(new QualifiedMethodExpr(c, sym), (String) SOURCE.deref(), lineDeref(), columnDeref(), tagOf(form), tailPosition, args); - } - } - if(fexpr instanceof QualifiedMethodExpr) return toHostExpr((QualifiedMethodExpr)fexpr, (String) SOURCE.deref(), lineDeref(), columnDeref(), tagOf(form), tailPosition, args); @@ -7838,8 +7848,15 @@ private static Expr analyzeSymbol(Symbol sym) { Class c = HostExpr.maybeClass(nsSym, false); if(c != null) { - if((paramTagsOf(sym) == null) && (Reflector.getField(c, sym.name, true) != null)) - return new StaticFieldExpr(lineDeref(), columnDeref(), c, sym.name, tag); + if(Reflector.getField(c, sym.name, true) != null) + { + List maybeOverloads = QualifiedMethodExpr.methodOverloads(c, sym.name, QualifiedMethodExpr.MethodKind.STATIC); + + if(maybeOverloads.isEmpty()) + return new StaticFieldExpr(lineDeref(), columnDeref(), c, sym.name, tag); + else + return new QualifiedMethodExpr(c, sym, new StaticFieldExpr(lineDeref(), columnDeref(), c, sym.name, tag)); + } else return new QualifiedMethodExpr(c, sym); } From c3721cb17c0dbd9db3ada7e25e657a7660f69605 Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 13 May 2025 09:09:20 -0400 Subject: [PATCH 06/10] preserving pre 1.12 error on non-overloaded field holding IFn in invoke position taking args. --- src/jvm/clojure/lang/Compiler.java | 20 ++++++++++++++------ test/clojure/test_clojure/param_tags.clj | 3 ++- test/java/clojure/test/SwissArmy.java | 4 ++++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 21da7a0575..7b7e9658dd 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -4378,18 +4378,26 @@ static public Expr parse(C context, ISeq form) { (KeywordExpr) fexpr, target); } - // Preserving the existing static field bug that replaces a reference in parens with - // the field itself rather than trying to invoke the value in the field. This is - // an exception to the uniform Class/member qualification per CLJ-2806 ticket. - if(fexpr instanceof StaticFieldExpr) - return fexpr; - PersistentVector args = PersistentVector.EMPTY; for(ISeq s = RT.seq(form.next()); s != null; s = s.next()) { args = args.cons(analyze(context, s.first())); } + // Preserving the existing static field syntax that replaces a reference in parens with + // the field itself rather than trying to invoke the value in the field. This is + // an exception to the uniform Class/member qualification per CLJ-2806 ticket. + if(fexpr instanceof StaticFieldExpr) + { + if(RT.count(args) == 0) + return fexpr; + else + throw new IllegalArgumentException("No matching method " + + ((StaticFieldExpr) fexpr).fieldName + + " found taking " + RT.count(args) + " args for " + + ((StaticFieldExpr) fexpr).c); + } + if(fexpr instanceof QualifiedMethodExpr) return toHostExpr((QualifiedMethodExpr)fexpr, (String) SOURCE.deref(), lineDeref(), columnDeref(), tagOf(form), tailPosition, args); diff --git a/test/clojure/test_clojure/param_tags.clj b/test/clojure/test_clojure/param_tags.clj index dc148cf159..d9f0fb618f 100644 --- a/test/clojure/test_clojure/param_tags.clj +++ b/test/clojure/test_clojure/param_tags.clj @@ -178,7 +178,8 @@ ;; Can't distinguish field vs static method in value position w/o param-tags ;; (is (= "int-int-long" (apply clojure.test.SwissArmy/doppelganger (int 1) (int 2) (long 42) []))) (is (= "" (apply ^[] clojure.test.SwissArmy/doppelganger []))) - (is (= "int-int-long" (clojure.test.SwissArmy/doppelganger (int 1) (int 2) (long 42))))) + (is (= "int-int-long" (clojure.test.SwissArmy/doppelganger (int 1) (int 2) (long 42)))) + (is (thrown? Exception (eval '(clojure.test.SwissArmy/idFn 42))))) (defmacro arg-tags-called-in-macro [a-type b-type a b] diff --git a/test/java/clojure/test/SwissArmy.java b/test/java/clojure/test/SwissArmy.java index b563d85acb..f38e2d44f5 100644 --- a/test/java/clojure/test/SwissArmy.java +++ b/test/java/clojure/test/SwissArmy.java @@ -1,8 +1,12 @@ package clojure.test; +import clojure.java.api.Clojure; +import clojure.lang.IFn; + public class SwissArmy { public static String doppelganger = "static-field"; public String ctorId; + public static IFn idFn = Clojure.var("clojure.core", "identity"); public SwissArmy() {this.ctorId = "1";} public SwissArmy(int a, long b) {this.ctorId = "2";} From f13a64e20369046534d671025eb9571161a24ad5 Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 13 May 2025 09:12:33 -0400 Subject: [PATCH 07/10] tests for non-overloaded field holding IFn in invoke position --- test/clojure/test_clojure/param_tags.clj | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/clojure/test_clojure/param_tags.clj b/test/clojure/test_clojure/param_tags.clj index d9f0fb618f..c22dee67b5 100644 --- a/test/clojure/test_clojure/param_tags.clj +++ b/test/clojure/test_clojure/param_tags.clj @@ -179,7 +179,9 @@ ;; (is (= "int-int-long" (apply clojure.test.SwissArmy/doppelganger (int 1) (int 2) (long 42) []))) (is (= "" (apply ^[] clojure.test.SwissArmy/doppelganger []))) (is (= "int-int-long" (clojure.test.SwissArmy/doppelganger (int 1) (int 2) (long 42)))) - (is (thrown? Exception (eval '(clojure.test.SwissArmy/idFn 42))))) + (is (thrown? Exception (eval '(clojure.test.SwissArmy/idFn 42)))) + (is (= #'clojure.core/identity clojure.test.SwissArmy/idFn)) + (is (= #'clojure.core/identity (clojure.test.SwissArmy/idFn)))) (defmacro arg-tags-called-in-macro [a-type b-type a b] From 1c39356eedbf9362b9c991c86bd861b0a54fda14 Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 13 May 2025 14:10:21 -0400 Subject: [PATCH 08/10] aggregating related tests --- test/clojure/test_clojure/param_tags.clj | 35 ++++++++++++++++-------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/test/clojure/test_clojure/param_tags.clj b/test/clojure/test_clojure/param_tags.clj index c22dee67b5..aabdbe93c8 100644 --- a/test/clojure/test_clojure/param_tags.clj +++ b/test/clojure/test_clojure/param_tags.clj @@ -170,18 +170,29 @@ :instance (let [{:keys [expected actual]} (exercise-instance-method m)] (is (= expected actual)))))) -(deftest field-shadows-method-CLJ-2899-regression - (is (= "static-field" clojure.test.SwissArmy/doppelganger)) - (is (= "" (clojure.test.SwissArmy/doppelganger))) ;; favor 0-arity call over unwrap static field bug - (is (= "int-int" (clojure.test.SwissArmy/.doppelganger (clojure.test.SwissArmy/new) (int 1) (int 2)))) - (is (= "int-int" (apply clojure.test.SwissArmy/.doppelganger (clojure.test.SwissArmy/new) (int 1) (int 2) []))) - ;; Can't distinguish field vs static method in value position w/o param-tags - ;; (is (= "int-int-long" (apply clojure.test.SwissArmy/doppelganger (int 1) (int 2) (long 42) []))) - (is (= "" (apply ^[] clojure.test.SwissArmy/doppelganger []))) - (is (= "int-int-long" (clojure.test.SwissArmy/doppelganger (int 1) (int 2) (long 42)))) - (is (thrown? Exception (eval '(clojure.test.SwissArmy/idFn 42)))) - (is (= #'clojure.core/identity clojure.test.SwissArmy/idFn)) - (is (= #'clojure.core/identity (clojure.test.SwissArmy/idFn)))) +(deftest field-overloads-method-CLJ-2899-regression + (testing "overloaded in value position" + (is (= "static-field" clojure.test.SwissArmy/doppelganger))) + + (testing "overloaded in value position, w/paramtags" + (is (= "" (apply ^[] clojure.test.SwissArmy/doppelganger [])))) + + (testing "overloaded, invoke no args" + (is (= "" (clojure.test.SwissArmy/doppelganger)))) + + (testing "overloaded, invoke w/args" + (is (= "int-int-long" (clojure.test.SwissArmy/doppelganger (int 1) (int 2) (long 42))))) + + (tesing "non-overloaded, field holds IFn, invoke w/args fails" + (is (thrown? Exception (eval '(clojure.test.SwissArmy/idFn 42)))) + (is (= #'clojure.core/identity clojure.test.SwissArmy/idFn))) + + (testing "non-overloaded, field holds IFn, invoke no args" + (is (= #'clojure.core/identity (clojure.test.SwissArmy/idFn)))) + + (testing "instance method overloads" + (is (= "int-int" (clojure.test.SwissArmy/.doppelganger (clojure.test.SwissArmy/new) (int 1) (int 2)))) + (is (= "int-int" (apply clojure.test.SwissArmy/.doppelganger (clojure.test.SwissArmy/new) (int 1) (int 2) []))))) (defmacro arg-tags-called-in-macro [a-type b-type a b] From 83e57d9e5eed28d717999d0ad376c4c31ab76291 Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 13 May 2025 14:12:09 -0400 Subject: [PATCH 09/10] aggregating related tests --- test/clojure/test_clojure/param_tags.clj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/clojure/test_clojure/param_tags.clj b/test/clojure/test_clojure/param_tags.clj index aabdbe93c8..bccd3ef127 100644 --- a/test/clojure/test_clojure/param_tags.clj +++ b/test/clojure/test_clojure/param_tags.clj @@ -183,7 +183,7 @@ (testing "overloaded, invoke w/args" (is (= "int-int-long" (clojure.test.SwissArmy/doppelganger (int 1) (int 2) (long 42))))) - (tesing "non-overloaded, field holds IFn, invoke w/args fails" + (testing "non-overloaded, field holds IFn, invoke w/args fails" (is (thrown? Exception (eval '(clojure.test.SwissArmy/idFn 42)))) (is (= #'clojure.core/identity clojure.test.SwissArmy/idFn))) From e282531425977d6085783a76549c286ec2cab873 Mon Sep 17 00:00:00 2001 From: Fogus Date: Tue, 20 May 2025 08:54:41 -0400 Subject: [PATCH 10/10] Renaming overloadsField to preferOverloadField --- src/jvm/clojure/lang/Compiler.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index 7b7e9658dd..0bae0f6d54 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -1195,14 +1195,15 @@ else if(sym.name.equals("new")) { fieldOverload = fieldOL; } - // Expr impl - invocation, convert to fn expr - private boolean overloadsField() { + private boolean preferOverloadedField() { return fieldOverload != null && paramTagsOf(methodSymbol) == null; } + // Expr impl - invocation, convert to fn expr + @Override public Object eval() { - if(overloadsField()) + if(preferOverloadedField()) return fieldOverload.eval(); else return buildThunk(C.EVAL, this).eval(); @@ -1210,7 +1211,7 @@ public Object eval() { @Override public void emit(C context, ObjExpr objx, GeneratorAdapter gen) { - if(overloadsField()) + if(preferOverloadedField()) fieldOverload.emit(context, objx, gen); else buildThunk(context, this).emit(context, objx, gen); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy