Clojure

when unable to match a method, report arity caller was looking for

Details

  • Type: Enhancement Enhancement
  • Status: Open Open
  • Priority: Major Major
  • Resolution: Unresolved
  • Affects Version/s: Release 1.4
  • Fix Version/s: None
  • Component/s: None
  • Labels:
  • Patch:
    Code and Test
  • Approval:
    Vetted

Description

Original motivation: Incorrectly invoking a static method with 0 parameters yields a NoSuchFieldException:

user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1) 
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)

Incorrectly invoking an instance method with 0 parameters yields a message about fields as well:

user=> (.setTime (java.util.Date.))
IllegalArgumentException No matching field found: setTime for class java.util.Date  clojure.lang.Reflector.getInstanceField (Reflector.java:271)

Patch: clj-1130-v5.diff

Approach: Primum non nocere. Error reporting enhanced at the site the errors happen, compiler logic unchanged.

  1. clj-1130-v1.txt
    09/Sep/13 12:36 AM
    4 kB
    Andy Fingerhut
  2. clj-1130-v2.diff
    22/Oct/13 9:11 AM
    4 kB
    Alex Miller
  3. clj-1130-v2.txt
    04/Oct/13 3:56 PM
    4 kB
    Alex Miller
  4. clj-1130-v2-ignore-ws.diff
    04/Nov/13 8:35 AM
    3 kB
    Andy Fingerhut
  5. clj-1130-v3.diff
    06/Dec/13 9:19 PM
    5 kB
    Alex Miller
  6. clj-1130-v4.diff
    31/Jan/14 3:12 PM
    8 kB
    Stuart Halloway
  7. clj-1130-v5.diff
    31/Jan/14 3:18 PM
    4 kB
    Andy Fingerhut

Activity

Alex Miller made changes -
Field Original Value New Value
Labels feedback errormsgs
Alex Miller made changes -
Approval Triaged [ 10120 ]
Rich Hickey made changes -
Approval Triaged [ 10120 ] Vetted [ 10003 ]
Fix Version/s Release 1.6 [ 10157 ]
Andy Fingerhut made changes -
Attachment clj-1130-v1.txt [ 12249 ]
Andy Fingerhut made changes -
Patch Code and Test [ 10002 ]
Andy Fingerhut made changes -
Description My code inadventently invoked a method that expected a single parameter, but passed no parameters.

The exception:
{noformat}
Exception in thread "main" java.lang.NoSuchFieldException: getService, compiling:(com/annadaletech/nexus/services/registry.clj:168)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6462)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6443)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:5883)
....
Caused by: java.lang.NoSuchFieldException: getService
at java.lang.Class.getField(Class.java:1520)
at clojure.lang.Compiler$StaticFieldExpr.<init>(Compiler.java:1180)
at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java:923)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
... 78 more
{noformat}

That threw me for a bit; really, it looks like the compiler is attempting to access a field and invoke it as an IFn. However, a proper message would be "getService() requires 1 parameter, not 0" (or something to that effect). Even "invalid number of parameters for SmashRuntime/getService()" would be better.
My code inadventently invoked a method that expected a single parameter, but passed no parameters.

The exception:
{noformat}
Exception in thread "main" java.lang.NoSuchFieldException: getService, compiling:(com/annadaletech/nexus/services/registry.clj:168)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6462)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6443)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:5883)
....
Caused by: java.lang.NoSuchFieldException: getService
at java.lang.Class.getField(Class.java:1520)
at clojure.lang.Compiler$StaticFieldExpr.<init>(Compiler.java:1180)
at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java:923)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
... 78 more
{noformat}

That threw me for a bit; really, it looks like the compiler is attempting to access a field and invoke it as an IFn. However, a proper message would be "getService() requires 1 parameter, not 0" (or something to that effect). Even "invalid number of parameters for SmashRuntime/getService()" would be better.

*Analysis*:

The compiler would guess that any attempt to invoke a static method with 0 args was an attempt to access a static field, which in the (. <class> <method/field-name>) syntax appear identical.

*Patch*: clj-1130-v1.txt

