Skip to content
/ cell Public

A replacement of std::cell::RefCell adding advanced support for mapping borrows.

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT
Notifications You must be signed in to change notification settings

d-e-s-o/cell

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

32 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

pipeline crates.io Docs rustc

cell

cell is a crate providing a revised RefCell implementation with additional mapping capabilities. It can be used as a drop-in replacement for std::cell::RefCell where this additional functionality is required.

Warning:


cell was found to contain a subtle unsafety, a work around for which is not known with current versions of Rust. Usage of the crate is therefore discouraged.


The Problem

A borrowed RefCell is represented as a Ref. Such a Ref contains a reference to the data contained in the RefCell. To extend the borrow to a different member in the original data, the map method can be used. Using this method a new Ref object can be created that contains a reference to a member in the borrowed data.

While having a direct reference to such a data member is appropriate in many cases, there are some where this is insufficient, and an actual object that contains such a reference is required.

Example

The most prominent example is an iterator. While an iterator internally keeps a reference to the object being iterated over, it is more than just a reference to it: it contains state about the progress of the iteration.

If such an iterator is to be exposed for an object contained in a RefCell that is currently borrowed, the Ref::map function is insufficient:

struct RefStrings(RefCell<Vec<String>>);

impl RefStrings {
    fn iter(&self) -> Ref<Iter<String>> {
        Ref::map(self.0.borrow(), |x| x.iter())
    }
}
error[E0308]: mismatched types
 |  Ref::map(self.0.borrow(), |x| x.iter())
 |                                ^^^^^^^^ expected reference, found struct `std::slice::Iter`
 |
 = note: expected type `&_`
            found type `std::slice::Iter<'_, std::string::String>`

(Note that required lifetimes have been elided in the example for brevity)

A Solution

This crate provides alternative RefCell and Ref implementations that solve this problem by introduction of another mapping method: map_val. This method returns a RefVal object. RefVal is a new type that is similar to Ref but, instead of embedding a reference to its T (a type parameter), it embeds a value of it. T in turn would contain the actual reference to the borrowed object.

In the above example the only changes that need to happen are the replacement of std::cell::RefCell with cell::RefCell, that of std::cell::Ref with cell::Ref, and the usage of Ref::map instead of Ref::map_val.

--- test.rs
+++ test.rs
@@ -1,13 +1,14 @@
-use std::cell::Ref;
-use std::cell::RefCell;
+use cell::Ref;
+use cell::RefCell;
+use cell::RefVal;
 use std::slice::Iter;


 struct RefStrings(RefCell<Vec<String>>);

 impl RefStrings {
-    fn iter<'t, 's: 't>(&'s self) -> Ref<'t, Iter<String>> {
-        Ref::map(self.0.borrow(), |x| x.iter())
+    fn iter<'t, 's: 't>(&'s self) -> RefVal<'t, Iter<String>> {
+        Ref::map_val(self.0.borrow(), |x| x.iter())
     }
 }

Similar functionality exists for mutable borrow with RefValMut.

Alternative Implementations

The possibility of providing this functionality by means of a trait has been investigated but no viable solution has been identified. The main problem stems from the fact that we require access to Ref internals in order to provide this functionality. Such a trait would alleviate the need for providing alternative RefCell and Ref implementations.

No other solutions for this problem have been found, but the discussion around possible alternatives is still open as part of Rust issue #54776.

About

A replacement of std::cell::RefCell adding advanced support for mapping borrows.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •  

Languages