Clojure

protocol fns with dashes may get compiled into property access when used higher order

Details

  • Type: Defect Defect
  • Status: Closed Closed
  • Priority: Major Major
  • Resolution: Completed
  • Affects Version/s: Release 1.5
  • Fix Version/s: Release 1.6
  • Component/s: None
  • Labels:
    None
  • Patch:
    Code and Test
  • Approval:
    Ok

Description

Problem: Protocol functions with leading hyphens may be incorrectly compiled into field accesses.

Demonstration:

(defprotocol Foo (-foo [x]))

(deftype Bar [] Foo (-foo [_] "foo"))

(map -foo (repeatedly 3 ->Bar))
;; IllegalArgumentException No matching field found: foo for class user.Bar  
;; clojure.lang.Reflector.getInstanceField (Reflector.java:271)

Cause: This was caused by CLJ-872, dash property support.

Solution: Emit forms like (. foo (bar)) instead of (. foo bar), so that names starting with a - don't look like field accesses.

Patch: CLJ-1202.patch

Activity

David Nolen made changes -
Field Original Value New Value
Description {code}
user=> (defprotocol Foo (-foo [x]))
Foo
user=> (deftype Bar [] Foo (-foo [_] :baz))
user.Bar
user=> (map -foo [(Bar.)])
IllegalArgumentException No matching field found: foo for class user.Bar clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

I would have expected to see (:baz). The full stack is:

{code}
IllegalArgumentException No matching field found: foo for class user.Bar
clojure.lang.Reflector.getInstanceField (Reflector.java:271)
clojure.lang.Reflector.invokeNoArgInstanceMember (Reflector.java:300)
user/eval79/fn--80/G--71--82 (NO_SOURCE_FILE:11)
user/eval79/fn--80/G--70--85 (NO_SOURCE_FILE:11)
clojure.core/map/fn--4207 (core.clj:2485)
clojure.lang.LazySeq.sval (LazySeq.java:42)
clojure.lang.LazySeq.seq (LazySeq.java:60)
clojure.lang.RT.seq (RT.java:484)
clojure.core/seq (core.clj:133)
clojure.core/print-sequential (core_print.clj:46)
clojure.core/fn--5406 (core_print.clj:143)
clojure.lang.MultiFn.invoke (MultiFn.java:231)
nil
{code}

I suspect this is somehow related to the property access changes to make Clojure/ClojureScript compatible. I was in fact prepping core.logic for a unified code base and was adopting the ClojureScript protocol naming convention when I encountered this issue.
{code}
user=> (defprotocol Foo (-foo [x]))
Foo
user=> (deftype Bar [] Foo (-foo [_] :baz))
user.Bar
user=> (map -foo [(Bar.)])
IllegalArgumentException No matching field found: foo for class user.Bar
clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

I would have expected to see (:baz). The full stack is:

{code}
IllegalArgumentException No matching field found: foo for class user.Bar
clojure.lang.Reflector.getInstanceField (Reflector.java:271)
clojure.lang.Reflector.invokeNoArgInstanceMember (Reflector.java:300)
user/eval79/fn--80/G--71--82 (NO_SOURCE_FILE:11)
user/eval79/fn--80/G--70--85 (NO_SOURCE_FILE:11)
clojure.core/map/fn--4207 (core.clj:2485)
clojure.lang.LazySeq.sval (LazySeq.java:42)
clojure.lang.LazySeq.seq (LazySeq.java:60)
clojure.lang.RT.seq (RT.java:484)
clojure.core/seq (core.clj:133)
clojure.core/print-sequential (core_print.clj:46)
clojure.core/fn--5406 (core_print.clj:143)
clojure.lang.MultiFn.invoke (MultiFn.java:231)
nil
{code}

I suspect this is somehow related to the property access changes to make Clojure/ClojureScript compatible. I was in fact prepping core.logic for a unified code base and was adopting the ClojureScript protocol naming convention when I encountered this issue.
David Nolen made changes -
Description {code}
user=> (defprotocol Foo (-foo [x]))
Foo
user=> (deftype Bar [] Foo (-foo [_] :baz))
user.Bar
user=> (map -foo [(Bar.)])
IllegalArgumentException No matching field found: foo for class user.Bar
clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