*Approach*: The guess that the form is trying to access a static field is still done the same as before. However, with the patch it will now check for a field with the specified name, and if there is none, the compiler will assume that it is a static method name instead.

The error message for attempting to call a static method now gives more details about the erroneous attempt, including the class name and that there is no such method that takes <n> arguments, where <n> is the number of arguments in the attempted method call.

Before patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

After patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 0 args, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 3 args, compiling:(NO_SOURCE_PATH:2:1)
{code}
Alex Miller made changes -
Assignee Alex Miller [ alexmiller ]
Alex Miller made changes -
Approval Vetted [ 10003 ] Screened [ 10004 ]
Description My code inadventently invoked a method that expected a single parameter, but passed no parameters.

The exception:
{noformat}
Exception in thread "main" java.lang.NoSuchFieldException: getService, compiling:(com/annadaletech/nexus/services/registry.clj:168)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6462)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6443)
at clojure.lang.Compiler.analyze(Compiler.java:6262)
at clojure.lang.Compiler.access$100(Compiler.java:37)
at clojure.lang.Compiler$LetExpr$Parser.parse(Compiler.java:5883)
....
Caused by: java.lang.NoSuchFieldException: getService
at java.lang.Class.getField(Class.java:1520)
at clojure.lang.Compiler$StaticFieldExpr.<init>(Compiler.java:1180)
at clojure.lang.Compiler$HostExpr$Parser.parse(Compiler.java:923)
at clojure.lang.Compiler.analyzeSeq(Compiler.java:6455)
... 78 more
{noformat}

That threw me for a bit; really, it looks like the compiler is attempting to access a field and invoke it as an IFn. However, a proper message would be "getService() requires 1 parameter, not 0" (or something to that effect). Even "invalid number of parameters for SmashRuntime/getService()" would be better.

*Analysis*:

The compiler would guess that any attempt to invoke a static method with 0 args was an attempt to access a static field, which in the (. <class> <method/field-name>) syntax appear identical.

*Patch*: clj-1130-v1.txt

*Approach*: The guess that the form is trying to access a static field is still done the same as before. However, with the patch it will now check for a field with the specified name, and if there is none, the compiler will assume that it is a static method name instead.

The error message for attempting to call a static method now gives more details about the erroneous attempt, including the class name and that there is no such method that takes <n> arguments, where <n> is the number of arguments in the attempted method call.

Before patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

After patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 0 args, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 3 args, compiling:(NO_SOURCE_PATH:2:1)
{code}
Invoking a static method with 0 parameters yields a NoSuchFieldException:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

*Cause:* This particular path in the Compiler covers both static field access and 0 argument static method invocation and in this case results in a confusing exception.

*Patch:* clj-1130-v1.txt

*Approach:* The guess that the form is trying to access a static field is still done the same as before. However, with the patch it will now check for a field with the specified name, and if there is none, the compiler will assume that the user is really trying to invoke a static method.

The error message for attempting to call a static method now gives more details about the erroneous attempt, including the class name and that there is no such method that takes <n> arguments, where <n> is the number of arguments in the attempted method call.

After patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 0 args, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 3 args, compiling:(NO_SOURCE_PATH:2:1)
{code}

*Screened by:* Alex Miller. Question: Is the performance impact prohibitive to add this reflective check for the existence of a static field when compiling 0-arg calls to static methods or static fields? It would be a bigger change (I think) but it might alternately be possible to do this check only in the case of a failure.
Attachment clj-1130-v2.txt [ 12292 ]
Assignee Alex Miller [ alexmiller ]
Alex Miller made changes -
Description Invoking a static method with 0 parameters yields a NoSuchFieldException:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

*Cause:* This particular path in the Compiler covers both static field access and 0 argument static method invocation and in this case results in a confusing exception.

*Patch:* clj-1130-v1.txt

*Approach:* The guess that the form is trying to access a static field is still done the same as before. However, with the patch it will now check for a field with the specified name, and if there is none, the compiler will assume that the user is really trying to invoke a static method.

The error message for attempting to call a static method now gives more details about the erroneous attempt, including the class name and that there is no such method that takes <n> arguments, where <n> is the number of arguments in the attempted method call.

After patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 0 args, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 3 args, compiling:(NO_SOURCE_PATH:2:1)
{code}

*Screened by:* Alex Miller. Question: Is the performance impact prohibitive to add this reflective check for the existence of a static field when compiling 0-arg calls to static methods or static fields? It would be a bigger change (I think) but it might alternately be possible to do this check only in the case of a failure.
Invoking a static method with 0 parameters yields a NoSuchFieldException:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

*Cause:* This particular path in the Compiler covers both static field access and 0 argument static method invocation and in this case results in a confusing exception.

*Patch:* clj-1130-v2.diff

*Approach:* The guess that the form is trying to access a static field is still done the same as before. However, with the patch it will now check for a field with the specified name, and if there is none, the compiler will assume that the user is really trying to invoke a static method.

The error message for attempting to call a static method now gives more details about the erroneous attempt, including the class name and that there is no such method that takes <n> arguments, where <n> is the number of arguments in the attempted method call.

After patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 0 args, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 3 args, compiling:(NO_SOURCE_PATH:2:1)
{code}

*Screened by:* Alex Miller. Question: Is the performance impact prohibitive to add this reflective check for the existence of a static field when compiling 0-arg calls to static methods or static fields? It would be a bigger change (I think) but it might alternately be possible to do this check only in the case of a failure.
Attachment clj-1130-v2.diff [ 12364 ]
Rich Hickey made changes -
Approval Screened [ 10004 ] Incomplete [ 10006 ]
Alex Miller made changes -
Approval Incomplete [ 10006 ] Screened [ 10004 ]
Andy Fingerhut made changes -
Attachment clj-1130-v2-ignore-ws.diff [ 12427 ]
Andy Fingerhut made changes -
Description Invoking a static method with 0 parameters yields a NoSuchFieldException:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

*Cause:* This particular path in the Compiler covers both static field access and 0 argument static method invocation and in this case results in a confusing exception.

*Patch:* clj-1130-v2.diff

*Approach:* The guess that the form is trying to access a static field is still done the same as before. However, with the patch it will now check for a field with the specified name, and if there is none, the compiler will assume that the user is really trying to invoke a static method.

The error message for attempting to call a static method now gives more details about the erroneous attempt, including the class name and that there is no such method that takes <n> arguments, where <n> is the number of arguments in the attempted method call.

After patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 0 args, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 3 args, compiling:(NO_SOURCE_PATH:2:1)
{code}

*Screened by:* Alex Miller. Question: Is the performance impact prohibitive to add this reflective check for the existence of a static field when compiling 0-arg calls to static methods or static fields? It would be a bigger change (I think) but it might alternately be possible to do this check only in the case of a failure.
Invoking a static method with 0 parameters yields a NoSuchFieldException:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

*Cause:* This particular path in the Compiler covers both static field access and 0 argument static method invocation and in this case results in a confusing exception.

*Patch:* clj-1130-v2.diff
*Patch with whitespace differences ignored, intended only for review purposes, not for committing:* clj-1130-v2-ignore-ws.diff

*Approach:* The guess that the form is trying to access a static field is still done the same as before. However, with the patch it will now check for a field with the specified name, and if there is none, the compiler will assume that the user is really trying to invoke a static method.

The error message for attempting to call a static method now gives more details about the erroneous attempt, including the class name and that there is no such method that takes <n> arguments, where <n> is the number of arguments in the attempted method call.

After patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 0 args, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 3 args, compiling:(NO_SOURCE_PATH:2:1)
{code}

*Screened by:* Alex Miller. Question: Is the performance impact prohibitive to add this reflective check for the existence of a static field when compiling 0-arg calls to static methods or static fields? It would be a bigger change (I think) but it might alternately be possible to do this check only in the case of a failure.
Rich Hickey made changes -
Approval Screened [ 10004 ] Incomplete [ 10006 ]
Alex Miller made changes -
Attachment clj-1130-v3.diff [ 12512 ]
Alex Miller made changes -
Description Invoking a static method with 0 parameters yields a NoSuchFieldException:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

