Clojure

transient blows up when passed a vector created by subvec

Details

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

Description

Subvectors created with subvec from a PersistentVector cannot be made transient:

user=> (transient (subvec [1 2 3 4] 2))
ClassCastException clojure.lang.APersistentVector$SubVector cannot be cast to clojure.lang.IEditableCollection  clojure.core/transient (core.clj:2864)

Cause: APersistentVector$SubVector does not implement IEditableCollection

Patch: CLJ-787-p1.patch

Approach: Create a TransientSubVector based on an underlying TransientVector.

Two assumptions:

  • It's okay for TransientSubVector to delegate the ensureEditable functionality to the underlying TransientVector (sometimes explicitly, sometimes implicitly) - calling ensureEditable explicitly also requires that the field for the underlying vector be the concrete TransientVector type rather than the ITransientVector interface.
  • When an operation that would throw an exception on a PersistentVector happens from the wrong thread (or after persistent!), we throw that exception rather than the IllegalAccessError that transients throw when accessed inappropriately.

Activity

Stuart Sierra made changes -
Field Original Value New Value
Fix Version/s Backlog [ 10035 ]
Affects Version/s Backlog [ 10035 ]
Affects Version/s Release.Next [ 10038 ]
Approval Vetted
Rich Hickey made changes -
Fix Version/s Backlog [ 10035 ]
Fix Version/s Release 1.6 [ 10157 ]
Gary Fredericks made changes -
Attachment CLJ-787-p1.patch [ 12013 ]
Andy Fingerhut made changes -
Patch Code and Test [ 10002 ]
Alex Miller made changes -
Description Subvectors created with subvec from a PersistentVector cannot be made transient:

{code}
user=> (transient (subvec [1 2 3 4] 2))
ClassCastException clojure.lang.APersistentVector$SubVector cannot be cast to clojure.lang.IEditableCollection clojure.core/transient (core.clj:2864)
{code}

Subvectors created with subvec from a PersistentVector cannot be made transient:

{code}
user=> (transient (subvec [1 2 3 4] 2))
ClassCastException clojure.lang.APersistentVector$SubVector cannot be cast to clojure.lang.IEditableCollection clojure.core/transient (core.clj:2864)
{code}

*Cause:* {{APersistentVector$SubVector}} does not implement {{IEditableCollection}}

*Patch:* {{CLJ-787-p1.patch}}

*Approach:* Create a {{TransientSubVector}} based on an underlying {{TransientVector}}.

Two assumptions:
* It's okay for {{TransientSubVector}} to delegate the {{ensureEditable}} functionality to the underlying {{TransientVector}} (sometimes explicitly, sometimes implicitly) - calling {{ensureEditable}} explicitly also requires that the field for the underlying vector be the concrete {{TransientVector}} type rather than the {{ITransientVector}} interface.
* When an operation that would throw an exception on a {{PersistentVector}} happens from the wrong thread (or after persistent!), we throw that exception rather than the {{IllegalAccessError}} that transients throw when accessed inappropriately.
Alex Miller made changes -
Priority Minor [ 4 ] Major [ 3 ]
Alex Miller made changes -
Description Subvectors created with subvec from a PersistentVector cannot be made transient:

{code}
user=> (transient (subvec [1 2 3 4] 2))
ClassCastException clojure.lang.APersistentVector$SubVector cannot be cast to clojure.lang.IEditableCollection clojure.core/transient (core.clj:2864)
{code}

*Cause:* {{APersistentVector$SubVector}} does not implement {{IEditableCollection}}

*Patch:* {{CLJ-787-p1.patch}}

*Approach:* Create a {{TransientSubVector}} based on an underlying {{TransientVector}}.

Two assumptions:
* It's okay for {{TransientSubVector}} to delegate the {{ensureEditable}} functionality to the underlying {{TransientVector}} (sometimes explicitly, sometimes implicitly) - calling {{ensureEditable}} explicitly also requires that the field for the underlying vector be the concrete {{TransientVector}} type rather than the {{ITransientVector}} interface.
* When an operation that would throw an exception on a {{PersistentVector}} happens from the wrong thread (or after persistent!), we throw that exception rather than the {{IllegalAccessError}} that transients throw when accessed inappropriately.
Subvectors created with subvec from a PersistentVector cannot be made transient:

{code}
user=> (transient (subvec [1 2 3 4] 2))
ClassCastException clojure.lang.APersistentVector$SubVector cannot be cast to clojure.lang.IEditableCollection clojure.core/transient (core.clj:2864)
{code}

*Cause:* {{APersistentVector$SubVector}} does not implement {{IEditableCollection}}

*Patch:* CLJ-787-p1.patch

*Approach:* Create a {{TransientSubVector}} based on an underlying {{TransientVector}}.

Two assumptions:
* It's okay for {{TransientSubVector}} to delegate the {{ensureEditable}} functionality to the underlying {{TransientVector}} (sometimes explicitly, sometimes implicitly) - calling {{ensureEditable}} explicitly also requires that the field for the underlying vector be the concrete {{TransientVector}} type rather than the {{ITransientVector}} interface.
* When an operation that would throw an exception on a {{PersistentVector}} happens from the wrong thread (or after persistent!), we throw that exception rather than the {{IllegalAccessError}} that transients throw when accessed inappropriately.
Alex Miller made changes -
Approval Vetted [ 10003 ] Incomplete [ 10006 ]
Alex Miller made changes -
Approval Incomplete [ 10006 ] Vetted [ 10003 ]
Affects Version/s Backlog [ 10035 ]
Fix Version/s Release 1.6 [ 10157 ]
Rich Hickey made changes -
Fix Version/s Release 1.7 [ 10250 ]

People

Vote (1)
Watch (4)

Dates

  • Created:
    Updated: