From a99e698628cbd396c8100ef776d10ac61d911847 Mon Sep 17 00:00:00 2001 From: Aaron Turon Date: Wed, 11 Feb 2015 23:16:32 -0800 Subject: [PATCH] Stabilize std::borrow This commit stabilizes `std::borrow`, making the following modifications to catch up the API with language changes: * It renames `BorrowFrom` to `Borrow`, as was originally intended (but blocked for technical reasons), and reorders the parameters accordingly. * It moves the type parameter of `ToOwned` to an associated type. This is somewhat less flexible, in that each borrowed type must have a unique owned type, but leads to a significant simplification for `Cow`. Flexibility can be regained by using newtyped slices, which is advisable for other reasons anyway. * It removes the owned type parameter from `Cow`, making the type much less verbose. * Deprecates the `is_owned` and `is_borrowed` predicates in favor of direct matching. The above API changes are relatively minor; the basic functionality remains the same, and essentially the whole module is now marked `#[stable]`. [breaking-change] --- src/liballoc/arc.rs | 7 - src/liballoc/rc.rs | 7 - src/libcollections/borrow.rs | 306 +++++++++++++++++ src/libcollections/borrow_stage0.rs | 313 ++++++++++++++++++ src/libcollections/btree/map.rs | 14 +- src/libcollections/btree/node.rs | 9 +- src/libcollections/btree/set.rs | 6 +- src/libcollections/lib.rs | 7 + src/libcollections/slice.rs | 19 +- src/libcollections/str.rs | 13 +- src/libcollections/string.rs | 35 +- src/libcollections/vec.rs | 42 +-- src/libcore/borrow.rs | 265 --------------- src/libcore/hash/mod.rs | 10 - src/libcore/lib.rs | 1 - src/libgraphviz/lib.rs | 6 +- src/librustc/middle/ty.rs | 8 +- src/libstd/collections/hash/map.rs | 26 +- src/libstd/collections/hash/set.rs | 6 +- src/libstd/ffi/os_str.rs | 9 +- src/libstd/lib.rs | 2 +- src/libstd/path.rs | 18 +- src/libsyntax/util/interner.rs | 12 +- .../compile-fail/ufcs-qpath-missing-params.rs | 3 +- src/test/run-make/save-analysis/foo.rs | 2 +- src/test/run-pass/const-polymorphic-paths.rs | 4 +- src/test/run-pass/send_str_hashmap.rs | 2 +- src/test/run-pass/send_str_treemap.rs | 2 +- src/test/run-pass/traits-issue-22019.rs | 6 +- 29 files changed, 753 insertions(+), 407 deletions(-) create mode 100644 src/libcollections/borrow.rs create mode 100644 src/libcollections/borrow_stage0.rs delete mode 100644 src/libcore/borrow.rs diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 3830d7fe295..a8d6c3ff2b0 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -73,7 +73,6 @@ use core::prelude::*; use core::atomic; use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst}; -use core::borrow::BorrowFrom; use core::fmt; use core::cmp::{Ordering}; use core::default::Default; @@ -244,12 +243,6 @@ impl Clone for Arc { } } -impl BorrowFrom> for T { - fn borrow_from(owned: &Arc) -> &T { - &**owned - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Deref for Arc { type Target = T; diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index f361c36ec8f..3e52886280b 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -144,7 +144,6 @@ #![stable(feature = "rust1", since = "1.0.0")] -use core::borrow::BorrowFrom; use core::cell::Cell; use core::clone::Clone; use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering}; @@ -349,12 +348,6 @@ impl Rc { } } -impl BorrowFrom> for T { - fn borrow_from(owned: &Rc) -> &T { - &**owned - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Deref for Rc { type Target = T; diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs new file mode 100644 index 00000000000..62e6f347df3 --- /dev/null +++ b/src/libcollections/borrow.rs @@ -0,0 +1,306 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A module for working with borrowed data. + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::clone::Clone; +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::hash::{Hash, Hasher}; +use core::marker::Sized; +use core::ops::Deref; +use core::option::Option; + +use fmt; +use alloc::{rc, arc}; + +use self::Cow::*; + +/// A trait for borrowing data. +/// +/// 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` 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 `Borrow` +/// trait: if `T: Borrow`, then `&U` can be borrowed from `&T`. A given +/// type can be borrowed as multiple different types. In particular, `Vec: +/// Borrow>` and `Vec: Borrow<[T]>`. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Borrow { + /// Immutably borrow from an owned value. + #[stable(feature = "rust1", since = "1.0.0")] + fn borrow(&self) -> &Borrowed; +} + +/// A trait for mutably borrowing data. +/// +/// Similar to `Borrow`, but for mutable borrows. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait BorrowMut : Borrow { + /// Mutably borrow from an owned value. + #[stable(feature = "rust1", since = "1.0.0")] + fn borrow_mut(&mut self) -> &mut Borrowed; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow for T { + fn borrow(&self) -> &T { self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BorrowMut for T { + fn borrow_mut(&mut self) -> &mut T { self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> Borrow for &'a T { + fn borrow(&self) -> &T { &**self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> Borrow for &'a mut T { + fn borrow(&self) -> &T { &**self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> BorrowMut for &'a mut T { + fn borrow_mut(&mut self) -> &mut T { &mut **self } +} + +impl Borrow for rc::Rc { + fn borrow(&self) -> &T { &**self } +} + +impl Borrow for arc::Arc { + fn borrow(&self) -> &T { &**self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Borrow for Cow<'a, B> where B: ToOwned, ::Owned: 'a { + fn borrow(&self) -> &B { + &**self + } +} + +/// A generalization of Clone to borrowed data. +/// +/// 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. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait ToOwned { + #[stable(feature = "rust1", since = "1.0.0")] + type Owned: Borrow; + + /// Create owned data from borrowed data, usually by copying. + #[stable(feature = "rust1", since = "1.0.0")] + fn to_owned(&self) -> Self::Owned; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for T where T: Clone { + type Owned = T; + fn to_owned(&self) -> T { self.clone() } +} + +/// A clone-on-write smart pointer. +/// +/// 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 `Borrow` trait. +/// +/// `Cow` implements both `Deref`, which means that you can call +/// non-mutating methods directly on the data it encloses. If mutation +/// is desired, `to_mut` will obtain a mutable references to an owned +/// value, cloning if necessary. +/// +/// # Example +/// +/// ```rust +/// use std::borrow::Cow; +/// +/// fn abs_all(input: &mut Cow<[int]>) { +/// for i in 0..input.len() { +/// let v = input[i]; +/// if v < 0 { +/// // clones into a vector the first time (if not already owned) +/// input.to_mut()[i] = -v; +/// } +/// } +/// } +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned { + /// Borrowed data. + #[stable(feature = "rust1", since = "1.0.0")] + Borrowed(&'a B), + + /// Owned data. + #[stable(feature = "rust1", since = "1.0.0")] + Owned(::Owned) +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned { + fn clone(&self) -> Cow<'a, B> { + match *self { + Borrowed(b) => Borrowed(b), + Owned(ref o) => { + let b: &B = o.borrow(); + Owned(b.to_owned()) + }, + } + } +} + +impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { + /// Acquire a mutable reference to the owned form of the data. + /// + /// Copies the data if it is not already owned. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_mut(&mut self) -> &mut ::Owned { + 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. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_owned(self) -> ::Owned { + match self { + Borrowed(borrowed) => borrowed.to_owned(), + Owned(owned) => owned + } + } + + /// Returns true if this `Cow` wraps a borrowed value + #[deprecated(since = "1.0.0", reason = "match on the enum instead")] + #[unstable(feature = "std_misc")] + pub fn is_borrowed(&self) -> bool { + match *self { + Borrowed(_) => true, + _ => false, + } + } + + /// Returns true if this `Cow` wraps an owned value + #[deprecated(since = "1.0.0", reason = "match on the enum instead")] + #[unstable(feature = "std_misc")] + pub fn is_owned(&self) -> bool { + match *self { + Owned(_) => true, + _ => false, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned { + type Target = B; + + fn deref(&self) -> &B { + match *self { + Borrowed(borrowed) => borrowed, + Owned(ref owned) => owned.borrow() + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned { + #[inline] + fn cmp(&self, other: &Cow<'a, B>) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq> for Cow<'a, B> where + B: PartialEq + ToOwned, C: ToOwned, +{ + #[inline] + fn eq(&self, other: &Cow<'b, C>) -> bool { + PartialEq::eq(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned, +{ + #[inline] + fn partial_cmp(&self, other: &Cow<'a, B>) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where + B: fmt::Debug + ToOwned, + ::Owned: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Debug::fmt(b, f), + Owned(ref o) => fmt::Debug::fmt(o, f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where + B: fmt::Display + ToOwned, + ::Owned: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Display::fmt(b, f), + Owned(ref o) => fmt::Display::fmt(o, f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized, S: Hasher> Hash for Cow<'a, B> where B: Hash + ToOwned +{ + #[inline] + fn hash(&self, state: &mut S) { + Hash::hash(&**self, state) + } +} + +/// Trait for moving into a `Cow` +#[stable(feature = "rust1", since = "1.0.0")] +pub trait IntoCow<'a, B: ?Sized> where B: ToOwned { + /// Moves `self` into `Cow` + #[stable(feature = "rust1", since = "1.0.0")] + fn into_cow(self) -> Cow<'a, B>; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { + fn into_cow(self) -> Cow<'a, B> { + self + } +} diff --git a/src/libcollections/borrow_stage0.rs b/src/libcollections/borrow_stage0.rs new file mode 100644 index 00000000000..c1d74b16ce6 --- /dev/null +++ b/src/libcollections/borrow_stage0.rs @@ -0,0 +1,313 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A module for working with borrowed data. + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::clone::Clone; +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::hash::{Hash, Hasher}; +use core::marker::Sized; +use core::ops::Deref; +use core::option::Option; + +use fmt; +use alloc::{rc, arc}; + +use self::Cow::*; + +/// A trait for borrowing data. +/// +/// 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` 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 `Borrow` +/// trait: if `T: Borrow`, then `&U` can be borrowed from `&T`. A given +/// type can be borrowed as multiple different types. In particular, `Vec: +/// Borrow>` and `Vec: Borrow<[T]>`. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Borrow { + /// Immutably borrow from an owned value. + #[stable(feature = "rust1", since = "1.0.0")] + fn borrow(&self) -> &Borrowed; +} + +/// A trait for mutably borrowing data. +/// +/// Similar to `Borrow`, but for mutable borrows. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait BorrowMut : Borrow { + /// Mutably borrow from an owned value. + #[stable(feature = "rust1", since = "1.0.0")] + fn borrow_mut(&mut self) -> &mut Borrowed; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow for T { + fn borrow(&self) -> &T { self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BorrowMut for T { + fn borrow_mut(&mut self) -> &mut T { self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> Borrow for &'a T { + fn borrow(&self) -> &T { &**self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> Borrow for &'a mut T { + fn borrow(&self) -> &T { &**self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> BorrowMut for &'a mut T { + fn borrow_mut(&mut self) -> &mut T { &mut **self } +} + +impl Borrow for rc::Rc { + fn borrow(&self) -> &T { &**self } +} + +impl Borrow for arc::Arc { + fn borrow(&self) -> &T { &**self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Borrow for Cow<'a, B> where B: ToOwned, ::Owned: 'a { + fn borrow(&self) -> &B { + &**self + } +} + +/// A generalization of Clone to borrowed data. +/// +/// 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. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait ToOwned { + #[stable(feature = "rust1", since = "1.0.0")] + type Owned: Borrow; + + /// Create owned data from borrowed data, usually by copying. + #[stable(feature = "rust1", since = "1.0.0")] + fn to_owned(&self) -> Self::Owned; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for T where T: Clone { + type Owned = T; + fn to_owned(&self) -> T { self.clone() } +} + +/// A clone-on-write smart pointer. +/// +/// 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 `Borrow` trait. +/// +/// `Cow` implements both `Deref`, which means that you can call +/// non-mutating methods directly on the data it encloses. If mutation +/// is desired, `to_mut` will obtain a mutable references to an owned +/// value, cloning if necessary. +/// +/// # Example +/// +/// ```rust +/// use std::borrow::Cow; +/// +/// fn abs_all(input: &mut Cow<[int]>) { +/// for i in 0..input.len() { +/// let v = input[i]; +/// if v < 0 { +/// // clones into a vector the first time (if not already owned) +/// input.to_mut()[i] = -v; +/// } +/// } +/// } +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned { + /// Borrowed data. + #[stable(feature = "rust1", since = "1.0.0")] + Borrowed(&'a B), + + /// Owned data. + #[stable(feature = "rust1", since = "1.0.0")] + Owned(::Owned) +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned { + fn clone(&self) -> Cow<'a, B> { + match *self { + Borrowed(b) => Borrowed(b), + Owned(ref o) => { + let b: &B = o.borrow(); + Owned(b.to_owned()) + }, + } + } +} + +impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned, ::Owned: 'a { + /// Acquire a mutable reference to the owned form of the data. + /// + /// Copies the data if it is not already owned. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_mut(&mut self) -> &mut ::Owned where ::Owned: 'a { + 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. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_owned(self) -> ::Owned { + match self { + Borrowed(borrowed) => borrowed.to_owned(), + Owned(owned) => owned + } + } + + /// Returns true if this `Cow` wraps a borrowed value + #[deprecated(since = "1.0.0", reason = "match on the enum instead")] + #[unstable(feature = "std_misc")] + pub fn is_borrowed(&self) -> bool { + match *self { + Borrowed(_) => true, + _ => false, + } + } + + /// Returns true if this `Cow` wraps an owned value + #[deprecated(since = "1.0.0", reason = "match on the enum instead")] + #[unstable(feature = "std_misc")] + pub fn is_owned(&self) -> bool { + match *self { + Owned(_) => true, + _ => false, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Deref for Cow<'a, B> where + B: ToOwned, ::Owned: 'a +{ + type Target = B; + + fn deref(&self) -> &B { + match *self { + Borrowed(borrowed) => borrowed, + Owned(ref owned) => owned.borrow() + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned, ::Owned: 'a {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Ord for Cow<'a, B> where + B: Ord + ToOwned, ::Owned: 'a +{ + #[inline] + fn cmp(&self, other: &Cow<'a, B>) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq> for Cow<'a, B> where + B: PartialEq + ToOwned, C: ToOwned, + ::Owned: 'a, ::Owned: 'b, +{ + #[inline] + fn eq(&self, other: &Cow<'b, C>) -> bool { + PartialEq::eq(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where + B: PartialOrd + ToOwned, ::Owned: 'a +{ + #[inline] + fn partial_cmp(&self, other: &Cow<'a, B>) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where + B: fmt::Debug + ToOwned, + ::Owned: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Debug::fmt(b, f), + Owned(ref o) => fmt::Debug::fmt(o, f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where + B: fmt::Display + ToOwned, + ::Owned: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Display::fmt(b, f), + Owned(ref o) => fmt::Display::fmt(o, f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized, S: Hasher> Hash for Cow<'a, B> where + B: Hash + ToOwned, ::Owned: 'a +{ + #[inline] + fn hash(&self, state: &mut S) { + Hash::hash(&**self, state) + } +} + +/// Trait for moving into a `Cow` +#[stable(feature = "rust1", since = "1.0.0")] +pub trait IntoCow<'a, B: ?Sized> where B: ToOwned { + /// Moves `self` into `Cow` + #[stable(feature = "rust1", since = "1.0.0")] + fn into_cow(self) -> Cow<'a, B>; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { + fn into_cow(self) -> Cow<'a, B> { + self + } +} diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 747211e9238..6b980d473b5 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -19,7 +19,6 @@ use self::Entry::*; use core::prelude::*; -use core::borrow::BorrowFrom; use core::cmp::Ordering; use core::default::Default; use core::fmt::Debug; @@ -29,6 +28,7 @@ use core::ops::{Index, IndexMut}; use core::{iter, fmt, mem}; use Bound::{self, Included, Excluded, Unbounded}; +use borrow::Borrow; use ring_buf::RingBuf; use self::Continuation::{Continue, Finished}; @@ -208,7 +208,7 @@ impl BTreeMap { /// assert_eq!(map.get(&2), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn get(&self, key: &Q) -> Option<&V> where Q: BorrowFrom + Ord { + pub fn get(&self, key: &Q) -> Option<&V> where K: Borrow, Q: Ord { let mut cur_node = &self.root; loop { match Node::search(cur_node, key) { @@ -240,7 +240,7 @@ impl BTreeMap { /// assert_eq!(map.contains_key(&2), false); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn contains_key(&self, key: &Q) -> bool where Q: BorrowFrom + Ord { + pub fn contains_key(&self, key: &Q) -> bool where K: Borrow, Q: Ord { self.get(key).is_some() } @@ -264,7 +264,7 @@ impl BTreeMap { /// ``` // See `get` for implementation notes, this is basically a copy-paste with mut's added #[stable(feature = "rust1", since = "1.0.0")] - pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom + Ord { + pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where K: Borrow, Q: Ord { // temp_node is a Borrowck hack for having a mutable value outlive a loop iteration let mut temp_node = &mut self.root; loop { @@ -434,7 +434,7 @@ impl BTreeMap { /// assert_eq!(map.remove(&1), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn remove(&mut self, key: &Q) -> Option where Q: BorrowFrom + Ord { + pub fn remove(&mut self, key: &Q) -> Option where K: Borrow, Q: Ord { // See `swap` for a more thorough description of the stuff going on in here let mut stack = stack::PartialSearchStack::new(self); loop { @@ -903,7 +903,7 @@ impl Debug for BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] impl Index for BTreeMap - where Q: BorrowFrom + Ord + where K: Borrow, Q: Ord { type Output = V; @@ -914,7 +914,7 @@ impl Index for BTreeMap #[stable(feature = "rust1", since = "1.0.0")] impl IndexMut for BTreeMap - where Q: BorrowFrom + Ord + where K: Borrow, Q: Ord { fn index_mut(&mut self, key: &Q) -> &mut V { self.get_mut(key).expect("no entry found for key") diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index 24523d4dcc9..8f5ee35fcb2 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -18,7 +18,6 @@ pub use self::TraversalItem::*; use core::prelude::*; -use core::borrow::BorrowFrom; use core::cmp::Ordering::{Greater, Less, Equal}; use core::iter::Zip; use core::ops::{Deref, DerefMut, Index, IndexMut}; @@ -26,6 +25,8 @@ use core::ptr::Unique; use core::{slice, mem, ptr, cmp, num, raw}; use alloc::heap; +use borrow::Borrow; + /// Represents the result of an Insertion: either the item fit, or the node had to split pub enum InsertionResult { /// The inserted element fit @@ -543,7 +544,7 @@ impl Node { /// `Found` will be yielded with the matching index. If it doesn't find an exact match, /// `GoDown` will be yielded with the index of the subtree the key must lie in. pub fn search>>(node: NodeRef, key: &Q) - -> SearchResult where Q: BorrowFrom + Ord { + -> SearchResult where K: Borrow, Q: Ord { // FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V). // For the B configured as of this writing (B = 6), binary search was *significantly* // worse for usizes. @@ -1491,9 +1492,9 @@ macro_rules! node_slice_impl { impl<'a, K: Ord + 'a, V: 'a> $NodeSlice<'a, K, V> { /// Performs linear search in a slice. Returns a tuple of (index, is_exact_match). fn search_linear(&self, key: &Q) -> (usize, bool) - where Q: BorrowFrom + Ord { + where K: Borrow, Q: Ord { for (i, k) in self.keys.iter().enumerate() { - match key.cmp(BorrowFrom::borrow_from(k)) { + match key.cmp(k.borrow()) { Greater => {}, Equal => return (i, true), Less => return (i, false), diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 7ef887b70cc..cf96ef49c7f 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -13,7 +13,6 @@ use core::prelude::*; -use core::borrow::BorrowFrom; use core::cmp::Ordering::{self, Less, Greater, Equal}; use core::default::Default; use core::fmt::Debug; @@ -21,6 +20,7 @@ use core::fmt; use core::iter::{Peekable, Map, FromIterator, IntoIterator}; use core::ops::{BitOr, BitAnd, BitXor, Sub}; +use borrow::Borrow; use btree_map::{BTreeMap, Keys}; use Bound; @@ -336,7 +336,7 @@ impl BTreeSet { /// assert_eq!(set.contains(&4), false); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn contains(&self, value: &Q) -> bool where Q: BorrowFrom + Ord { + pub fn contains(&self, value: &Q) -> bool where T: Borrow, Q: Ord { self.map.contains_key(value) } @@ -466,7 +466,7 @@ impl BTreeSet { /// assert_eq!(set.remove(&2), false); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn remove(&mut self, value: &Q) -> bool where Q: BorrowFrom + Ord { + pub fn remove(&mut self, value: &Q) -> bool where T: Borrow, Q: Ord { self.map.remove(value).is_some() } } diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index cacbf3bce80..f5fbd10ceeb 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -81,6 +81,13 @@ pub mod string; pub mod vec; pub mod vec_map; +#[cfg(stage0)] +#[path = "borrow_stage0.rs"] +pub mod borrow; + +#[cfg(not(stage0))] +pub mod borrow; + #[unstable(feature = "collections", reason = "RFC 509")] pub mod bitv { diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 06ae8127c00..a0cb98267fa 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -88,7 +88,6 @@ #![stable(feature = "rust1", since = "1.0.0")] use alloc::boxed::Box; -use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned}; use core::clone::Clone; use core::cmp::Ordering::{self, Greater, Less}; use core::cmp::{self, Ord, PartialEq}; @@ -105,6 +104,7 @@ use core::result::Result; use core::slice as core_slice; use self::Direction::*; +use borrow::{Borrow, BorrowMut, ToOwned}; use vec::Vec; pub use core::slice::{Chunks, AsSlice, Windows}; @@ -1175,18 +1175,19 @@ impl ElementSwaps { // Standard trait implementations for slices //////////////////////////////////////////////////////////////////////////////// -#[unstable(feature = "collections", reason = "trait is unstable")] -impl BorrowFrom> for [T] { - fn borrow_from(owned: &Vec) -> &[T] { &owned[] } +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow<[T]> for Vec { + fn borrow(&self) -> &[T] { &self[] } } -#[unstable(feature = "collections", reason = "trait is unstable")] -impl BorrowFromMut> for [T] { - fn borrow_from_mut(owned: &mut Vec) -> &mut [T] { &mut owned[] } +#[stable(feature = "rust1", since = "1.0.0")] +impl BorrowMut<[T]> for Vec { + fn borrow_mut(&mut self) -> &mut [T] { &mut self[] } } -#[unstable(feature = "collections", reason = "trait is unstable")] -impl ToOwned> for [T] { +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for [T] { + type Owned = Vec; fn to_owned(&self) -> Vec { self.to_vec() } } diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 2d4dc2bcf30..95fd233dc97 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -55,7 +55,6 @@ use self::RecompositionState::*; use self::DecompositionType::*; -use core::borrow::{BorrowFrom, ToOwned}; use core::char::CharExt; use core::clone::Clone; use core::iter::AdditiveIterator; @@ -68,6 +67,7 @@ use core::slice::AsSlice; use core::str as core_str; use unicode::str::{UnicodeStr, Utf16Encoder}; +use borrow::{Borrow, ToOwned}; use ring_buf::RingBuf; use slice::SliceExt; use string::String; @@ -386,13 +386,14 @@ macro_rules! utf8_acc_cont_byte { ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63u8) as u32) } -#[unstable(feature = "collections", reason = "trait is unstable")] -impl BorrowFrom for str { - fn borrow_from(owned: &String) -> &str { &owned[] } +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow for String { + fn borrow(&self) -> &str { &self[] } } -#[unstable(feature = "collections", reason = "trait is unstable")] -impl ToOwned for str { +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for str { + type Owned = String; fn to_owned(&self) -> String { unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 69fd28d1723..f03ee671ffa 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -16,7 +16,6 @@ use core::prelude::*; -use core::borrow::{Cow, IntoCow}; use core::default::Default; use core::error::Error; use core::fmt; @@ -29,6 +28,7 @@ use core::raw::Slice as RawSlice; use unicode::str as unicode_str; use unicode::str::Utf16Item; +use borrow::{Cow, IntoCow}; use str::{self, CharRange, FromStr, Utf8Error}; use vec::{DerefVec, Vec, as_vec}; @@ -142,7 +142,7 @@ impl String { /// assert_eq!(output.as_slice(), "Hello \u{FFFD}World"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> CowString<'a> { + pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str> { let mut i = 0; match str::from_utf8(v) { Ok(s) => return Cow::Borrowed(s), @@ -780,10 +780,10 @@ macro_rules! impl_eq { } impl_eq! { String, &'a str } -impl_eq! { CowString<'a>, String } +impl_eq! { Cow<'a, str>, String } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> PartialEq<&'b str> for CowString<'a> { +impl<'a, 'b> PartialEq<&'b str> for Cow<'a, str> { #[inline] fn eq(&self, other: &&'b str) -> bool { PartialEq::eq(&**self, &**other) } #[inline] @@ -791,11 +791,11 @@ impl<'a, 'b> PartialEq<&'b str> for CowString<'a> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> PartialEq> for &'b str { +impl<'a, 'b> PartialEq> for &'b str { #[inline] - fn eq(&self, other: &CowString<'a>) -> bool { PartialEq::eq(&**self, &**other) } + fn eq(&self, other: &Cow<'a, str>) -> bool { PartialEq::eq(&**self, &**other) } #[inline] - fn ne(&self, other: &CowString<'a>) -> bool { PartialEq::ne(&**self, &**other) } + fn ne(&self, other: &Cow<'a, str>) -> bool { PartialEq::ne(&**self, &**other) } } #[unstable(feature = "collections", reason = "waiting on Str stabilization")] @@ -958,31 +958,34 @@ impl ToString for T { } } -impl IntoCow<'static, String, str> for String { +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoCow<'static, str> for String { #[inline] - fn into_cow(self) -> CowString<'static> { + fn into_cow(self) -> Cow<'static, str> { Cow::Owned(self) } } -impl<'a> IntoCow<'a, String, str> for &'a str { +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a> IntoCow<'a, str> for &'a str { #[inline] - fn into_cow(self) -> CowString<'a> { + fn into_cow(self) -> Cow<'a, str> { Cow::Borrowed(self) } } -/// A clone-on-write string -#[stable(feature = "rust1", since = "1.0.0")] -pub type CowString<'a> = Cow<'a, String, str>; - -impl<'a> Str for CowString<'a> { +impl<'a> Str for Cow<'a, str> { #[inline] fn as_slice<'b>(&'b self) -> &'b str { &**self } } +/// A clone-on-write string +#[deprecated(since = "1.0.0", reason = "use Cow<'a, str> instead")] +#[stable(feature = "rust1", since = "1.0.0")] +pub type CowString<'a> = Cow<'a, str>; + #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Write for String { #[inline] diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index bde733644b5..df6aa560257 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -50,7 +50,6 @@ use core::prelude::*; use alloc::boxed::Box; use alloc::heap::{EMPTY, allocate, reallocate, deallocate}; -use core::borrow::{Cow, IntoCow}; use core::cmp::max; use core::cmp::{Ordering}; use core::default::Default; @@ -68,6 +67,8 @@ use core::raw::Slice as RawSlice; use core::slice; use core::usize; +use borrow::{Cow, IntoCow}; + /// A growable list type, written `Vec` but pronounced 'vector.' /// /// # Examples @@ -1517,34 +1518,34 @@ macro_rules! impl_eq { impl_eq! { Vec, &'b [B] } impl_eq! { Vec, &'b mut [B] } -impl<'a, A, B> PartialEq> for CowVec<'a, A> where A: PartialEq + Clone { +impl<'a, A, B> PartialEq> for Cow<'a, [A]> where A: PartialEq + Clone { #[inline] fn eq(&self, other: &Vec) -> bool { PartialEq::eq(&**self, &**other) } #[inline] fn ne(&self, other: &Vec) -> bool { PartialEq::ne(&**self, &**other) } } -impl<'a, A, B> PartialEq> for Vec where A: Clone, B: PartialEq { +impl<'a, A, B> PartialEq> for Vec where A: Clone, B: PartialEq { #[inline] - fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) } + fn eq(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::eq(&**self, &**other) } #[inline] - fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) } + fn ne(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::ne(&**self, &**other) } } macro_rules! impl_eq_for_cowvec { ($rhs:ty) => { - impl<'a, 'b, A, B> PartialEq<$rhs> for CowVec<'a, A> where A: PartialEq + Clone { + impl<'a, 'b, A, B> PartialEq<$rhs> for Cow<'a, [A]> where A: PartialEq + Clone { #[inline] fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) } #[inline] fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) } } - impl<'a, 'b, A, B> PartialEq> for $rhs where A: Clone, B: PartialEq { + impl<'a, 'b, A, B> PartialEq> for $rhs where A: Clone, B: PartialEq { #[inline] - fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) } + fn eq(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::eq(&**self, &**other) } #[inline] - fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) } + fn ne(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::ne(&**self, &**other) } } } } @@ -1552,8 +1553,7 @@ macro_rules! impl_eq_for_cowvec { impl_eq_for_cowvec! { &'b [B] } impl_eq_for_cowvec! { &'b mut [B] } -#[unstable(feature = "collections", - reason = "waiting on PartialOrd stability")] +#[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for Vec { #[inline] fn partial_cmp(&self, other: &Vec) -> Option { @@ -1561,10 +1561,10 @@ impl PartialOrd for Vec { } } -#[unstable(feature = "collections", reason = "waiting on Eq stability")] +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for Vec {} -#[unstable(feature = "collections", reason = "waiting on Ord stability")] +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for Vec { #[inline] fn cmp(&self, other: &Vec) -> Ordering { @@ -1643,26 +1643,26 @@ impl fmt::Debug for Vec { // Clone-on-write //////////////////////////////////////////////////////////////////////////////// -#[unstable(feature = "collections", - reason = "unclear how valuable this alias is")] /// A clone-on-write vector -pub type CowVec<'a, T> = Cow<'a, Vec, [T]>; +#[deprecated(since = "1.0.0", reason = "use Cow<'a, [T]> instead")] +#[unstable(feature = "collections")] +pub type CowVec<'a, T> = Cow<'a, [T]>; #[unstable(feature = "collections")] -impl<'a, T> FromIterator for CowVec<'a, T> where T: Clone { +impl<'a, T> FromIterator for Cow<'a, [T]> where T: Clone { fn from_iter>(it: I) -> CowVec<'a, T> { Cow::Owned(FromIterator::from_iter(it)) } } -impl<'a, T: 'a> IntoCow<'a, Vec, [T]> for Vec where T: Clone { - fn into_cow(self) -> CowVec<'a, T> { +impl<'a, T: 'a> IntoCow<'a, [T]> for Vec where T: Clone { + fn into_cow(self) -> Cow<'a, [T]> { Cow::Owned(self) } } -impl<'a, T> IntoCow<'a, Vec, [T]> for &'a [T] where T: Clone { - fn into_cow(self) -> CowVec<'a, T> { +impl<'a, T> IntoCow<'a, [T]> for &'a [T] where T: Clone { + fn into_cow(self) -> Cow<'a, [T]> { Cow::Borrowed(self) } } diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs deleted file mode 100644 index 035443e9c3f..00000000000 --- a/src/libcore/borrow.rs +++ /dev/null @@ -1,265 +0,0 @@ -// 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 or the MIT license -// , 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` 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`, then `&T` can be borrowed from `&U`. A given -//! type can be borrowed as multiple different types. In particular, `Vec: -//! BorrowFrom>` and `[T]: BorrowFrom>`. -//! -//! # 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`, which means that you can call -//! non-mutating methods directly on the data it encloses. If mutation -//! is desired, `to_mut` will obtain a mutable references to an owned -//! value, cloning if necessary. - -#![unstable(feature = "core", - reason = "recently added as part of collections reform")] - -use clone::Clone; -use cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; -use fmt; -use marker::Sized; -use ops::Deref; -use option::Option; -use self::Cow::*; - -/// A trait for borrowing data. -#[old_orphan_check] -pub trait BorrowFrom { - /// Immutably borrow from an owned value. - fn borrow_from(owned: &Owned) -> &Self; -} - -/// A trait for mutably borrowing data. -#[old_orphan_check] -pub trait BorrowFromMut : BorrowFrom { - /// Mutably borrow from an owned value. - fn borrow_from_mut(owned: &mut Owned) -> &mut Self; -} - -impl BorrowFrom for T { - fn borrow_from(owned: &T) -> &T { owned } -} - -impl BorrowFromMut for T { - fn borrow_from_mut(owned: &mut T) -> &mut T { owned } -} - -impl<'a, T: ?Sized> BorrowFrom<&'a T> for T { - fn borrow_from<'b>(owned: &'b &'a T) -> &'b T { &**owned } -} - -impl<'a, T: ?Sized> BorrowFrom<&'a mut T> for T { - fn borrow_from<'b>(owned: &'b &'a mut T) -> &'b T { &**owned } -} - -impl<'a, T: ?Sized> BorrowFromMut<&'a mut T> for T { - fn borrow_from_mut<'b>(owned: &'b mut &'a mut T) -> &'b mut T { &mut **owned } -} - -impl<'a, T, B: ?Sized> BorrowFrom> for B where B: ToOwned { - fn borrow_from<'b>(owned: &'b Cow<'a, T, B>) -> &'b B { - &**owned - } -} - -/// Trait for moving into a `Cow` -#[old_orphan_check] -pub trait IntoCow<'a, T, B: ?Sized> { - /// Moves `self` into `Cow` - fn into_cow(self) -> Cow<'a, T, B>; -} - -impl<'a, T, B: ?Sized> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned { - fn into_cow(self) -> Cow<'a, T, B> { - self - } -} - -/// A generalization of Clone to borrowed data. -#[old_orphan_check] -pub trait ToOwned: BorrowFrom { - /// Create owned data from borrowed data, usually by copying. - fn to_owned(&self) -> Owned; -} - -impl ToOwned for T where T: Clone { - fn to_owned(&self) -> T { self.clone() } -} - -/// A clone-on-write smart pointer. -/// -/// # Example -/// -/// ```rust -/// use std::borrow::Cow; -/// -/// fn abs_all(input: &mut Cow, [int]>) { -/// for i in 0..input.len() { -/// let v = input[i]; -/// if v < 0 { -/// // clones into a vector the first time (if not already owned) -/// input.to_mut()[i] = -v; -/// } -/// } -/// } -/// ``` -pub enum Cow<'a, T, B: ?Sized + 'a> where B: ToOwned { - /// Borrowed data. - Borrowed(&'a B), - - /// Owned data. - Owned(T) -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> Clone for Cow<'a, T, B> where B: ToOwned { - fn clone(&self) -> Cow<'a, T, B> { - match *self { - Borrowed(b) => Borrowed(b), - Owned(ref o) => { - let b: &B = BorrowFrom::borrow_from(o); - Owned(b.to_owned()) - }, - } - } -} - -impl<'a, T, B: ?Sized> Cow<'a, T, B> where B: ToOwned { - /// 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 - } - } - - /// Returns true if this `Cow` wraps a borrowed value - pub fn is_borrowed(&self) -> bool { - match *self { - Borrowed(_) => true, - _ => false, - } - } - - /// Returns true if this `Cow` wraps an owned value - pub fn is_owned(&self) -> bool { - match *self { - Owned(_) => true, - _ => false, - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> Deref for Cow<'a, T, B> where B: ToOwned { - type Target = B; - - fn deref(&self) -> &B { - match *self { - Borrowed(borrowed) => borrowed, - Owned(ref owned) => BorrowFrom::borrow_from(owned) - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> Eq for Cow<'a, T, B> where B: Eq + ToOwned {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> Ord for Cow<'a, T, B> where B: Ord + ToOwned { - #[inline] - fn cmp(&self, other: &Cow<'a, T, B>) -> Ordering { - Ord::cmp(&**self, &**other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, U, B: ?Sized, C: ?Sized> PartialEq> for Cow<'a, T, B> where - B: PartialEq + ToOwned, - C: ToOwned, -{ - #[inline] - fn eq(&self, other: &Cow<'b, U, C>) -> bool { - PartialEq::eq(&**self, &**other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned { - #[inline] - fn partial_cmp(&self, other: &Cow<'a, T, B>) -> Option { - PartialOrd::partial_cmp(&**self, &**other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> fmt::Debug for Cow<'a, T, B> where - B: fmt::Debug + ToOwned, - T: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Borrowed(ref b) => fmt::Debug::fmt(b, f), - Owned(ref o) => fmt::Debug::fmt(o, f), - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> fmt::Display for Cow<'a, T, B> where - B: fmt::Display + ToOwned, - T: fmt::Display, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Borrowed(ref b) => fmt::Display::fmt(b, f), - Owned(ref o) => fmt::Display::fmt(o, f), - } - } -} diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index a5d2618eff9..28e14836a04 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -61,7 +61,6 @@ use prelude::*; -use borrow::{Cow, ToOwned}; use default::Default; use mem; use num::Int; @@ -243,12 +242,3 @@ impl Hash for *mut T { (*self as uint).hash(state); } } - -impl<'a, T, B: ?Sized, S: Hasher> Hash for Cow<'a, T, B> - where B: Hash + ToOwned -{ - #[inline] - fn hash(&self, state: &mut S) { - Hash::hash(&**self, state) - } -} diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index f0c60ffe4bf..3c58480ff0c 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -126,7 +126,6 @@ pub mod default; pub mod any; pub mod atomic; -pub mod borrow; pub mod cell; pub mod char; pub mod panicking; diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 230deabee00..28a97b1e8db 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -358,7 +358,7 @@ impl<'a> Id<'a> { /// /// Passing an invalid string (containing spaces, brackets, /// quotes, ...) will return an empty `Err` value. - pub fn new>(name: Name) -> Result, ()> { + pub fn new>(name: Name) -> Result, ()> { let name = name.into_cow(); { let mut chars = name.chars(); @@ -427,11 +427,11 @@ pub trait Labeller<'a,N,E> { } impl<'a> LabelText<'a> { - pub fn label>(s: S) -> LabelText<'a> { + pub fn label>(s: S) -> LabelText<'a> { LabelStr(s.into_cow()) } - pub fn escaped>(s: S) -> LabelText<'a> { + pub fn escaped>(s: S) -> LabelText<'a> { EscStr(s.into_cow()) } diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index e3eda02b0a8..60ae646e2c7 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -68,7 +68,7 @@ use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; use util::nodemap::{FnvHashMap}; use arena::TypedArena; -use std::borrow::{BorrowFrom, Cow}; +use std::borrow::{Borrow, Cow}; use std::cell::{Cell, RefCell}; use std::cmp; use std::fmt; @@ -986,9 +986,9 @@ impl<'tcx, S: Writer + Hasher> Hash for InternedTy<'tcx> { } } -impl<'tcx> BorrowFrom> for sty<'tcx> { - fn borrow_from<'a>(ty: &'a InternedTy<'tcx>) -> &'a sty<'tcx> { - &ty.ty.sty +impl<'tcx> Borrow> for InternedTy<'tcx> { + fn borrow<'a>(&'a self) -> &'a sty<'tcx> { + &self.ty.sty } } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 1b9f8b99017..9d3ffb114c1 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -14,7 +14,7 @@ use self::Entry::*; use self::SearchResult::*; use self::VacantEntryState::*; -use borrow::BorrowFrom; +use borrow::Borrow; use clone::Clone; use cmp::{max, Eq, PartialEq}; use default::Default; @@ -453,18 +453,18 @@ impl HashMap /// If you already have the hash for the key lying around, use /// search_hashed. fn search<'a, Q: ?Sized>(&'a self, q: &Q) -> Option> - where Q: BorrowFrom + Eq + Hash + where K: Borrow, Q: Eq + Hash { let hash = self.make_hash(q); - search_hashed(&self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k))) + search_hashed(&self.table, hash, |k| q.eq(k.borrow())) .into_option() } fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> Option> - where Q: BorrowFrom + Eq + Hash + where K: Borrow, Q: Eq + Hash { let hash = self.make_hash(q); - search_hashed(&mut self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k))) + search_hashed(&mut self.table, hash, |k| q.eq(k.borrow())) .into_option() } @@ -1037,7 +1037,7 @@ impl HashMap /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self, k: &Q) -> Option<&V> - where Q: Hash + Eq + BorrowFrom + where K: Borrow, Q: Hash + Eq { self.search(k).map(|bucket| bucket.into_refs().1) } @@ -1060,7 +1060,7 @@ impl HashMap /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn contains_key(&self, k: &Q) -> bool - where Q: Hash + Eq + BorrowFrom + where K: Borrow, Q: Hash + Eq { self.search(k).is_some() } @@ -1086,7 +1086,7 @@ impl HashMap /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> - where Q: Hash + Eq + BorrowFrom + where K: Borrow, Q: Hash + Eq { self.search_mut(k).map(|bucket| bucket.into_mut_refs().1) } @@ -1138,7 +1138,7 @@ impl HashMap /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, k: &Q) -> Option - where Q: Hash + Eq + BorrowFrom + where K: Borrow, Q: Hash + Eq { if self.table.size() == 0 { return None @@ -1247,8 +1247,8 @@ impl Default for HashMap #[stable(feature = "rust1", since = "1.0.0")] impl Index for HashMap - where K: Eq + Hash, - Q: Eq + Hash + BorrowFrom, + where K: Eq + Hash + Borrow, + Q: Eq + Hash, S: HashState, H: hash::Hasher { @@ -1262,8 +1262,8 @@ impl Index for HashMap #[stable(feature = "rust1", since = "1.0.0")] impl IndexMut for HashMap - where K: Eq + Hash, - Q: Eq + Hash + BorrowFrom, + where K: Eq + Hash + Borrow, + Q: Eq + Hash, S: HashState, H: hash::Hasher { diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 5fbbcb3b347..7befaa8c368 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -10,7 +10,7 @@ // // ignore-lexer-test FIXME #15883 -use borrow::BorrowFrom; +use borrow::Borrow; use clone::Clone; use cmp::{Eq, PartialEq}; use core::marker::Sized; @@ -462,7 +462,7 @@ impl HashSet /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn contains(&self, value: &Q) -> bool - where Q: BorrowFrom + Hash + Eq + where T: Borrow, Q: Hash + Eq { self.map.contains_key(value) } @@ -572,7 +572,7 @@ impl HashSet /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, value: &Q) -> bool - where Q: BorrowFrom + Hash + Eq + where T: Borrow, Q: Hash + Eq { self.map.remove(value).is_some() } diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 1d14b141778..8c29b11cb99 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -34,7 +34,7 @@ use core::prelude::*; -use core::borrow::{BorrowFrom, ToOwned}; +use borrow::{Borrow, ToOwned}; use fmt::{self, Debug}; use mem; use string::{String, CowString}; @@ -266,11 +266,12 @@ impl Debug for OsStr { } } -impl BorrowFrom for OsStr { - fn borrow_from(owned: &OsString) -> &OsStr { &owned[] } +impl Borrow for OsString { + fn borrow(&self) -> &OsStr { &self[] } } -impl ToOwned for OsStr { +impl ToOwned for OsStr { + type Owned = OsString; fn to_owned(&self) -> OsString { self.to_os_string() } } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 7c9a8a7b4b5..fbd403ea593 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -161,7 +161,6 @@ extern crate libc; // NB: These reexports are in the order they should be listed in rustdoc pub use core::any; -pub use core::borrow; pub use core::cell; pub use core::clone; #[cfg(not(test))] pub use core::cmp; @@ -184,6 +183,7 @@ pub use core::error; #[cfg(not(test))] pub use alloc::boxed; pub use alloc::rc; +pub use core_collections::borrow; pub use core_collections::fmt; pub use core_collections::slice; pub use core_collections::str; diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 1d992668900..1f7129bf361 100755 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -108,12 +108,11 @@ use core::prelude::*; use ascii::*; -use borrow::BorrowFrom; +use borrow::{Borrow, ToOwned, Cow}; use cmp; use iter; use mem; use ops::{self, Deref}; -use string::CowString; use vec::Vec; use fmt; @@ -982,12 +981,17 @@ impl ops::Deref for PathBuf { } } -impl BorrowFrom for Path { - fn borrow_from(owned: &PathBuf) -> &Path { - owned.deref() +impl Borrow for PathBuf { + fn borrow(&self) -> &Path { + self.deref() } } +impl ToOwned for Path { + type Owned = PathBuf; + fn to_owned(&self) -> PathBuf { self.to_path_buf() } +} + impl cmp::PartialEq for PathBuf { fn eq(&self, other: &PathBuf) -> bool { self.components() == other.components() @@ -1066,10 +1070,10 @@ impl Path { self.inner.to_str() } - /// Convert a `Path` to a `CowString`. + /// Convert a `Path` to a `Cow`. /// /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER. - pub fn to_string_lossy(&self) -> CowString { + pub fn to_string_lossy(&self) -> Cow { self.inner.to_string_lossy() } diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 51144267519..5236122f585 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -14,7 +14,7 @@ use ast::Name; -use std::borrow::BorrowFrom; +use std::borrow::Borrow; use std::cell::RefCell; use std::cmp::Ordering; use std::collections::HashMap; @@ -79,7 +79,7 @@ impl + Clone + 'static> Interner { } pub fn find(&self, val: &Q) -> Option - where Q: BorrowFrom + Eq + Hash { + where T: Borrow, Q: Eq + Hash { let map = self.map.borrow(); match (*map).get(val) { Some(v) => Some(*v), @@ -128,9 +128,9 @@ impl fmt::Display for RcStr { } } -impl BorrowFrom for str { - fn borrow_from(owned: &RcStr) -> &str { - &owned.string[] +impl Borrow for RcStr { + fn borrow(&self) -> &str { + &self.string[] } } @@ -211,7 +211,7 @@ impl StrInterner { } pub fn find(&self, val: &Q) -> Option - where Q: BorrowFrom + Eq + Hash { + where RcStr: Borrow, Q: Eq + Hash { match (*self.map.borrow()).get(val) { Some(v) => Some(*v), None => None, diff --git a/src/test/compile-fail/ufcs-qpath-missing-params.rs b/src/test/compile-fail/ufcs-qpath-missing-params.rs index 5fa66eb98e1..f4e18265fd9 100644 --- a/src/test/compile-fail/ufcs-qpath-missing-params.rs +++ b/src/test/compile-fail/ufcs-qpath-missing-params.rs @@ -12,6 +12,5 @@ use std::borrow::IntoCow; fn main() { ::into_cow("foo".to_string()); - //~^ ERROR wrong number of type arguments: expected 2, found 0 + //~^ ERROR wrong number of type arguments: expected 1, found 0 } - diff --git a/src/test/run-make/save-analysis/foo.rs b/src/test/run-make/save-analysis/foo.rs index d90219b4221..b393afeef39 100644 --- a/src/test/run-make/save-analysis/foo.rs +++ b/src/test/run-make/save-analysis/foo.rs @@ -34,7 +34,7 @@ use std::mem::size_of; static uni: &'static str = "Les Miséééééééérables"; static yy: usize = 25us; -static bob: Option> = None; +static bob: Option> = None; // buglink test - see issue #1337. diff --git a/src/test/run-pass/const-polymorphic-paths.rs b/src/test/run-pass/const-polymorphic-paths.rs index f8f92a56adb..be4c3272a5b 100644 --- a/src/test/run-pass/const-polymorphic-paths.rs +++ b/src/test/run-pass/const-polymorphic-paths.rs @@ -100,8 +100,8 @@ tests! { Add::add, fn(i32, i32) -> i32, (5, 6); >::add, fn(i32, i32) -> i32, (5, 6); >::add, fn(i32, i32) -> i32, (5, 6); - >::into_cow, fn(String) -> Cow<'static, String, str>, + >::into_cow, fn(String) -> Cow<'static, str>, ("foo".to_string()); - >::into_cow, fn(String) -> Cow<'static, String, str>, + >::into_cow, fn(String) -> Cow<'static, str>, ("foo".to_string()); } diff --git a/src/test/run-pass/send_str_hashmap.rs b/src/test/run-pass/send_str_hashmap.rs index c58654670d1..33e4fa85bcb 100644 --- a/src/test/run-pass/send_str_hashmap.rs +++ b/src/test/run-pass/send_str_hashmap.rs @@ -13,7 +13,7 @@ extern crate collections; use std::collections::HashMap; use std::borrow::{Cow, IntoCow}; -type SendStr = Cow<'static, String, str>; +type SendStr = Cow<'static, str>; pub fn main() { let mut map: HashMap = HashMap::new(); diff --git a/src/test/run-pass/send_str_treemap.rs b/src/test/run-pass/send_str_treemap.rs index 438724a2b06..3390369242d 100644 --- a/src/test/run-pass/send_str_treemap.rs +++ b/src/test/run-pass/send_str_treemap.rs @@ -13,7 +13,7 @@ extern crate collections; use self::collections::BTreeMap; use std::borrow::{Cow, IntoCow}; -type SendStr = Cow<'static, String, str>; +type SendStr = Cow<'static, str>; pub fn main() { let mut map: BTreeMap = BTreeMap::new(); diff --git a/src/test/run-pass/traits-issue-22019.rs b/src/test/run-pass/traits-issue-22019.rs index 5d3195e1937..7e0f60d55a8 100644 --- a/src/test/run-pass/traits-issue-22019.rs +++ b/src/test/run-pass/traits-issue-22019.rs @@ -23,18 +23,18 @@ pub type Node<'a> = &'a CFGNode; pub trait GraphWalk<'c, N> { /// Returns all the nodes in this graph. - fn nodes(&'c self) where [N]:ToOwned>; + fn nodes(&'c self) where [N]:ToOwned>; } impl<'g> GraphWalk<'g, Node<'g>> for u32 { - fn nodes(&'g self) where [Node<'g>]:ToOwned>> + fn nodes(&'g self) where [Node<'g>]:ToOwned>> { loop { } } } impl<'h> GraphWalk<'h, Node<'h>> for u64 { - fn nodes(&'h self) where [Node<'h>]:ToOwned>> + fn nodes(&'h self) where [Node<'h>]:ToOwned>> { loop { } } }