*Cause:* This particular path in the Compiler covers both static field access and 0 argument static method invocation and in this case results in a confusing exception.

*Patch:* clj-1130-v2.diff
*Patch with whitespace differences ignored, intended only for review purposes, not for committing:* clj-1130-v2-ignore-ws.diff

*Approach:* The guess that the form is trying to access a static field is still done the same as before. However, with the patch it will now check for a field with the specified name, and if there is none, the compiler will assume that the user is really trying to invoke a static method.

The error message for attempting to call a static method now gives more details about the erroneous attempt, including the class name and that there is no such method that takes <n> arguments, where <n> is the number of arguments in the attempted method call.

After patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 0 args, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 3 args, compiling:(NO_SOURCE_PATH:2:1)
{code}

*Screened by:* Alex Miller. Question: Is the performance impact prohibitive to add this reflective check for the existence of a static field when compiling 0-arg calls to static methods or static fields? It would be a bigger change (I think) but it might alternately be possible to do this check only in the case of a failure.
Incorrectly invoking a static method with 0 parameters yields a NoSuchFieldException:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

Incorrectly invoking an instance method with 0 parameters yields a message about fields as well:

{code}
user=> (.setTime (java.util.Date.))
IllegalArgumentException No matching field found: setTime for class java.util.Date clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

*Cause:* The decision about whether to check for field access is done based on the arity of the dot invocation so the call to a field and a 0-arg method invocation are conflated.

*Patch:* clj-1130-v3.diff

*Approach:* Instead of checking field/method based on the arity of the dot invocation, do a check for a field of that name. This avoids going down field-checking paths for 0-arity method calls and yields a better exception for those cases. Error message was improved to list class name and the arity

After patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 0 args, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 3 args, compiling:(NO_SOURCE_PATH:2:1)
user=> (.setTime (java.util.Date.))
IllegalArgumentException No matching method found: setTime taking 0 args for class java.util.Date clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:53)
{code}

*Screened by:*
Summary Invoking a static method with the wrong number of arguments results in a NoSuchFieldException, rather than a proper message that the arguments could not be matched to the method Invoking an n-arity method with 0 args results in a field-related exception
Alex Miller made changes -
Approval Incomplete [ 10006 ] Vetted [ 10003 ]
Stuart Sierra made changes -
Approval Vetted [ 10003 ] Screened [ 10004 ]
Description Incorrectly invoking a static method with 0 parameters yields a NoSuchFieldException:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

Incorrectly invoking an instance method with 0 parameters yields a message about fields as well:

{code}
user=> (.setTime (java.util.Date.))
IllegalArgumentException No matching field found: setTime for class java.util.Date clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

*Cause:* The decision about whether to check for field access is done based on the arity of the dot invocation so the call to a field and a 0-arg method invocation are conflated.

*Patch:* clj-1130-v3.diff

*Approach:* Instead of checking field/method based on the arity of the dot invocation, do a check for a field of that name. This avoids going down field-checking paths for 0-arity method calls and yields a better exception for those cases. Error message was improved to list class name and the arity

After patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 0 args, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 3 args, compiling:(NO_SOURCE_PATH:2:1)
user=> (.setTime (java.util.Date.))
IllegalArgumentException No matching method found: setTime taking 0 args for class java.util.Date clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:53)
{code}

*Screened by:*
Incorrectly invoking a static method with 0 parameters yields a NoSuchFieldException:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

Incorrectly invoking an instance method with 0 parameters yields a message about fields as well:

{code}
user=> (.setTime (java.util.Date.))
IllegalArgumentException No matching field found: setTime for class java.util.Date clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

*Cause:* The decision about whether to check for field access is done based on the arity of the dot invocation so the call to a field and a 0-arg method invocation are conflated.

*Patch:* clj-1130-v3.diff

*Approach:* Instead of checking field/method based on the arity of the dot invocation, do a check for a field of that name. This avoids going down field-checking paths for 0-arity method calls and yields a better exception for those cases. Error message was improved to list class name and the arity

After patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 0 args, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 3 args, compiling:(NO_SOURCE_PATH:2:1)
user=> (.setTime (java.util.Date.))
IllegalArgumentException No matching method found: setTime taking 0 args for class java.util.Date clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:53)
{code}

*Screened by:* Stuart Sierra
Rich Hickey made changes -
Approval Screened [ 10004 ] Incomplete [ 10006 ]
Fix Version/s Release 1.6 [ 10157 ]
Stuart Halloway made changes -
Assignee Stuart Halloway [ stu ]
Stuart Halloway made changes -
Issue Type Defect [ 1 ] Enhancement [ 4 ]
Stuart Halloway made changes -
Approval Incomplete [ 10006 ] Vetted [ 10003 ]
Description Incorrectly invoking a static method with 0 parameters yields a NoSuchFieldException:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

Incorrectly invoking an instance method with 0 parameters yields a message about fields as well:

{code}
user=> (.setTime (java.util.Date.))
IllegalArgumentException No matching field found: setTime for class java.util.Date clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

*Cause:* The decision about whether to check for field access is done based on the arity of the dot invocation so the call to a field and a 0-arg method invocation are conflated.

*Patch:* clj-1130-v3.diff

*Approach:* Instead of checking field/method based on the arity of the dot invocation, do a check for a field of that name. This avoids going down field-checking paths for 0-arity method calls and yields a better exception for those cases. Error message was improved to list class name and the arity

After patch:

{code}
user=> (Long/parseLong)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 0 args, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: Class java.lang.Long has no method parseLong taking 3 args, compiling:(NO_SOURCE_PATH:2:1)
user=> (.setTime (java.util.Date.))
IllegalArgumentException No matching method found: setTime taking 0 args for class java.util.Date clojure.lang.Reflector.invokeMatchingMethod (Reflector.java:53)
{code}

*Screened by:* Stuart Sierra
Original motivation: Incorrectly invoking a static method with 0 parameters yields a NoSuchFieldException:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

Incorrectly invoking an instance method with 0 parameters yields a message about fields as well:

{code}
user=> (.setTime (java.util.Date.))
IllegalArgumentException No matching field found: setTime for class java.util.Date clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

*Patch:* clj-1130-v4.diff

*Approach:* Primum non nocere. Error reporting enhanced at the site the errors happen, compiler logic unchanged.
Summary Invoking an n-arity method with 0 args results in a field-related exception when unable to match a method, report arity caller was looking for
Stuart Halloway made changes -
Attachment clj-1130-v4.diff [ 12735 ]
Andy Fingerhut made changes -
Attachment clj-1130-v5.diff [ 12736 ]
Alex Miller made changes -
Description Original motivation: Incorrectly invoking a static method with 0 parameters yields a NoSuchFieldException:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

Incorrectly invoking an instance method with 0 parameters yields a message about fields as well:

{code}
user=> (.setTime (java.util.Date.))
IllegalArgumentException No matching field found: setTime for class java.util.Date clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

*Patch:* clj-1130-v4.diff

*Approach:* Primum non nocere. Error reporting enhanced at the site the errors happen, compiler logic unchanged.
Original motivation: Incorrectly invoking a static method with 0 parameters yields a NoSuchFieldException:

{code}
user=> (Long/parseLong)
CompilerException java.lang.NoSuchFieldException: parseLong, compiling:(NO_SOURCE_PATH:1:1)
user=> (Long/parseLong "5" 10 3)
CompilerException java.lang.IllegalArgumentException: No matching method: parseLong, compiling:(NO_SOURCE_PATH:2:1)
{code}

Incorrectly invoking an instance method with 0 parameters yields a message about fields as well:

{code}
user=> (.setTime (java.util.Date.))
IllegalArgumentException No matching field found: setTime for class java.util.Date clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

*Patch:* clj-1130-v5.diff

*Approach:* Primum non nocere. Error reporting enhanced at the site the errors happen, compiler logic unchanged.
Alex Miller made changes -
Priority Minor [ 4 ] Major [ 3 ]

People

Vote (1)
Watch (2)

Dates

  • Created:
    Updated: