-
-
Notifications
You must be signed in to change notification settings - Fork 14.1k
libs: Add borrow module, deprecate _equiv and friends #18910
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
4ab2235
5eec666
80a2867
7213de1
ff88510
9f1217d
46be8eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
Following [the collections reform RFC](rust-lang/rfcs#235), this commit adds a new `borrow` module to libcore. The module contains traits for borrowing data (`BorrowFrom` and `BorrowFromMut`), generalized cloning (`ToOwned`), and a clone-on-write smartpointer (`Cow`).
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,126 @@ | ||
| // Copyright 2014 The Rust Project Developers. See the COPYRIGHT | ||
| // file at the top-level directory of this distribution and at | ||
| // http://rust-lang.org/COPYRIGHT. | ||
| // | ||
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | ||
| // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | ||
| // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | ||
| // option. This file may not be copied, modified, or distributed | ||
| // except according to those terms. | ||
|
|
||
| //! A module for working with borrowed data. | ||
| //! | ||
| //! # The `BorrowFrom` traits | ||
| //! | ||
| //! In general, there may be several ways to "borrow" a piece of data. The | ||
| //! typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T` | ||
| //! (a mutable borrow). But types like `Vec<T>` provide additional kinds of | ||
| //! borrows: the borrowed slices `&[T]` and `&mut [T]`. | ||
| //! | ||
| //! When writing generic code, it is often desirable to abstract over all ways | ||
| //! of borrowing data from a given type. That is the role of the `BorrowFrom` | ||
| //! trait: if `T: BorrowFrom<U>`, then `&T` can be borrowed from `&U`. A given | ||
| //! type can be borrowed as multiple different types. In particular, `Vec<T>: | ||
| //! BorrowFrom<Vec<T>>` and `[T]: BorrowFrom<Vec<T>>`. | ||
| //! | ||
| //! # The `ToOwned` trait | ||
| //! | ||
| //! Some types make it possible to go from borrowed to owned, usually by | ||
| //! implementing the `Clone` trait. But `Clone` works only for going from `&T` | ||
| //! to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data | ||
| //! from any borrow of a given type. | ||
| //! | ||
| //! # The `Cow` (clone-on-write) type | ||
| //! | ||
| //! The type `Cow` is a smart pointer providing clone-on-write functionality: it | ||
| //! can enclose and provide immutable access to borrowed data, and clone the | ||
| //! data lazily when mutation or ownership is required. The type is designed to | ||
| //! work with general borrowed data via the `BorrowFrom` trait. | ||
| //! | ||
| //! `Cow` implements both `Deref` and `DerefMut`, which means that you can call | ||
| //! methods directly on the data it encloses. The first time a mutable reference | ||
| //! is required, the data will be cloned (via `to_owned`) if it is not | ||
| //! already owned. | ||
|
|
||
| #![unstable = "recently added as part of collections reform"] | ||
|
|
||
| use clone::Clone; | ||
| use kinds::Sized; | ||
| use ops::Deref; | ||
|
|
||
| /// A trait for borrowing data. | ||
| pub trait BorrowFrom<Sized? Owned> for Sized? { | ||
| /// Immutably borrow from an owned value. | ||
| fn borrow_from(owned: &Owned) -> &Self; | ||
| } | ||
|
|
||
| /// A trait for mutably borrowing data. | ||
| pub trait BorrowFromMut<Sized? Owned> for Sized? : BorrowFrom<Owned> { | ||
| /// Mutably borrow from an owned value. | ||
| fn borrow_from_mut(owned: &mut Owned) -> &mut Self; | ||
| } | ||
|
|
||
| impl<Sized? T> BorrowFrom<T> for T { | ||
| fn borrow_from(owned: &T) -> &T { owned } | ||
| } | ||
|
|
||
| impl<Sized? T> BorrowFromMut<T> for T { | ||
| fn borrow_from_mut(owned: &mut T) -> &mut T { owned } | ||
| } | ||
|
|
||
| impl BorrowFrom<&'static str> for str { | ||
| fn borrow_from<'a>(owned: &'a &'static str) -> &'a str { &**owned } | ||
| } | ||
|
|
||
| /// A generalization of Clone to borrowed data. | ||
| pub trait ToOwned<Owned> for Sized?: BorrowFrom<Owned> { | ||
| /// Create owned data from borrowed data, usually by copying. | ||
| fn to_owned(&self) -> Owned; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why I think that Example: http://is.gd/YORUei I didn't tried to modify this pull request with this change, so maybe there is problem in Cow with this change. |
||
| } | ||
|
|
||
| impl<T> ToOwned<T> for T where T: Clone { | ||
| fn to_owned(&self) -> T { self.clone() } | ||
| } | ||
|
|
||
| /// A clone-on-write smart pointer. | ||
| pub enum Cow<'a, T, B: 'a> where B: ToOwned<T> { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we want people to be able to match on the internals of this?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I debated making this a newtype. That's probably the more conservative thing to do, but then we'd need to separately expose constructors. Either way is fine by me.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm... unsure. I feel like newtyping is "the right thing", but I dunno. It's unstable so I think we can leave it like this for now, and revisit this for stabilization. |
||
| /// Borrowed data. | ||
| Borrowed(&'a B), | ||
|
|
||
| /// Owned data. | ||
| Owned(T) | ||
| } | ||
|
|
||
| impl<'a, T, B> Cow<'a, T, B> where B: ToOwned<T> { | ||
| /// Acquire a mutable reference to the owned form of the data. | ||
| /// | ||
| /// Copies the data if it is not already owned. | ||
| pub fn to_mut(&mut self) -> &mut T { | ||
| match *self { | ||
| Borrowed(borrowed) => { | ||
| *self = Owned(borrowed.to_owned()); | ||
| self.to_mut() | ||
| } | ||
| Owned(ref mut owned) => owned | ||
| } | ||
| } | ||
|
|
||
| /// Extract the owned data. | ||
| /// | ||
| /// Copies the data if it is not already owned. | ||
| pub fn into_owned(self) -> T { | ||
| match self { | ||
| Borrowed(borrowed) => borrowed.to_owned(), | ||
| Owned(owned) => owned | ||
| } | ||
| } | ||
| } | ||
|
|
||
| impl<'a, T, B> Deref<B> for Cow<'a, T, B> where B: ToOwned<T> { | ||
| fn deref(&self) -> &B { | ||
| match *self { | ||
| Borrowed(borrowed) => borrowed, | ||
| Owned(ref owned) => BorrowFrom::borrow_from(owned) | ||
| } | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should these be in vec.rs? Genuinely unsure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the
BorrowFromandBorrowFromMuttraits are in libcore, they cannot implement forVecthere. Sincce these implementations can't be anywhere else, surely this is the right place?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They could be in the
vecmodule inlibcollections. I put them here because they are being applied to the slice type, and I feel like putting impls in the module defining theirSelftype is a good default.