I would have expected to see (:baz). The full stack is:

{code}
IllegalArgumentException No matching field found: foo for class user.Bar
clojure.lang.Reflector.getInstanceField (Reflector.java:271)
clojure.lang.Reflector.invokeNoArgInstanceMember (Reflector.java:300)
user/eval79/fn--80/G--71--82 (NO_SOURCE_FILE:11)
user/eval79/fn--80/G--70--85 (NO_SOURCE_FILE:11)
clojure.core/map/fn--4207 (core.clj:2485)
clojure.lang.LazySeq.sval (LazySeq.java:42)
clojure.lang.LazySeq.seq (LazySeq.java:60)
clojure.lang.RT.seq (RT.java:484)
clojure.core/seq (core.clj:133)
clojure.core/print-sequential (core_print.clj:46)
clojure.core/fn--5406 (core_print.clj:143)
clojure.lang.MultiFn.invoke (MultiFn.java:231)
nil
{code}

I suspect this is somehow related to the property access changes to make Clojure/ClojureScript compatible. I was in fact prepping core.logic for a unified code base and was adopting the ClojureScript protocol naming convention when I encountered this issue.
{code}
user=> (defprotocol Foo (-foo [x]))
Foo
user=> (deftype Bar [] Foo (-foo [_] :baz))
user.Bar
user=> (map -foo [(Bar.)])
IllegalArgumentException No matching field found: foo for class user.Bar
clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

I would have expected to see (:baz). The full stack is:

{code}
IllegalArgumentException No matching field found: foo for class user.Bar
clojure.lang.Reflector.getInstanceField (Reflector.java:271)
clojure.lang.Reflector.invokeNoArgInstanceMember (Reflector.java:300)
user/eval79/fn--80/G--71--82 (NO_SOURCE_FILE:11)
user/eval79/fn--80/G--70--85 (NO_SOURCE_FILE:11)
clojure.core/map/fn--4207 (core.clj:2485)
clojure.lang.LazySeq.sval (LazySeq.java:42)
clojure.lang.LazySeq.seq (LazySeq.java:60)
clojure.lang.RT.seq (RT.java:484)
clojure.core/seq (core.clj:133)
clojure.core/print-sequential (core_print.clj:46)
clojure.core/fn--5406 (core_print.clj:143)
clojure.lang.MultiFn.invoke (MultiFn.java:231)
nil
{code}

I suspect this is somehow related to the property access changes to make Clojure/ClojureScript compatible. I was in fact prepping core.logic for a unified code base and was adopting the ClojureScript protocol naming convention when I encountered this issue.

CLJ-872 added dash property support to Clojure.
Hide
Alan Malloy added a comment -

Attached patch fixes the issue, and adds regression test for it.

Show
Alan Malloy added a comment - Attached patch fixes the issue, and adds regression test for it.
Alan Malloy made changes -
Attachment CLJ-1202.patch [ 11962 ]
Andy Fingerhut made changes -
Patch Code and Test [ 10002 ]
Gabriel Horner made changes -
Approval Vetted [ 10003 ]
Fix Version/s Release 1.6 [ 10157 ]
Hide
Gabriel Horner added a comment -

Verified patch works

Show
Gabriel Horner added a comment - Verified patch works
Hide
Stuart Sierra added a comment -

Screened and cleaned up description.

Show
Stuart Sierra added a comment - Screened and cleaned up description.
Stuart Sierra made changes -
Approval Vetted [ 10003 ] Screened [ 10004 ]
Description {code}
user=> (defprotocol Foo (-foo [x]))
Foo
user=> (deftype Bar [] Foo (-foo [_] :baz))
user.Bar
user=> (map -foo [(Bar.)])
IllegalArgumentException No matching field found: foo for class user.Bar
clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

I would have expected to see (:baz). The full stack is:

{code}
IllegalArgumentException No matching field found: foo for class user.Bar
clojure.lang.Reflector.getInstanceField (Reflector.java:271)
clojure.lang.Reflector.invokeNoArgInstanceMember (Reflector.java:300)
user/eval79/fn--80/G--71--82 (NO_SOURCE_FILE:11)
user/eval79/fn--80/G--70--85 (NO_SOURCE_FILE:11)
clojure.core/map/fn--4207 (core.clj:2485)
clojure.lang.LazySeq.sval (LazySeq.java:42)
clojure.lang.LazySeq.seq (LazySeq.java:60)
clojure.lang.RT.seq (RT.java:484)
clojure.core/seq (core.clj:133)
clojure.core/print-sequential (core_print.clj:46)
clojure.core/fn--5406 (core_print.clj:143)
clojure.lang.MultiFn.invoke (MultiFn.java:231)
nil
{code}

I suspect this is somehow related to the property access changes to make Clojure/ClojureScript compatible. I was in fact prepping core.logic for a unified code base and was adopting the ClojureScript protocol naming convention when I encountered this issue.

CLJ-872 added dash property support to Clojure.
Problem: Protocol functions with leading hyphens may be incorrectly compiled into field accesses.

Demonstration:

{code}
(defprotocol Foo (-foo [x]))

(deftype Bar [] Foo (-foo [_] "foo"))

(map -foo (repeatedly 3 ->Bar))
;; IllegalArgumentException No matching field found: foo for class user.Bar
;; clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

This was caused by CLJ-872, dash property support.

Current patch CLJ-1202.patch fixes the problem and adds a test.
Hide
Alex Miller added a comment -

More cleansing.

Show
Alex Miller added a comment - More cleansing.
Alex Miller made changes -
Description Problem: Protocol functions with leading hyphens may be incorrectly compiled into field accesses.

Demonstration:

{code}
(defprotocol Foo (-foo [x]))

(deftype Bar [] Foo (-foo [_] "foo"))

(map -foo (repeatedly 3 ->Bar))
;; IllegalArgumentException No matching field found: foo for class user.Bar
;; clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

This was caused by CLJ-872, dash property support.

Current patch CLJ-1202.patch fixes the problem and adds a test.
Problem: Protocol functions with leading hyphens may be incorrectly compiled into field accesses.

Demonstration:

{code}
(defprotocol Foo (-foo [x]))

(deftype Bar [] Foo (-foo [_] "foo"))

(map -foo (repeatedly 3 ->Bar))
;; IllegalArgumentException No matching field found: foo for class user.Bar
;; clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

Cause: This was caused by CLJ-872, dash property support.

Solution: Emit forms like (. foo (bar)) instead of (. foo bar), so that names starting with a - don't look like field accesses.

Patch: CLJ-1202.patch
Alex Miller made changes -
Description Problem: Protocol functions with leading hyphens may be incorrectly compiled into field accesses.

Demonstration:

{code}
(defprotocol Foo (-foo [x]))

(deftype Bar [] Foo (-foo [_] "foo"))

(map -foo (repeatedly 3 ->Bar))
;; IllegalArgumentException No matching field found: foo for class user.Bar
;; clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

Cause: This was caused by CLJ-872, dash property support.

Solution: Emit forms like (. foo (bar)) instead of (. foo bar), so that names starting with a - don't look like field accesses.

Patch: CLJ-1202.patch
*Problem:* Protocol functions with leading hyphens may be incorrectly compiled into field accesses.

*Demonstration:*

{code}
(defprotocol Foo (-foo [x]))

(deftype Bar [] Foo (-foo [_] "foo"))

(map -foo (repeatedly 3 ->Bar))
;; IllegalArgumentException No matching field found: foo for class user.Bar
;; clojure.lang.Reflector.getInstanceField (Reflector.java:271)
{code}

*Cause:* This was caused by CLJ-872, dash property support.

*Solution:* Emit forms like (. foo (bar)) instead of (. foo bar), so that names starting with a - don't look like field accesses.

*Patch:* CLJ-1202.patch
Rich Hickey made changes -
Approval Screened [ 10004 ] Ok [ 10007 ]
Stuart Halloway made changes -
Resolution Completed [ 1 ]
Status Open [ 1 ] Closed [ 6 ]

People

Vote (0)
Watch (4)

Dates

  • Created:
    Updated:
    Resolved: