mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-20 12:35:11 +00:00
Register new snapshots
This commit is contained in:
parent
522d09dfec
commit
6686f7aa47
@ -598,13 +598,6 @@ impl<T: Default + Sync + Send> Default for Arc<T> {
|
|||||||
fn default() -> Arc<T> { Arc::new(Default::default()) }
|
fn default() -> Arc<T> { Arc::new(Default::default()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<H: Hasher, T: Hash<H>> Hash<H> for Arc<T> {
|
|
||||||
fn hash(&self, state: &mut H) {
|
|
||||||
(**self).hash(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Hash> Hash for Arc<T> {
|
impl<T: Hash> Hash for Arc<T> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
@ -220,14 +220,6 @@ impl<T: ?Sized + Ord> Ord for Box<T> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized + Eq> Eq for Box<T> {}
|
impl<T: ?Sized + Eq> Eq for Box<T> {}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: hash::Hasher, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
(**self).hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized + Hash> Hash for Box<T> {
|
impl<T: ?Sized + Hash> Hash for Box<T> {
|
||||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
|
@ -592,14 +592,6 @@ impl<T: Ord> Ord for Rc<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME (#18248) Make `T` `Sized?`
|
// FIXME (#18248) Make `T` `Sized?`
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: Hasher, T: Hash<S>> Hash<S> for Rc<T> {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
(**self).hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Hash> Hash for Rc<T> {
|
impl<T: Hash> Hash for Rc<T> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
@ -985,17 +985,6 @@ impl fmt::Debug for BitVec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for BitVec {
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
self.nbits.hash(state);
|
|
||||||
for elem in self.blocks() {
|
|
||||||
elem.hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl hash::Hash for BitVec {
|
impl hash::Hash for BitVec {
|
||||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
self.nbits.hash(state);
|
self.nbits.hash(state);
|
||||||
@ -1776,16 +1765,7 @@ impl fmt::Debug for BitSet {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for BitSet {
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
for pos in self {
|
|
||||||
pos.hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl hash::Hash for BitSet {
|
impl hash::Hash for BitSet {
|
||||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
for pos in self {
|
for pos in self {
|
||||||
|
@ -282,16 +282,6 @@ impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<'a, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, B> where B: Hash<S> + ToOwned
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
Hash::hash(&**self, state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned
|
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -1,313 +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 <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.
|
|
||||||
|
|
||||||
#![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<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 `Borrow`
|
|
||||||
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`. A given
|
|
||||||
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
|
|
||||||
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
pub trait Borrow<Borrowed: ?Sized> {
|
|
||||||
/// 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<Borrowed: ?Sized> : Borrow<Borrowed> {
|
|
||||||
/// 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<T: ?Sized> Borrow<T> for T {
|
|
||||||
fn borrow(&self) -> &T { self }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<T: ?Sized> BorrowMut<T> for T {
|
|
||||||
fn borrow_mut(&mut self) -> &mut T { self }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<'a, T: ?Sized> Borrow<T> for &'a T {
|
|
||||||
fn borrow(&self) -> &T { &**self }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<'a, T: ?Sized> Borrow<T> for &'a mut T {
|
|
||||||
fn borrow(&self) -> &T { &**self }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<'a, T: ?Sized> BorrowMut<T> for &'a mut T {
|
|
||||||
fn borrow_mut(&mut self) -> &mut T { &mut **self }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Borrow<T> for rc::Rc<T> {
|
|
||||||
fn borrow(&self) -> &T { &**self }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> Borrow<T> for arc::Arc<T> {
|
|
||||||
fn borrow(&self) -> &T { &**self }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> where B: ToOwned, <B as 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<Self>;
|
|
||||||
|
|
||||||
/// 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<T> 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(<B as ToOwned>::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, <B as 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 <B as ToOwned>::Owned where <B as ToOwned>::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) -> <B as ToOwned>::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, <B as 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, <B as ToOwned>::Owned: 'a {}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<'a, B: ?Sized> Ord for Cow<'a, B> where
|
|
||||||
B: Ord + ToOwned, <B as 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<Cow<'b, C>> for Cow<'a, B> where
|
|
||||||
B: PartialEq<C> + ToOwned, C: ToOwned,
|
|
||||||
<B as ToOwned>::Owned: 'a, <C as ToOwned>::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, <B as ToOwned>::Owned: 'a
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
|
|
||||||
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,
|
|
||||||
<B as 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,
|
|
||||||
<B as 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<S> for Cow<'a, B> where
|
|
||||||
B: Hash<S> + ToOwned, <B as 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
|
|
||||||
}
|
|
||||||
}
|
|
@ -852,16 +852,6 @@ impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<S: Hasher, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
for elt in self {
|
|
||||||
elt.hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<K: Hash, V: Hash> Hash for BTreeMap<K, V> {
|
impl<K: Hash, V: Hash> Hash for BTreeMap<K, V> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
@ -86,23 +86,17 @@ mod macros;
|
|||||||
pub mod binary_heap;
|
pub mod binary_heap;
|
||||||
mod bit;
|
mod bit;
|
||||||
mod btree;
|
mod btree;
|
||||||
pub mod linked_list;
|
pub mod borrow;
|
||||||
pub mod enum_set;
|
pub mod enum_set;
|
||||||
pub mod fmt;
|
pub mod fmt;
|
||||||
pub mod vec_deque;
|
pub mod linked_list;
|
||||||
pub mod slice;
|
pub mod slice;
|
||||||
pub mod str;
|
pub mod str;
|
||||||
pub mod string;
|
pub mod string;
|
||||||
pub mod vec;
|
pub mod vec;
|
||||||
|
pub mod vec_deque;
|
||||||
pub mod vec_map;
|
pub mod vec_map;
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
#[path = "borrow_stage0.rs"]
|
|
||||||
pub mod borrow;
|
|
||||||
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub mod borrow;
|
|
||||||
|
|
||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "RFC 509")]
|
reason = "RFC 509")]
|
||||||
pub mod bit_vec {
|
pub mod bit_vec {
|
||||||
|
@ -28,8 +28,6 @@ use core::cmp::Ordering;
|
|||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::hash::{Hasher, Hash};
|
use core::hash::{Hasher, Hash};
|
||||||
#[cfg(stage0)]
|
|
||||||
use core::hash::Writer;
|
|
||||||
use core::iter::{self, FromIterator, IntoIterator};
|
use core::iter::{self, FromIterator, IntoIterator};
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
@ -932,17 +930,6 @@ impl<A: fmt::Debug> fmt::Debug for LinkedList<A> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for LinkedList<A> {
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
self.len().hash(state);
|
|
||||||
for elt in self {
|
|
||||||
elt.hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<A: Hash> Hash for LinkedList<A> {
|
impl<A: Hash> Hash for LinkedList<A> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
self.len().hash(state);
|
self.len().hash(state);
|
||||||
|
@ -834,16 +834,7 @@ impl fmt::Debug for String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections", reason = "waiting on Hash stabilization")]
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for String {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, hasher: &mut H) {
|
|
||||||
(**self).hash(hasher)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl hash::Hash for String {
|
impl hash::Hash for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
|
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
|
||||||
|
@ -1303,15 +1303,7 @@ impl<T:Clone> Clone for Vec<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for Vec<T> {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
Hash::hash(&**self, state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<T: Hash> Hash for Vec<T> {
|
impl<T: Hash> Hash for Vec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
@ -1599,9 +1591,7 @@ impl<T> AsSlice<T> for Vec<T> {
|
|||||||
fn as_slice(&self) -> &[T] {
|
fn as_slice(&self) -> &[T] {
|
||||||
unsafe {
|
unsafe {
|
||||||
let p = *self.ptr;
|
let p = *self.ptr;
|
||||||
if cfg!(not(stage0)) { // NOTE remove cfg after next snapshot
|
|
||||||
assume(p != 0 as *mut T);
|
assume(p != 0 as *mut T);
|
||||||
}
|
|
||||||
mem::transmute(RawSlice {
|
mem::transmute(RawSlice {
|
||||||
data: p,
|
data: p,
|
||||||
len: self.len
|
len: self.len
|
||||||
|
@ -32,7 +32,6 @@ use core::ptr::{self, Unique};
|
|||||||
use core::raw::Slice as RawSlice;
|
use core::raw::Slice as RawSlice;
|
||||||
|
|
||||||
use core::hash::{Hash, Hasher};
|
use core::hash::{Hash, Hasher};
|
||||||
#[cfg(stage0)] use core::hash::Writer;
|
|
||||||
use core::cmp;
|
use core::cmp;
|
||||||
|
|
||||||
use alloc::heap;
|
use alloc::heap;
|
||||||
@ -1675,17 +1674,6 @@ impl<A: Ord> Ord for VecDeque<A> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for VecDeque<A> {
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
self.len().hash(state);
|
|
||||||
for elt in self {
|
|
||||||
elt.hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<A: Hash> Hash for VecDeque<A> {
|
impl<A: Hash> Hash for VecDeque<A> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
self.len().hash(state);
|
self.len().hash(state);
|
||||||
|
@ -21,7 +21,6 @@ use core::cmp::Ordering;
|
|||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::hash::{Hash, Hasher};
|
use core::hash::{Hash, Hasher};
|
||||||
#[cfg(stage0)] use core::hash::Writer;
|
|
||||||
use core::iter::{Enumerate, FilterMap, Map, FromIterator, IntoIterator};
|
use core::iter::{Enumerate, FilterMap, Map, FromIterator, IntoIterator};
|
||||||
use core::iter;
|
use core::iter;
|
||||||
use core::mem::replace;
|
use core::mem::replace;
|
||||||
@ -113,21 +112,7 @@ impl<V:Clone> Clone for VecMap<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: Writer + Hasher, V: Hash<S>> Hash<S> for VecMap<V> {
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
// In order to not traverse the `VecMap` twice, count the elements
|
|
||||||
// during iteration.
|
|
||||||
let mut count: usize = 0;
|
|
||||||
for elt in self {
|
|
||||||
elt.hash(state);
|
|
||||||
count += 1;
|
|
||||||
}
|
|
||||||
count.hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<V: Hash> Hash for VecMap<V> {
|
impl<V: Hash> Hash for VecMap<V> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
// In order to not traverse the `VecMap` twice, count the elements
|
// In order to not traverse the `VecMap` twice, count the elements
|
||||||
|
@ -35,13 +35,6 @@ macro_rules! array_impls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for [T; $N] {
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
Hash::hash(&self[..], state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Hash> Hash for [T; $N] {
|
impl<T: Hash> Hash for [T; $N] {
|
||||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
|
@ -73,7 +73,6 @@ mod sip;
|
|||||||
/// to compute the hash. Specific implementations of this trait may specialize
|
/// to compute the hash. Specific implementations of this trait may specialize
|
||||||
/// for particular instances of `H` in order to be able to optimize the hashing
|
/// for particular instances of `H` in order to be able to optimize the hashing
|
||||||
/// behavior.
|
/// behavior.
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait Hash {
|
pub trait Hash {
|
||||||
/// Feeds this value into the state given, updating the hasher as necessary.
|
/// Feeds this value into the state given, updating the hasher as necessary.
|
||||||
@ -89,72 +88,40 @@ pub trait Hash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A hashable type.
|
|
||||||
///
|
|
||||||
/// The `H` type parameter is an abstract hash state that is used by the `Hash`
|
|
||||||
/// to compute the hash. Specific implementations of this trait may specialize
|
|
||||||
/// for particular instances of `H` in order to be able to optimize the hashing
|
|
||||||
/// behavior.
|
|
||||||
#[cfg(stage0)]
|
|
||||||
pub trait Hash<H: Hasher> {
|
|
||||||
/// Feeds this value into the state given, updating the hasher as necessary.
|
|
||||||
fn hash(&self, state: &mut H);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A trait which represents the ability to hash an arbitrary stream of bytes.
|
/// A trait which represents the ability to hash an arbitrary stream of bytes.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait Hasher {
|
pub trait Hasher {
|
||||||
/// Result type of one run of hashing generated by this hasher.
|
|
||||||
#[cfg(stage0)]
|
|
||||||
type Output;
|
|
||||||
|
|
||||||
/// Resets this hasher back to its initial state (as if it were just
|
|
||||||
/// created).
|
|
||||||
#[cfg(stage0)]
|
|
||||||
fn reset(&mut self);
|
|
||||||
|
|
||||||
/// Completes a round of hashing, producing the output hash generated.
|
/// Completes a round of hashing, producing the output hash generated.
|
||||||
#[cfg(stage0)]
|
|
||||||
fn finish(&self) -> Self::Output;
|
|
||||||
|
|
||||||
/// Completes a round of hashing, producing the output hash generated.
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
fn finish(&self) -> u64;
|
fn finish(&self) -> u64;
|
||||||
|
|
||||||
/// Writes some data into this `Hasher`
|
/// Writes some data into this `Hasher`
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn write(&mut self, bytes: &[u8]);
|
fn write(&mut self, bytes: &[u8]);
|
||||||
|
|
||||||
/// Write a single `u8` into this hasher
|
/// Write a single `u8` into this hasher
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
fn write_u8(&mut self, i: u8) { self.write(&[i]) }
|
fn write_u8(&mut self, i: u8) { self.write(&[i]) }
|
||||||
/// Write a single `u16` into this hasher.
|
/// Write a single `u16` into this hasher.
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
fn write_u16(&mut self, i: u16) {
|
fn write_u16(&mut self, i: u16) {
|
||||||
self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
|
self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
|
||||||
}
|
}
|
||||||
/// Write a single `u32` into this hasher.
|
/// Write a single `u32` into this hasher.
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
fn write_u32(&mut self, i: u32) {
|
fn write_u32(&mut self, i: u32) {
|
||||||
self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
|
self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
|
||||||
}
|
}
|
||||||
/// Write a single `u64` into this hasher.
|
/// Write a single `u64` into this hasher.
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
fn write_u64(&mut self, i: u64) {
|
fn write_u64(&mut self, i: u64) {
|
||||||
self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
|
self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
|
||||||
}
|
}
|
||||||
/// Write a single `usize` into this hasher.
|
/// Write a single `usize` into this hasher.
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
fn write_usize(&mut self, i: usize) {
|
fn write_usize(&mut self, i: usize) {
|
||||||
@ -166,58 +133,31 @@ pub trait Hasher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Write a single `i8` into this hasher.
|
/// Write a single `i8` into this hasher.
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) }
|
fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) }
|
||||||
/// Write a single `i16` into this hasher.
|
/// Write a single `i16` into this hasher.
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) }
|
fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) }
|
||||||
/// Write a single `i32` into this hasher.
|
/// Write a single `i32` into this hasher.
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) }
|
fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) }
|
||||||
/// Write a single `i64` into this hasher.
|
/// Write a single `i64` into this hasher.
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) }
|
fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) }
|
||||||
/// Write a single `isize` into this hasher.
|
/// Write a single `isize` into this hasher.
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) }
|
fn write_isize(&mut self, i: isize) { self.write_usize(i as usize) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A common bound on the `Hasher` parameter to `Hash` implementations in order
|
|
||||||
/// to generically hash an aggregate.
|
|
||||||
#[unstable(feature = "hash",
|
|
||||||
reason = "this trait will likely be replaced by io::Writer")]
|
|
||||||
#[allow(missing_docs)]
|
|
||||||
#[cfg(stage0)]
|
|
||||||
pub trait Writer {
|
|
||||||
fn write(&mut self, bytes: &[u8]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Hash a value with the default SipHasher algorithm (two initial keys of 0).
|
/// Hash a value with the default SipHasher algorithm (two initial keys of 0).
|
||||||
///
|
///
|
||||||
/// The specified value will be hashed with this hasher and then the resulting
|
/// The specified value will be hashed with this hasher and then the resulting
|
||||||
/// hash will be returned.
|
/// hash will be returned.
|
||||||
#[cfg(stage0)]
|
|
||||||
pub fn hash<T: Hash<H>, H: Hasher + Default>(value: &T) -> H::Output {
|
|
||||||
let mut h: H = Default::default();
|
|
||||||
value.hash(&mut h);
|
|
||||||
h.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Hash a value with the default SipHasher algorithm (two initial keys of 0).
|
|
||||||
///
|
|
||||||
/// The specified value will be hashed with this hasher and then the resulting
|
|
||||||
/// hash will be returned.
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
|
pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
|
||||||
let mut h: H = Default::default();
|
let mut h: H = Default::default();
|
||||||
@ -227,145 +167,6 @@ pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
|
|||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
mod impls {
|
|
||||||
use prelude::*;
|
|
||||||
|
|
||||||
use mem;
|
|
||||||
use num::Int;
|
|
||||||
use super::*;
|
|
||||||
|
|
||||||
macro_rules! impl_hash {
|
|
||||||
($ty:ident, $uty:ident) => {
|
|
||||||
impl<S: Writer + Hasher> Hash<S> for $ty {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
let a: [u8; ::$ty::BYTES] = unsafe {
|
|
||||||
mem::transmute(*self)
|
|
||||||
};
|
|
||||||
state.write(&a)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_hash! { u8, u8 }
|
|
||||||
impl_hash! { u16, u16 }
|
|
||||||
impl_hash! { u32, u32 }
|
|
||||||
impl_hash! { u64, u64 }
|
|
||||||
impl_hash! { uint, uint }
|
|
||||||
impl_hash! { i8, u8 }
|
|
||||||
impl_hash! { i16, u16 }
|
|
||||||
impl_hash! { i32, u32 }
|
|
||||||
impl_hash! { i64, u64 }
|
|
||||||
impl_hash! { int, uint }
|
|
||||||
|
|
||||||
impl<S: Writer + Hasher> Hash<S> for bool {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
(*self as u8).hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: Writer + Hasher> Hash<S> for char {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
(*self as u32).hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: Writer + Hasher> Hash<S> for str {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
state.write(self.as_bytes());
|
|
||||||
0xffu8.hash(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_hash_tuple {
|
|
||||||
() => (
|
|
||||||
impl<S: Hasher> Hash<S> for () {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, _state: &mut S) {}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
( $($name:ident)+) => (
|
|
||||||
impl<S: Hasher, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
|
|
||||||
#[inline]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
match *self {
|
|
||||||
($(ref $name,)*) => {
|
|
||||||
$(
|
|
||||||
$name.hash(state);
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_hash_tuple! {}
|
|
||||||
impl_hash_tuple! { A }
|
|
||||||
impl_hash_tuple! { A B }
|
|
||||||
impl_hash_tuple! { A B C }
|
|
||||||
impl_hash_tuple! { A B C D }
|
|
||||||
impl_hash_tuple! { A B C D E }
|
|
||||||
impl_hash_tuple! { A B C D E F }
|
|
||||||
impl_hash_tuple! { A B C D E F G }
|
|
||||||
impl_hash_tuple! { A B C D E F G H }
|
|
||||||
impl_hash_tuple! { A B C D E F G H I }
|
|
||||||
impl_hash_tuple! { A B C D E F G H I J }
|
|
||||||
impl_hash_tuple! { A B C D E F G H I J K }
|
|
||||||
impl_hash_tuple! { A B C D E F G H I J K L }
|
|
||||||
|
|
||||||
impl<S: Writer + Hasher, T: Hash<S>> Hash<S> for [T] {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
self.len().hash(state);
|
|
||||||
for elt in self {
|
|
||||||
elt.hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a T {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
(**self).hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
(**self).hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: Writer + Hasher, T> Hash<S> for *const T {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
// NB: raw-pointer Hash does _not_ dereference
|
|
||||||
// to the target; it just gives you the pointer-bytes.
|
|
||||||
(*self as uint).hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: Writer + Hasher, T> Hash<S> for *mut T {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
// NB: raw-pointer Hash does _not_ dereference
|
|
||||||
// to the target; it just gives you the pointer-bytes.
|
|
||||||
(*self as uint).hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
mod impls {
|
mod impls {
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
|
|
||||||
|
@ -16,8 +16,6 @@ use prelude::*;
|
|||||||
use default::Default;
|
use default::Default;
|
||||||
|
|
||||||
use super::Hasher;
|
use super::Hasher;
|
||||||
#[cfg(stage0)]
|
|
||||||
use super::Writer;
|
|
||||||
|
|
||||||
/// An implementation of SipHash 2-4.
|
/// An implementation of SipHash 2-4.
|
||||||
///
|
///
|
||||||
@ -175,26 +173,9 @@ impl SipHasher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl Writer for SipHasher {
|
|
||||||
#[inline]
|
|
||||||
fn write(&mut self, msg: &[u8]) {
|
|
||||||
self.write(msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl Hasher for SipHasher {
|
impl Hasher for SipHasher {
|
||||||
#[cfg(stage0)]
|
|
||||||
type Output = u64;
|
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
fn reset(&mut self) {
|
|
||||||
self.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cfg(not(stage0))]
|
|
||||||
fn write(&mut self, msg: &[u8]) {
|
fn write(&mut self, msg: &[u8]) {
|
||||||
self.write(msg)
|
self.write(msg)
|
||||||
}
|
}
|
||||||
|
@ -31,20 +31,10 @@ use option::Option;
|
|||||||
use hash::Hash;
|
use hash::Hash;
|
||||||
use hash::Hasher;
|
use hash::Hasher;
|
||||||
|
|
||||||
/// Types able to be transferred across thread boundaries.
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "will be overhauled with new lifetime rules; see RFC 458")]
|
|
||||||
#[lang="send"]
|
|
||||||
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
|
||||||
#[cfg(stage0)]
|
|
||||||
pub unsafe trait Send: 'static {
|
|
||||||
// empty.
|
|
||||||
}
|
|
||||||
/// Types able to be transferred across thread boundaries.
|
/// Types able to be transferred across thread boundaries.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[lang="send"]
|
#[lang="send"]
|
||||||
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub unsafe trait Send : MarkerTrait {
|
pub unsafe trait Send : MarkerTrait {
|
||||||
// empty.
|
// empty.
|
||||||
}
|
}
|
||||||
@ -233,13 +223,6 @@ pub struct Managed;
|
|||||||
|
|
||||||
macro_rules! impls{
|
macro_rules! impls{
|
||||||
($t: ident) => (
|
($t: ident) => (
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<T:?Sized, S: Hasher> Hash<S> for $t<T> {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, _: &mut S) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<T:?Sized> Hash for $t<T> {
|
impl<T:?Sized> Hash for $t<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, _: &mut H) {
|
fn hash<H: Hasher>(&self, _: &mut H) {
|
||||||
@ -348,14 +331,6 @@ impl<T:?Sized> MarkerTrait for T { }
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
|
pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
|
||||||
|
|
||||||
#[cfg(stage0)] // built into the trait matching system after stage0
|
|
||||||
impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
|
|
||||||
|
|
||||||
/// Specific to stage0. You should not be seeing these docs!
|
|
||||||
#[cfg(stage0)]
|
|
||||||
#[lang="covariant_type"] // only relevant to stage0
|
|
||||||
pub struct PhantomData<T:?Sized>;
|
|
||||||
|
|
||||||
/// `PhantomData` is a way to tell the compiler about fake fields.
|
/// `PhantomData` is a way to tell the compiler about fake fields.
|
||||||
/// Phantom data is required whenever type parameters are not used.
|
/// Phantom data is required whenever type parameters are not used.
|
||||||
/// The idea is that if the compiler encounters a `PhantomData<T>`
|
/// The idea is that if the compiler encounters a `PhantomData<T>`
|
||||||
@ -374,14 +349,12 @@ pub struct PhantomData<T:?Sized>;
|
|||||||
/// here! For now, please see [RFC 738][738] for more information.
|
/// here! For now, please see [RFC 738][738] for more information.
|
||||||
///
|
///
|
||||||
/// [738]: https://github.com/rust-lang/rfcs/blob/master/text/0738-variance.md
|
/// [738]: https://github.com/rust-lang/rfcs/blob/master/text/0738-variance.md
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[lang="phantom_data"]
|
#[lang="phantom_data"]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct PhantomData<T:?Sized>;
|
pub struct PhantomData<T:?Sized>;
|
||||||
|
|
||||||
impls! { PhantomData }
|
impls! { PhantomData }
|
||||||
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
mod impls {
|
mod impls {
|
||||||
use super::{Send, Sync, Sized};
|
use super::{Send, Sync, Sized};
|
||||||
|
|
||||||
@ -417,7 +390,6 @@ pub struct ContravariantType<T>;
|
|||||||
#[unstable(feature = "core", reason = "deprecated")]
|
#[unstable(feature = "core", reason = "deprecated")]
|
||||||
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<T>`")]
|
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<T>`")]
|
||||||
#[lang="covariant_type"]
|
#[lang="covariant_type"]
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub struct CovariantType<T>;
|
pub struct CovariantType<T>;
|
||||||
|
|
||||||
/// Old-style marker trait. Deprecated.
|
/// Old-style marker trait. Deprecated.
|
||||||
|
@ -185,14 +185,6 @@ impl PartialEq for LintId {
|
|||||||
|
|
||||||
impl Eq for LintId { }
|
impl Eq for LintId { }
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for LintId {
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
let ptr = self.lint as *const Lint;
|
|
||||||
ptr.hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl hash::Hash for LintId {
|
impl hash::Hash for LintId {
|
||||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
let ptr = self.lint as *const Lint;
|
let ptr = self.lint as *const Lint;
|
||||||
|
@ -1588,48 +1588,6 @@ fn encode_info_for_items(ecx: &EncodeContext,
|
|||||||
|
|
||||||
// Path and definition ID indexing
|
// Path and definition ID indexing
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
|
|
||||||
F: FnMut(&mut SeekableMemWriter, &T),
|
|
||||||
T: Hash<SipHasher>,
|
|
||||||
{
|
|
||||||
let mut buckets: Vec<Vec<entry<T>>> = (0..256u16).map(|_| Vec::new()).collect();
|
|
||||||
for elt in index {
|
|
||||||
let mut s = SipHasher::new();
|
|
||||||
elt.val.hash(&mut s);
|
|
||||||
let h = s.finish() as uint;
|
|
||||||
(&mut buckets[h % 256]).push(elt);
|
|
||||||
}
|
|
||||||
|
|
||||||
rbml_w.start_tag(tag_index);
|
|
||||||
let mut bucket_locs = Vec::new();
|
|
||||||
rbml_w.start_tag(tag_index_buckets);
|
|
||||||
for bucket in &buckets {
|
|
||||||
bucket_locs.push(rbml_w.writer.tell().unwrap());
|
|
||||||
rbml_w.start_tag(tag_index_buckets_bucket);
|
|
||||||
for elt in bucket {
|
|
||||||
rbml_w.start_tag(tag_index_buckets_bucket_elt);
|
|
||||||
assert!(elt.pos < 0xffff_ffff);
|
|
||||||
{
|
|
||||||
let wr: &mut SeekableMemWriter = rbml_w.writer;
|
|
||||||
wr.write_be_u32(elt.pos as u32);
|
|
||||||
}
|
|
||||||
write_fn(rbml_w.writer, &elt.val);
|
|
||||||
rbml_w.end_tag();
|
|
||||||
}
|
|
||||||
rbml_w.end_tag();
|
|
||||||
}
|
|
||||||
rbml_w.end_tag();
|
|
||||||
rbml_w.start_tag(tag_index_table);
|
|
||||||
for pos in &bucket_locs {
|
|
||||||
assert!(*pos < 0xffff_ffff);
|
|
||||||
let wr: &mut SeekableMemWriter = rbml_w.writer;
|
|
||||||
wr.write_be_u32(*pos as u32);
|
|
||||||
}
|
|
||||||
rbml_w.end_tag();
|
|
||||||
rbml_w.end_tag();
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
|
fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
|
||||||
F: FnMut(&mut SeekableMemWriter, &T),
|
F: FnMut(&mut SeekableMemWriter, &T),
|
||||||
T: Hash,
|
T: Hash,
|
||||||
|
@ -73,7 +73,6 @@ use std::cell::{Cell, RefCell};
|
|||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::{Hash, SipHasher, Hasher};
|
use std::hash::{Hash, SipHasher, Hasher};
|
||||||
#[cfg(stage0)] use std::hash::Writer;
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops;
|
use std::ops;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -959,13 +958,6 @@ impl<'tcx> PartialEq for TyS<'tcx> {
|
|||||||
}
|
}
|
||||||
impl<'tcx> Eq for TyS<'tcx> {}
|
impl<'tcx> Eq for TyS<'tcx> {}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<'tcx, S: Writer + Hasher> Hash<S> for TyS<'tcx> {
|
|
||||||
fn hash(&self, s: &mut S) {
|
|
||||||
(self as *const _).hash(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<'tcx> Hash for TyS<'tcx> {
|
impl<'tcx> Hash for TyS<'tcx> {
|
||||||
fn hash<H: Hasher>(&self, s: &mut H) {
|
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||||
(self as *const _).hash(s)
|
(self as *const _).hash(s)
|
||||||
@ -988,13 +980,6 @@ impl<'tcx> PartialEq for InternedTy<'tcx> {
|
|||||||
|
|
||||||
impl<'tcx> Eq for InternedTy<'tcx> {}
|
impl<'tcx> Eq for InternedTy<'tcx> {}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<'tcx, S: Writer + Hasher> Hash<S> for InternedTy<'tcx> {
|
|
||||||
fn hash(&self, s: &mut S) {
|
|
||||||
self.ty.sty.hash(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<'tcx> Hash for InternedTy<'tcx> {
|
impl<'tcx> Hash for InternedTy<'tcx> {
|
||||||
fn hash<H: Hasher>(&self, s: &mut H) {
|
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||||
self.ty.sty.hash(s)
|
self.ty.sty.hash(s)
|
||||||
|
@ -14,7 +14,6 @@ use std::cell::{RefCell, Cell};
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
#[cfg(stage0)] use std::hash::Hasher;
|
|
||||||
use std::iter::repeat;
|
use std::iter::repeat;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::collections::hash_state::HashState;
|
use std::collections::hash_state::HashState;
|
||||||
@ -139,57 +138,13 @@ pub fn block_query<P>(b: &ast::Block, p: P) -> bool where P: FnMut(&ast::Expr) -
|
|||||||
|
|
||||||
/// K: Eq + Hash<S>, V, S, H: Hasher<S>
|
/// K: Eq + Hash<S>, V, S, H: Hasher<S>
|
||||||
///
|
///
|
||||||
/// Determines whether there exists a path from `source` to `destination`. The graph is defined by
|
/// Determines whether there exists a path from `source` to `destination`. The
|
||||||
/// the `edges_map`, which maps from a node `S` to a list of its adjacent nodes `T`.
|
/// graph is defined by the `edges_map`, which maps from a node `S` to a list of
|
||||||
|
/// its adjacent nodes `T`.
|
||||||
///
|
///
|
||||||
/// Efficiency note: This is implemented in an inefficient way because it is typically invoked on
|
/// Efficiency note: This is implemented in an inefficient way because it is
|
||||||
/// very small graphs. If the graphs become larger, a more efficient graph representation and
|
/// typically invoked on very small graphs. If the graphs become larger, a more
|
||||||
/// algorithm would probably be advised.
|
/// efficient graph representation and algorithm would probably be advised.
|
||||||
#[cfg(stage0)]
|
|
||||||
pub fn can_reach<T, S>(edges_map: &HashMap<T, Vec<T>, S>, source: T,
|
|
||||||
destination: T) -> bool
|
|
||||||
where S: HashState,
|
|
||||||
<S as HashState>::Hasher: Hasher<Output=u64>,
|
|
||||||
T: Hash<<S as HashState>::Hasher> + Eq + Clone,
|
|
||||||
{
|
|
||||||
if source == destination {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do a little breadth-first-search here. The `queue` list
|
|
||||||
// doubles as a way to detect if we've seen a particular FR
|
|
||||||
// before. Note that we expect this graph to be an *extremely
|
|
||||||
// shallow* tree.
|
|
||||||
let mut queue = vec!(source);
|
|
||||||
let mut i = 0;
|
|
||||||
while i < queue.len() {
|
|
||||||
match edges_map.get(&queue[i]) {
|
|
||||||
Some(edges) => {
|
|
||||||
for target in edges {
|
|
||||||
if *target == destination {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if !queue.iter().any(|x| x == target) {
|
|
||||||
queue.push((*target).clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/// K: Eq + Hash<S>, V, S, H: Hasher<S>
|
|
||||||
///
|
|
||||||
/// Determines whether there exists a path from `source` to `destination`. The graph is defined by
|
|
||||||
/// the `edges_map`, which maps from a node `S` to a list of its adjacent nodes `T`.
|
|
||||||
///
|
|
||||||
/// Efficiency note: This is implemented in an inefficient way because it is typically invoked on
|
|
||||||
/// very small graphs. If the graphs become larger, a more efficient graph representation and
|
|
||||||
/// algorithm would probably be advised.
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub fn can_reach<T, S>(edges_map: &HashMap<T, Vec<T>, S>, source: T,
|
pub fn can_reach<T, S>(edges_map: &HashMap<T, Vec<T>, S>, source: T,
|
||||||
destination: T) -> bool
|
destination: T) -> bool
|
||||||
where S: HashState, T: Hash + Eq + Clone,
|
where S: HashState, T: Hash + Eq + Clone,
|
||||||
@ -250,52 +205,6 @@ pub fn can_reach<T, S>(edges_map: &HashMap<T, Vec<T>, S>, source: T,
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
#[cfg(stage0)]
|
|
||||||
pub fn memoized<T, U, S, F>(cache: &RefCell<HashMap<T, U, S>>, arg: T, f: F) -> U
|
|
||||||
where T: Clone + Hash<<S as HashState>::Hasher> + Eq,
|
|
||||||
U: Clone,
|
|
||||||
S: HashState,
|
|
||||||
<S as HashState>::Hasher: Hasher<Output=u64>,
|
|
||||||
F: FnOnce(T) -> U,
|
|
||||||
{
|
|
||||||
let key = arg.clone();
|
|
||||||
let result = cache.borrow().get(&key).cloned();
|
|
||||||
match result {
|
|
||||||
Some(result) => result,
|
|
||||||
None => {
|
|
||||||
let result = f(arg);
|
|
||||||
cache.borrow_mut().insert(key, result.clone());
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Memoizes a one-argument closure using the given RefCell containing
|
|
||||||
/// a type implementing MutableMap to serve as a cache.
|
|
||||||
///
|
|
||||||
/// In the future the signature of this function is expected to be:
|
|
||||||
/// ```
|
|
||||||
/// pub fn memoized<T: Clone, U: Clone, M: MutableMap<T, U>>(
|
|
||||||
/// cache: &RefCell<M>,
|
|
||||||
/// f: &|T| -> U
|
|
||||||
/// ) -> impl |T| -> U {
|
|
||||||
/// ```
|
|
||||||
/// but currently it is not possible.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
/// ```
|
|
||||||
/// struct Context {
|
|
||||||
/// cache: RefCell<HashMap<uint, uint>>
|
|
||||||
/// }
|
|
||||||
///
|
|
||||||
/// fn factorial(ctxt: &Context, n: uint) -> uint {
|
|
||||||
/// memoized(&ctxt.cache, n, |n| match n {
|
|
||||||
/// 0 | 1 => n,
|
|
||||||
/// _ => factorial(ctxt, n - 2) + factorial(ctxt, n - 1)
|
|
||||||
/// })
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
#[inline(always)]
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub fn memoized<T, U, S, F>(cache: &RefCell<HashMap<T, U, S>>, arg: T, f: F) -> U
|
pub fn memoized<T, U, S, F>(cache: &RefCell<HashMap<T, U, S>>, arg: T, f: F) -> U
|
||||||
where T: Clone + Hash + Eq,
|
where T: Clone + Hash + Eq,
|
||||||
U: Clone,
|
U: Clone,
|
||||||
|
@ -16,7 +16,6 @@ use std::collections::hash_state::{DefaultState};
|
|||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::hash::{Hasher, Hash};
|
use std::hash::{Hasher, Hash};
|
||||||
#[cfg(stage0)] use std::hash::Writer;
|
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
|
|
||||||
pub type FnvHashMap<K, V> = HashMap<K, V, DefaultState<FnvHasher>>;
|
pub type FnvHashMap<K, V> = HashMap<K, V, DefaultState<FnvHasher>>;
|
||||||
@ -28,19 +27,9 @@ pub type DefIdMap<T> = FnvHashMap<ast::DefId, T>;
|
|||||||
pub type NodeSet = FnvHashSet<ast::NodeId>;
|
pub type NodeSet = FnvHashSet<ast::NodeId>;
|
||||||
pub type DefIdSet = FnvHashSet<ast::DefId>;
|
pub type DefIdSet = FnvHashSet<ast::DefId>;
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
pub fn FnvHashMap<K: Hash<FnvHasher> + Eq, V>() -> FnvHashMap<K, V> {
|
|
||||||
Default::default()
|
|
||||||
}
|
|
||||||
#[cfg(stage0)]
|
|
||||||
pub fn FnvHashSet<V: Hash<FnvHasher> + Eq>() -> FnvHashSet<V> {
|
|
||||||
Default::default()
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub fn FnvHashMap<K: Hash + Eq, V>() -> FnvHashMap<K, V> {
|
pub fn FnvHashMap<K: Hash + Eq, V>() -> FnvHashMap<K, V> {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub fn FnvHashSet<V: Hash + Eq>() -> FnvHashSet<V> {
|
pub fn FnvHashSet<V: Hash + Eq>() -> FnvHashSet<V> {
|
||||||
Default::default()
|
Default::default()
|
||||||
}
|
}
|
||||||
@ -63,26 +52,6 @@ impl Default for FnvHasher {
|
|||||||
fn default() -> FnvHasher { FnvHasher(0xcbf29ce484222325) }
|
fn default() -> FnvHasher { FnvHasher(0xcbf29ce484222325) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl Hasher for FnvHasher {
|
|
||||||
type Output = u64;
|
|
||||||
fn reset(&mut self) { *self = Default::default(); }
|
|
||||||
fn finish(&self) -> u64 { self.0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl Writer for FnvHasher {
|
|
||||||
fn write(&mut self, bytes: &[u8]) {
|
|
||||||
let FnvHasher(mut hash) = *self;
|
|
||||||
for byte in bytes {
|
|
||||||
hash = hash ^ (*byte as u64);
|
|
||||||
hash = hash * 0x100000001b3;
|
|
||||||
}
|
|
||||||
*self = FnvHasher(hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl Hasher for FnvHasher {
|
impl Hasher for FnvHasher {
|
||||||
fn write(&mut self, bytes: &[u8]) {
|
fn write(&mut self, bytes: &[u8]) {
|
||||||
let FnvHasher(mut hash) = *self;
|
let FnvHasher(mut hash) = *self;
|
||||||
|
@ -29,7 +29,6 @@ use middle::ty_fold::TypeFoldable;
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::hash_state::HashState;
|
use std::collections::hash_state::HashState;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
#[cfg(stage0)] use std::hash::Hasher;
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
use syntax::ast_map;
|
use syntax::ast_map;
|
||||||
@ -1434,23 +1433,6 @@ impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for ty::Binder<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<'tcx, S, K, V> Repr<'tcx> for HashMap<K, V, S>
|
|
||||||
where K: Hash<<S as HashState>::Hasher> + Eq + Repr<'tcx>,
|
|
||||||
V: Repr<'tcx>,
|
|
||||||
S: HashState,
|
|
||||||
<S as HashState>::Hasher: Hasher<Output=u64>,
|
|
||||||
{
|
|
||||||
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
|
|
||||||
format!("HashMap({})",
|
|
||||||
self.iter()
|
|
||||||
.map(|(k,v)| format!("{} => {}", k.repr(tcx), v.repr(tcx)))
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
.connect(", "))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<'tcx, S, K, V> Repr<'tcx> for HashMap<K, V, S>
|
impl<'tcx, S, K, V> Repr<'tcx> for HashMap<K, V, S>
|
||||||
where K: Hash + Eq + Repr<'tcx>,
|
where K: Hash + Eq + Repr<'tcx>,
|
||||||
V: Repr<'tcx>,
|
V: Repr<'tcx>,
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
use std::usize;
|
use std::usize;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
#[cfg(stage0)] use std::hash::Hasher;
|
|
||||||
use std::collections::hash_state::HashState;
|
use std::collections::hash_state::HashState;
|
||||||
|
|
||||||
use {Decodable, Encodable, Decoder, Encoder};
|
use {Decodable, Encodable, Decoder, Encoder};
|
||||||
@ -158,26 +157,6 @@ impl<
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<K, V, S> Encodable for HashMap<K, V, S>
|
|
||||||
where K: Encodable + Hash< <S as HashState>::Hasher> + Eq,
|
|
||||||
V: Encodable,
|
|
||||||
S: HashState,
|
|
||||||
<S as HashState>::Hasher: Hasher<Output=u64>
|
|
||||||
{
|
|
||||||
fn encode<E: Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
|
|
||||||
e.emit_map(self.len(), |e| {
|
|
||||||
let mut i = 0;
|
|
||||||
for (key, val) in self {
|
|
||||||
try!(e.emit_map_elt_key(i, |e| key.encode(e)));
|
|
||||||
try!(e.emit_map_elt_val(i, |e| val.encode(e)));
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<K, V, S> Encodable for HashMap<K, V, S>
|
impl<K, V, S> Encodable for HashMap<K, V, S>
|
||||||
where K: Encodable + Hash + Eq,
|
where K: Encodable + Hash + Eq,
|
||||||
V: Encodable,
|
V: Encodable,
|
||||||
@ -196,27 +175,6 @@ impl<K, V, S> Encodable for HashMap<K, V, S>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<K, V, S> Decodable for HashMap<K, V, S>
|
|
||||||
where K: Decodable + Hash< <S as HashState>::Hasher> + Eq,
|
|
||||||
V: Decodable,
|
|
||||||
S: HashState + Default,
|
|
||||||
<S as HashState>::Hasher: Hasher<Output=u64>
|
|
||||||
{
|
|
||||||
fn decode<D: Decoder>(d: &mut D) -> Result<HashMap<K, V, S>, D::Error> {
|
|
||||||
d.read_map(|d, len| {
|
|
||||||
let state = Default::default();
|
|
||||||
let mut map = HashMap::with_capacity_and_hash_state(len, state);
|
|
||||||
for i in 0..len {
|
|
||||||
let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
|
|
||||||
let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
|
|
||||||
map.insert(key, val);
|
|
||||||
}
|
|
||||||
Ok(map)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<K, V, S> Decodable for HashMap<K, V, S>
|
impl<K, V, S> Decodable for HashMap<K, V, S>
|
||||||
where K: Decodable + Hash + Eq,
|
where K: Decodable + Hash + Eq,
|
||||||
V: Decodable,
|
V: Decodable,
|
||||||
@ -236,24 +194,6 @@ impl<K, V, S> Decodable for HashMap<K, V, S>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<T, S> Encodable for HashSet<T, S>
|
|
||||||
where T: Encodable + Hash< <S as HashState>::Hasher> + Eq,
|
|
||||||
S: HashState,
|
|
||||||
<S as HashState>::Hasher: Hasher<Output=u64>
|
|
||||||
{
|
|
||||||
fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
|
|
||||||
s.emit_seq(self.len(), |s| {
|
|
||||||
let mut i = 0;
|
|
||||||
for e in self {
|
|
||||||
try!(s.emit_seq_elt(i, |s| e.encode(s)));
|
|
||||||
i += 1;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<T, S> Encodable for HashSet<T, S>
|
impl<T, S> Encodable for HashSet<T, S>
|
||||||
where T: Encodable + Hash + Eq,
|
where T: Encodable + Hash + Eq,
|
||||||
S: HashState,
|
S: HashState,
|
||||||
@ -270,24 +210,6 @@ impl<T, S> Encodable for HashSet<T, S>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<T, S> Decodable for HashSet<T, S>
|
|
||||||
where T: Decodable + Hash< <S as HashState>::Hasher> + Eq,
|
|
||||||
S: HashState + Default,
|
|
||||||
<S as HashState>::Hasher: Hasher<Output=u64>
|
|
||||||
{
|
|
||||||
fn decode<D: Decoder>(d: &mut D) -> Result<HashSet<T, S>, D::Error> {
|
|
||||||
d.read_seq(|d, len| {
|
|
||||||
let state = Default::default();
|
|
||||||
let mut set = HashSet::with_capacity_and_hash_state(len, state);
|
|
||||||
for i in 0..len {
|
|
||||||
set.insert(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
|
|
||||||
}
|
|
||||||
Ok(set)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<T, S> Decodable for HashSet<T, S>
|
impl<T, S> Decodable for HashSet<T, S>
|
||||||
where T: Decodable + Hash + Eq,
|
where T: Decodable + Hash + Eq,
|
||||||
S: HashState + Default,
|
S: HashState + Default,
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -12,14 +12,6 @@
|
|||||||
|
|
||||||
mod bench;
|
mod bench;
|
||||||
mod table;
|
mod table;
|
||||||
#[cfg(stage0)]
|
|
||||||
#[path = "map_stage0.rs"]
|
|
||||||
pub mod map;
|
pub mod map;
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub mod map;
|
|
||||||
#[cfg(stage0)]
|
|
||||||
#[path = "set_stage0.rs"]
|
|
||||||
pub mod set;
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub mod set;
|
pub mod set;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -143,25 +143,6 @@ impl SafeHash {
|
|||||||
/// We need to remove hashes of 0. That's reserved for empty buckets.
|
/// We need to remove hashes of 0. That's reserved for empty buckets.
|
||||||
/// This function wraps up `hash_keyed` to be the only way outside this
|
/// This function wraps up `hash_keyed` to be the only way outside this
|
||||||
/// module to generate a SafeHash.
|
/// module to generate a SafeHash.
|
||||||
#[cfg(stage0)]
|
|
||||||
pub fn make_hash<T: ?Sized, S, H>(hash_state: &S, t: &T) -> SafeHash
|
|
||||||
where T: Hash<H>,
|
|
||||||
S: HashState<Hasher=H>,
|
|
||||||
H: Hasher<Output=u64>
|
|
||||||
{
|
|
||||||
let mut state = hash_state.hasher();
|
|
||||||
t.hash(&mut state);
|
|
||||||
// We need to avoid 0u64 in order to prevent collisions with
|
|
||||||
// EMPTY_HASH. We can maintain our precious uniform distribution
|
|
||||||
// of initial indexes by unconditionally setting the MSB,
|
|
||||||
// effectively reducing 64-bits hashes to 63 bits.
|
|
||||||
SafeHash { hash: 0x8000_0000_0000_0000 | state.finish() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// We need to remove hashes of 0. That's reserved for empty buckets.
|
|
||||||
/// This function wraps up `hash_keyed` to be the only way outside this
|
|
||||||
/// module to generate a SafeHash.
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub fn make_hash<T: ?Sized, S>(hash_state: &S, t: &T) -> SafeHash
|
pub fn make_hash<T: ?Sized, S>(hash_state: &S, t: &T) -> SafeHash
|
||||||
where T: Hash, S: HashState
|
where T: Hash, S: HashState
|
||||||
{
|
{
|
||||||
|
@ -41,7 +41,6 @@ use string::{String, CowString};
|
|||||||
use ops;
|
use ops;
|
||||||
use cmp;
|
use cmp;
|
||||||
use hash::{Hash, Hasher};
|
use hash::{Hash, Hasher};
|
||||||
#[cfg(stage0)] use hash::Writer;
|
|
||||||
use old_path::{Path, GenericPath};
|
use old_path::{Path, GenericPath};
|
||||||
|
|
||||||
use sys::os_str::{Buf, Slice};
|
use sys::os_str::{Buf, Slice};
|
||||||
@ -163,14 +162,6 @@ impl Ord for OsString {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<'a, S: Hasher + Writer> Hash<S> for OsString {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
(&**self).hash(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl Hash for OsString {
|
impl Hash for OsString {
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -263,14 +254,6 @@ impl Ord for OsStr {
|
|||||||
fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
|
fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<'a, S: Hasher + Writer> Hash<S> for OsStr {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
self.bytes().hash(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl Hash for OsStr {
|
impl Hash for OsStr {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -147,21 +147,6 @@ impl PartialEq for Repr {
|
|||||||
}
|
}
|
||||||
impl Eq for Repr {}
|
impl Eq for Repr {}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: hash::Hasher + hash::Writer> hash::Hash<S> for Repr {
|
|
||||||
fn hash(&self, s: &mut S) {
|
|
||||||
match *self {
|
|
||||||
Repr::V4(ref a) => {
|
|
||||||
(a.sin_family, a.sin_port, a.sin_addr.s_addr).hash(s)
|
|
||||||
}
|
|
||||||
Repr::V6(ref a) => {
|
|
||||||
(a.sin6_family, a.sin6_port, &a.sin6_addr.s6_addr,
|
|
||||||
a.sin6_flowinfo, a.sin6_scope_id).hash(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl hash::Hash for Repr {
|
impl hash::Hash for Repr {
|
||||||
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
||||||
|
@ -189,13 +189,6 @@ impl PartialEq for Ipv4Addr {
|
|||||||
}
|
}
|
||||||
impl Eq for Ipv4Addr {}
|
impl Eq for Ipv4Addr {}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: hash::Hasher + hash::Writer> hash::Hash<S> for Ipv4Addr {
|
|
||||||
fn hash(&self, s: &mut S) {
|
|
||||||
self.inner.s_addr.hash(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl hash::Hash for Ipv4Addr {
|
impl hash::Hash for Ipv4Addr {
|
||||||
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
||||||
@ -429,13 +422,6 @@ impl PartialEq for Ipv6Addr {
|
|||||||
}
|
}
|
||||||
impl Eq for Ipv6Addr {}
|
impl Eq for Ipv6Addr {}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: hash::Hasher + hash::Writer> hash::Hash<S> for Ipv6Addr {
|
|
||||||
fn hash(&self, s: &mut S) {
|
|
||||||
self.inner.s6_addr.hash(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl hash::Hash for Ipv6Addr {
|
impl hash::Hash for Ipv6Addr {
|
||||||
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
fn hash<H: hash::Hasher>(&self, s: &mut H) {
|
||||||
|
@ -104,19 +104,7 @@ struct EnvKey(CString);
|
|||||||
#[derive(Eq, Clone, Debug)]
|
#[derive(Eq, Clone, Debug)]
|
||||||
struct EnvKey(CString);
|
struct EnvKey(CString);
|
||||||
|
|
||||||
#[cfg(all(windows, stage0))]
|
#[cfg(windows)]
|
||||||
impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for EnvKey {
|
|
||||||
fn hash(&self, state: &mut H) {
|
|
||||||
let &EnvKey(ref x) = self;
|
|
||||||
match str::from_utf8(x.as_bytes()) {
|
|
||||||
Ok(s) => for ch in s.chars() {
|
|
||||||
(ch as u8 as char).to_lowercase().hash(state);
|
|
||||||
},
|
|
||||||
Err(..) => x.hash(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(all(windows, not(stage0)))]
|
|
||||||
impl hash::Hash for EnvKey {
|
impl hash::Hash for EnvKey {
|
||||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
let &EnvKey(ref x) = self;
|
let &EnvKey(ref x) = self;
|
||||||
|
@ -100,14 +100,6 @@ impl FromStr for Path {
|
|||||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||||
pub struct ParsePathError;
|
pub struct ParsePathError;
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
self.repr.hash(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl hash::Hash for Path {
|
impl hash::Hash for Path {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -127,21 +127,6 @@ impl FromStr for Path {
|
|||||||
#[derive(Debug, Clone, PartialEq, Copy)]
|
#[derive(Debug, Clone, PartialEq, Copy)]
|
||||||
pub struct ParsePathError;
|
pub struct ParsePathError;
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
|
|
||||||
#[cfg(not(test))]
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
self.repr.hash(state)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, _: &mut S) {
|
|
||||||
// No-op because the `hash` implementation will be wrong.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl hash::Hash for Path {
|
impl hash::Hash for Path {
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
|
@ -32,7 +32,6 @@ use borrow::Cow;
|
|||||||
use cmp;
|
use cmp;
|
||||||
use fmt;
|
use fmt;
|
||||||
use hash::{Hash, Hasher};
|
use hash::{Hash, Hasher};
|
||||||
#[cfg(stage0)] use hash::Writer;
|
|
||||||
use iter::{FromIterator, IntoIterator};
|
use iter::{FromIterator, IntoIterator};
|
||||||
use mem;
|
use mem;
|
||||||
use num::Int;
|
use num::Int;
|
||||||
@ -796,14 +795,6 @@ impl<'a> Iterator for EncodeWide<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: Writer + Hasher> Hash<S> for CodePoint {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
self.value.hash(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl Hash for CodePoint {
|
impl Hash for CodePoint {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
@ -811,15 +802,6 @@ impl Hash for CodePoint {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: Writer + Hasher> Hash<S> for Wtf8Buf {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
state.write(&self.bytes);
|
|
||||||
0xfeu8.hash(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl Hash for Wtf8Buf {
|
impl Hash for Wtf8Buf {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
@ -828,15 +810,6 @@ impl Hash for Wtf8Buf {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<'a, S: Writer + Hasher> Hash<S> for Wtf8 {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
state.write(&self.bytes);
|
|
||||||
0xfeu8.hash(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl Hash for Wtf8 {
|
impl Hash for Wtf8 {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
@ -12,8 +12,6 @@ use prelude::v1::*;
|
|||||||
use self::Req::*;
|
use self::Req::*;
|
||||||
|
|
||||||
use collections::HashMap;
|
use collections::HashMap;
|
||||||
#[cfg(stage0)]
|
|
||||||
use collections::hash_map::Hasher;
|
|
||||||
use ffi::CString;
|
use ffi::CString;
|
||||||
use hash::Hash;
|
use hash::Hash;
|
||||||
use old_io::process::{ProcessExit, ExitStatus, ExitSignal};
|
use old_io::process::{ProcessExit, ExitStatus, ExitSignal};
|
||||||
@ -64,223 +62,6 @@ impl Process {
|
|||||||
mkerr_libc(r)
|
mkerr_libc(r)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
|
|
||||||
out_fd: Option<P>, err_fd: Option<P>)
|
|
||||||
-> IoResult<Process>
|
|
||||||
where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
|
|
||||||
K: BytesContainer + Eq + Hash<Hasher>, V: BytesContainer
|
|
||||||
{
|
|
||||||
use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
|
|
||||||
|
|
||||||
mod rustrt {
|
|
||||||
extern {
|
|
||||||
pub fn rust_unset_sigprocmask();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(all(target_os = "android", target_arch = "aarch64"))]
|
|
||||||
unsafe fn getdtablesize() -> c_int {
|
|
||||||
libc::sysconf(libc::consts::os::sysconf::_SC_OPEN_MAX) as c_int
|
|
||||||
}
|
|
||||||
#[cfg(not(all(target_os = "android", target_arch = "aarch64")))]
|
|
||||||
unsafe fn getdtablesize() -> c_int {
|
|
||||||
libc::funcs::bsd44::getdtablesize()
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe fn set_cloexec(fd: c_int) {
|
|
||||||
let ret = c::ioctl(fd, c::FIOCLEX);
|
|
||||||
assert_eq!(ret, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
let dirp = cfg.cwd().map(|c| c.as_ptr()).unwrap_or(ptr::null());
|
|
||||||
|
|
||||||
// temporary until unboxed closures land
|
|
||||||
let cfg = unsafe {
|
|
||||||
mem::transmute::<&ProcessConfig<K,V>,&'static ProcessConfig<K,V>>(cfg)
|
|
||||||
};
|
|
||||||
|
|
||||||
with_envp(cfg.env(), move|envp: *const c_void| {
|
|
||||||
with_argv(cfg.program(), cfg.args(), move|argv: *const *const libc::c_char| unsafe {
|
|
||||||
let (input, mut output) = try!(sys::os::pipe());
|
|
||||||
|
|
||||||
// We may use this in the child, so perform allocations before the
|
|
||||||
// fork
|
|
||||||
let devnull = b"/dev/null\0";
|
|
||||||
|
|
||||||
set_cloexec(output.fd());
|
|
||||||
|
|
||||||
let pid = fork();
|
|
||||||
if pid < 0 {
|
|
||||||
return Err(super::last_error())
|
|
||||||
} else if pid > 0 {
|
|
||||||
#[inline]
|
|
||||||
fn combine(arr: &[u8]) -> i32 {
|
|
||||||
let a = arr[0] as u32;
|
|
||||||
let b = arr[1] as u32;
|
|
||||||
let c = arr[2] as u32;
|
|
||||||
let d = arr[3] as u32;
|
|
||||||
|
|
||||||
((a << 24) | (b << 16) | (c << 8) | (d << 0)) as i32
|
|
||||||
}
|
|
||||||
|
|
||||||
let p = Process{ pid: pid };
|
|
||||||
drop(output);
|
|
||||||
let mut bytes = [0; 8];
|
|
||||||
return match input.read(&mut bytes) {
|
|
||||||
Ok(8) => {
|
|
||||||
assert!(combine(CLOEXEC_MSG_FOOTER) == combine(&bytes[4.. 8]),
|
|
||||||
"Validation on the CLOEXEC pipe failed: {:?}", bytes);
|
|
||||||
let errno = combine(&bytes[0.. 4]);
|
|
||||||
assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
|
|
||||||
Err(super::decode_error(errno))
|
|
||||||
}
|
|
||||||
Err(ref e) if e.kind == EndOfFile => Ok(p),
|
|
||||||
Err(e) => {
|
|
||||||
assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
|
|
||||||
panic!("the CLOEXEC pipe failed: {:?}", e)
|
|
||||||
},
|
|
||||||
Ok(..) => { // pipe I/O up to PIPE_BUF bytes should be atomic
|
|
||||||
assert!(p.wait(0).is_ok(), "wait(0) should either return Ok or panic");
|
|
||||||
panic!("short read on the CLOEXEC pipe")
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// And at this point we've reached a special time in the life of the
|
|
||||||
// child. The child must now be considered hamstrung and unable to
|
|
||||||
// do anything other than syscalls really. Consider the following
|
|
||||||
// scenario:
|
|
||||||
//
|
|
||||||
// 1. Thread A of process 1 grabs the malloc() mutex
|
|
||||||
// 2. Thread B of process 1 forks(), creating thread C
|
|
||||||
// 3. Thread C of process 2 then attempts to malloc()
|
|
||||||
// 4. The memory of process 2 is the same as the memory of
|
|
||||||
// process 1, so the mutex is locked.
|
|
||||||
//
|
|
||||||
// This situation looks a lot like deadlock, right? It turns out
|
|
||||||
// that this is what pthread_atfork() takes care of, which is
|
|
||||||
// presumably implemented across platforms. The first thing that
|
|
||||||
// threads to *before* forking is to do things like grab the malloc
|
|
||||||
// mutex, and then after the fork they unlock it.
|
|
||||||
//
|
|
||||||
// Despite this information, libnative's spawn has been witnessed to
|
|
||||||
// deadlock on both OSX and FreeBSD. I'm not entirely sure why, but
|
|
||||||
// all collected backtraces point at malloc/free traffic in the
|
|
||||||
// child spawned process.
|
|
||||||
//
|
|
||||||
// For this reason, the block of code below should contain 0
|
|
||||||
// invocations of either malloc of free (or their related friends).
|
|
||||||
//
|
|
||||||
// As an example of not having malloc/free traffic, we don't close
|
|
||||||
// this file descriptor by dropping the FileDesc (which contains an
|
|
||||||
// allocation). Instead we just close it manually. This will never
|
|
||||||
// have the drop glue anyway because this code never returns (the
|
|
||||||
// child will either exec() or invoke libc::exit)
|
|
||||||
let _ = libc::close(input.fd());
|
|
||||||
|
|
||||||
fn fail(output: &mut FileDesc) -> ! {
|
|
||||||
let errno = sys::os::errno() as u32;
|
|
||||||
let bytes = [
|
|
||||||
(errno >> 24) as u8,
|
|
||||||
(errno >> 16) as u8,
|
|
||||||
(errno >> 8) as u8,
|
|
||||||
(errno >> 0) as u8,
|
|
||||||
CLOEXEC_MSG_FOOTER[0], CLOEXEC_MSG_FOOTER[1],
|
|
||||||
CLOEXEC_MSG_FOOTER[2], CLOEXEC_MSG_FOOTER[3]
|
|
||||||
];
|
|
||||||
// pipe I/O up to PIPE_BUF bytes should be atomic
|
|
||||||
assert!(output.write(&bytes).is_ok());
|
|
||||||
unsafe { libc::_exit(1) }
|
|
||||||
}
|
|
||||||
|
|
||||||
rustrt::rust_unset_sigprocmask();
|
|
||||||
|
|
||||||
// If a stdio file descriptor is set to be ignored (via a -1 file
|
|
||||||
// descriptor), then we don't actually close it, but rather open
|
|
||||||
// up /dev/null into that file descriptor. Otherwise, the first file
|
|
||||||
// descriptor opened up in the child would be numbered as one of the
|
|
||||||
// stdio file descriptors, which is likely to wreak havoc.
|
|
||||||
let setup = |src: Option<P>, dst: c_int| {
|
|
||||||
let src = match src {
|
|
||||||
None => {
|
|
||||||
let flags = if dst == libc::STDIN_FILENO {
|
|
||||||
libc::O_RDONLY
|
|
||||||
} else {
|
|
||||||
libc::O_RDWR
|
|
||||||
};
|
|
||||||
libc::open(devnull.as_ptr() as *const _, flags, 0)
|
|
||||||
}
|
|
||||||
Some(obj) => {
|
|
||||||
let fd = obj.as_inner().fd();
|
|
||||||
// Leak the memory and the file descriptor. We're in the
|
|
||||||
// child now an all our resources are going to be
|
|
||||||
// cleaned up very soon
|
|
||||||
mem::forget(obj);
|
|
||||||
fd
|
|
||||||
}
|
|
||||||
};
|
|
||||||
src != -1 && retry(|| dup2(src, dst)) != -1
|
|
||||||
};
|
|
||||||
|
|
||||||
if !setup(in_fd, libc::STDIN_FILENO) { fail(&mut output) }
|
|
||||||
if !setup(out_fd, libc::STDOUT_FILENO) { fail(&mut output) }
|
|
||||||
if !setup(err_fd, libc::STDERR_FILENO) { fail(&mut output) }
|
|
||||||
|
|
||||||
// close all other fds
|
|
||||||
for fd in (3..getdtablesize()).rev() {
|
|
||||||
if fd != output.fd() {
|
|
||||||
let _ = close(fd as c_int);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match cfg.gid() {
|
|
||||||
Some(u) => {
|
|
||||||
if libc::setgid(u as libc::gid_t) != 0 {
|
|
||||||
fail(&mut output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
match cfg.uid() {
|
|
||||||
Some(u) => {
|
|
||||||
// When dropping privileges from root, the `setgroups` call
|
|
||||||
// will remove any extraneous groups. If we don't call this,
|
|
||||||
// then even though our uid has dropped, we may still have
|
|
||||||
// groups that enable us to do super-user things. This will
|
|
||||||
// fail if we aren't root, so don't bother checking the
|
|
||||||
// return value, this is just done as an optimistic
|
|
||||||
// privilege dropping function.
|
|
||||||
extern {
|
|
||||||
fn setgroups(ngroups: libc::c_int,
|
|
||||||
ptr: *const libc::c_void) -> libc::c_int;
|
|
||||||
}
|
|
||||||
let _ = setgroups(0, ptr::null());
|
|
||||||
|
|
||||||
if libc::setuid(u as libc::uid_t) != 0 {
|
|
||||||
fail(&mut output);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
if cfg.detach() {
|
|
||||||
// Don't check the error of setsid because it fails if we're the
|
|
||||||
// process leader already. We just forked so it shouldn't return
|
|
||||||
// error, but ignore it anyway.
|
|
||||||
let _ = libc::setsid();
|
|
||||||
}
|
|
||||||
if !dirp.is_null() && chdir(dirp) == -1 {
|
|
||||||
fail(&mut output);
|
|
||||||
}
|
|
||||||
if !envp.is_null() {
|
|
||||||
*sys::os::environ() = envp as *const _;
|
|
||||||
}
|
|
||||||
let _ = execvp(*argv, argv as *mut _);
|
|
||||||
fail(&mut output);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
|
pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
|
||||||
out_fd: Option<P>, err_fd: Option<P>)
|
out_fd: Option<P>, err_fd: Option<P>)
|
||||||
-> IoResult<Process>
|
-> IoResult<Process>
|
||||||
@ -766,45 +547,6 @@ fn with_argv<T,F>(prog: &CString, args: &[CString],
|
|||||||
cb(ptrs.as_ptr())
|
cb(ptrs.as_ptr())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
|
|
||||||
cb: F)
|
|
||||||
-> T
|
|
||||||
where F : FnOnce(*const c_void) -> T,
|
|
||||||
K : BytesContainer + Eq + Hash<Hasher>,
|
|
||||||
V : BytesContainer
|
|
||||||
{
|
|
||||||
// On posixy systems we can pass a char** for envp, which is a
|
|
||||||
// null-terminated array of "k=v\0" strings. Since we must create
|
|
||||||
// these strings locally, yet expose a raw pointer to them, we
|
|
||||||
// create a temporary vector to own the CStrings that outlives the
|
|
||||||
// call to cb.
|
|
||||||
match env {
|
|
||||||
Some(env) => {
|
|
||||||
let mut tmps = Vec::with_capacity(env.len());
|
|
||||||
|
|
||||||
for pair in env {
|
|
||||||
let mut kv = Vec::new();
|
|
||||||
kv.push_all(pair.0.container_as_bytes());
|
|
||||||
kv.push('=' as u8);
|
|
||||||
kv.push_all(pair.1.container_as_bytes());
|
|
||||||
kv.push(0); // terminating null
|
|
||||||
tmps.push(kv);
|
|
||||||
}
|
|
||||||
|
|
||||||
// As with `with_argv`, this is unsafe, since cb could leak the pointers.
|
|
||||||
let mut ptrs: Vec<*const libc::c_char> =
|
|
||||||
tmps.iter()
|
|
||||||
.map(|tmp| tmp.as_ptr() as *const libc::c_char)
|
|
||||||
.collect();
|
|
||||||
ptrs.push(ptr::null());
|
|
||||||
|
|
||||||
cb(ptrs.as_ptr() as *const c_void)
|
|
||||||
}
|
|
||||||
_ => cb(ptr::null())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
|
fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
|
||||||
cb: F)
|
cb: F)
|
||||||
-> T
|
-> T
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
|
|
||||||
use prelude::v1::*;
|
use prelude::v1::*;
|
||||||
|
|
||||||
#[cfg(stage0)] use collections::hash_map::Hasher;
|
|
||||||
use collections;
|
use collections;
|
||||||
use env;
|
use env;
|
||||||
use ffi::CString;
|
use ffi::CString;
|
||||||
@ -106,170 +105,6 @@ impl Process {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
#[cfg(stage0)]
|
|
||||||
pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
|
|
||||||
out_fd: Option<P>, err_fd: Option<P>)
|
|
||||||
-> IoResult<Process>
|
|
||||||
where C: ProcessConfig<K, V>, P: AsInner<FileDesc>,
|
|
||||||
K: BytesContainer + Eq + Hash<Hasher>, V: BytesContainer
|
|
||||||
{
|
|
||||||
use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO};
|
|
||||||
use libc::consts::os::extra::{
|
|
||||||
TRUE, FALSE,
|
|
||||||
STARTF_USESTDHANDLES,
|
|
||||||
INVALID_HANDLE_VALUE,
|
|
||||||
DUPLICATE_SAME_ACCESS
|
|
||||||
};
|
|
||||||
use libc::funcs::extra::kernel32::{
|
|
||||||
GetCurrentProcess,
|
|
||||||
DuplicateHandle,
|
|
||||||
CloseHandle,
|
|
||||||
CreateProcessW
|
|
||||||
};
|
|
||||||
use libc::funcs::extra::msvcrt::get_osfhandle;
|
|
||||||
|
|
||||||
use mem;
|
|
||||||
use iter::IteratorExt;
|
|
||||||
use str::StrExt;
|
|
||||||
|
|
||||||
if cfg.gid().is_some() || cfg.uid().is_some() {
|
|
||||||
return Err(IoError {
|
|
||||||
kind: old_io::IoUnavailable,
|
|
||||||
desc: "unsupported gid/uid requested on windows",
|
|
||||||
detail: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// To have the spawning semantics of unix/windows stay the same, we need to
|
|
||||||
// read the *child's* PATH if one is provided. See #15149 for more details.
|
|
||||||
let program = cfg.env().and_then(|env| {
|
|
||||||
for (key, v) in env {
|
|
||||||
if b"PATH" != key.container_as_bytes() { continue }
|
|
||||||
|
|
||||||
// Split the value and test each path to see if the
|
|
||||||
// program exists.
|
|
||||||
for path in os::split_paths(v.container_as_bytes()) {
|
|
||||||
let path = path.join(cfg.program().as_bytes())
|
|
||||||
.with_extension(env::consts::EXE_EXTENSION);
|
|
||||||
if path.exists() {
|
|
||||||
return Some(CString::from_slice(path.as_vec()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
None
|
|
||||||
});
|
|
||||||
|
|
||||||
unsafe {
|
|
||||||
let mut si = zeroed_startupinfo();
|
|
||||||
si.cb = mem::size_of::<STARTUPINFO>() as DWORD;
|
|
||||||
si.dwFlags = STARTF_USESTDHANDLES;
|
|
||||||
|
|
||||||
let cur_proc = GetCurrentProcess();
|
|
||||||
|
|
||||||
// Similarly to unix, we don't actually leave holes for the stdio file
|
|
||||||
// descriptors, but rather open up /dev/null equivalents. These
|
|
||||||
// equivalents are drawn from libuv's windows process spawning.
|
|
||||||
let set_fd = |fd: &Option<P>, slot: &mut HANDLE,
|
|
||||||
is_stdin: bool| {
|
|
||||||
match *fd {
|
|
||||||
None => {
|
|
||||||
let access = if is_stdin {
|
|
||||||
libc::FILE_GENERIC_READ
|
|
||||||
} else {
|
|
||||||
libc::FILE_GENERIC_WRITE | libc::FILE_READ_ATTRIBUTES
|
|
||||||
};
|
|
||||||
let size = mem::size_of::<libc::SECURITY_ATTRIBUTES>();
|
|
||||||
let mut sa = libc::SECURITY_ATTRIBUTES {
|
|
||||||
nLength: size as libc::DWORD,
|
|
||||||
lpSecurityDescriptor: ptr::null_mut(),
|
|
||||||
bInheritHandle: 1,
|
|
||||||
};
|
|
||||||
let mut filename: Vec<u16> = "NUL".utf16_units().collect();
|
|
||||||
filename.push(0);
|
|
||||||
*slot = libc::CreateFileW(filename.as_ptr(),
|
|
||||||
access,
|
|
||||||
libc::FILE_SHARE_READ |
|
|
||||||
libc::FILE_SHARE_WRITE,
|
|
||||||
&mut sa,
|
|
||||||
libc::OPEN_EXISTING,
|
|
||||||
0,
|
|
||||||
ptr::null_mut());
|
|
||||||
if *slot == INVALID_HANDLE_VALUE {
|
|
||||||
return Err(super::last_error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(ref fd) => {
|
|
||||||
let orig = get_osfhandle(fd.as_inner().fd()) as HANDLE;
|
|
||||||
if orig == INVALID_HANDLE_VALUE {
|
|
||||||
return Err(super::last_error())
|
|
||||||
}
|
|
||||||
if DuplicateHandle(cur_proc, orig, cur_proc, slot,
|
|
||||||
0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
|
|
||||||
return Err(super::last_error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
};
|
|
||||||
|
|
||||||
try!(set_fd(&in_fd, &mut si.hStdInput, true));
|
|
||||||
try!(set_fd(&out_fd, &mut si.hStdOutput, false));
|
|
||||||
try!(set_fd(&err_fd, &mut si.hStdError, false));
|
|
||||||
|
|
||||||
let cmd_str = make_command_line(program.as_ref().unwrap_or(cfg.program()),
|
|
||||||
cfg.args());
|
|
||||||
let mut pi = zeroed_process_information();
|
|
||||||
let mut create_err = None;
|
|
||||||
|
|
||||||
// stolen from the libuv code.
|
|
||||||
let mut flags = libc::CREATE_UNICODE_ENVIRONMENT;
|
|
||||||
if cfg.detach() {
|
|
||||||
flags |= libc::DETACHED_PROCESS | libc::CREATE_NEW_PROCESS_GROUP;
|
|
||||||
}
|
|
||||||
|
|
||||||
with_envp(cfg.env(), |envp| {
|
|
||||||
with_dirp(cfg.cwd(), |dirp| {
|
|
||||||
let mut cmd_str: Vec<u16> = cmd_str.utf16_units().collect();
|
|
||||||
cmd_str.push(0);
|
|
||||||
let _lock = CREATE_PROCESS_LOCK.lock().unwrap();
|
|
||||||
let created = CreateProcessW(ptr::null(),
|
|
||||||
cmd_str.as_mut_ptr(),
|
|
||||||
ptr::null_mut(),
|
|
||||||
ptr::null_mut(),
|
|
||||||
TRUE,
|
|
||||||
flags, envp, dirp,
|
|
||||||
&mut si, &mut pi);
|
|
||||||
if created == FALSE {
|
|
||||||
create_err = Some(super::last_error());
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
assert!(CloseHandle(si.hStdInput) != 0);
|
|
||||||
assert!(CloseHandle(si.hStdOutput) != 0);
|
|
||||||
assert!(CloseHandle(si.hStdError) != 0);
|
|
||||||
|
|
||||||
match create_err {
|
|
||||||
Some(err) => return Err(err),
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We close the thread handle because we don't care about keeping the
|
|
||||||
// thread id valid, and we aren't keeping the thread handle around to be
|
|
||||||
// able to close it later. We don't close the process handle however
|
|
||||||
// because std::we want the process id to stay valid at least until the
|
|
||||||
// calling code closes the process handle.
|
|
||||||
assert!(CloseHandle(pi.hThread) != 0);
|
|
||||||
|
|
||||||
Ok(Process {
|
|
||||||
pid: pi.dwProcessId as pid_t,
|
|
||||||
handle: pi.hProcess as *mut ()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[allow(deprecated)]
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
|
pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
|
||||||
out_fd: Option<P>, err_fd: Option<P>)
|
out_fd: Option<P>, err_fd: Option<P>)
|
||||||
-> IoResult<Process>
|
-> IoResult<Process>
|
||||||
@ -589,35 +424,6 @@ fn make_command_line(prog: &CString, args: &[CString]) -> String {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
fn with_envp<K, V, T, F>(env: Option<&collections::HashMap<K, V>>, cb: F) -> T
|
|
||||||
where K: BytesContainer + Eq + Hash<Hasher>,
|
|
||||||
V: BytesContainer,
|
|
||||||
F: FnOnce(*mut c_void) -> T,
|
|
||||||
{
|
|
||||||
// On Windows we pass an "environment block" which is not a char**, but
|
|
||||||
// rather a concatenation of null-terminated k=v\0 sequences, with a final
|
|
||||||
// \0 to terminate.
|
|
||||||
match env {
|
|
||||||
Some(env) => {
|
|
||||||
let mut blk = Vec::new();
|
|
||||||
|
|
||||||
for pair in env {
|
|
||||||
let kv = format!("{}={}",
|
|
||||||
pair.0.container_as_str().unwrap(),
|
|
||||||
pair.1.container_as_str().unwrap());
|
|
||||||
blk.extend(kv.utf16_units());
|
|
||||||
blk.push(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
blk.push(0);
|
|
||||||
|
|
||||||
cb(blk.as_mut_ptr() as *mut c_void)
|
|
||||||
}
|
|
||||||
_ => cb(ptr::null_mut())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
fn with_envp<K, V, T, F>(env: Option<&collections::HashMap<K, V>>, cb: F) -> T
|
fn with_envp<K, V, T, F>(env: Option<&collections::HashMap<K, V>>, cb: F) -> T
|
||||||
where K: BytesContainer + Eq + Hash,
|
where K: BytesContainer + Eq + Hash,
|
||||||
V: BytesContainer,
|
V: BytesContainer,
|
||||||
|
@ -17,9 +17,6 @@ use core::marker::Send;
|
|||||||
use core::ops::FnOnce;
|
use core::ops::FnOnce;
|
||||||
|
|
||||||
pub struct Thunk<'a, A=(),R=()> {
|
pub struct Thunk<'a, A=(),R=()> {
|
||||||
#[cfg(stage0)]
|
|
||||||
invoke: Box<Invoke<A,R>+Send>,
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
invoke: Box<Invoke<A,R>+Send + 'a>,
|
invoke: Box<Invoke<A,R>+Send + 'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,13 +111,6 @@ impl<T: Display> Display for P<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<S: Hasher, T: Hash<S>> Hash<S> for P<T> {
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
(**self).hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<T: Hash> Hash for P<T> {
|
impl<T: Hash> Hash for P<T> {
|
||||||
fn hash<H: Hasher>(&self, state: &mut H) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
(**self).hash(state);
|
(**self).hash(state);
|
||||||
|
@ -18,7 +18,6 @@ use std::borrow::Borrow;
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
#[cfg(stage0)] use std::collections::hash_map::Hasher;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
@ -30,71 +29,6 @@ pub struct Interner<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// when traits can extend traits, we should extend index<Name,T> to get []
|
// when traits can extend traits, we should extend index<Name,T> to get []
|
||||||
#[cfg(stage0)]
|
|
||||||
impl<T: Eq + Hash<Hasher> + Clone + 'static> Interner<T> {
|
|
||||||
pub fn new() -> Interner<T> {
|
|
||||||
Interner {
|
|
||||||
map: RefCell::new(HashMap::new()),
|
|
||||||
vect: RefCell::new(Vec::new()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn prefill(init: &[T]) -> Interner<T> {
|
|
||||||
let rv = Interner::new();
|
|
||||||
for v in init {
|
|
||||||
rv.intern((*v).clone());
|
|
||||||
}
|
|
||||||
rv
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn intern(&self, val: T) -> Name {
|
|
||||||
let mut map = self.map.borrow_mut();
|
|
||||||
match (*map).get(&val) {
|
|
||||||
Some(&idx) => return idx,
|
|
||||||
None => (),
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut vect = self.vect.borrow_mut();
|
|
||||||
let new_idx = Name((*vect).len() as u32);
|
|
||||||
(*map).insert(val.clone(), new_idx);
|
|
||||||
(*vect).push(val);
|
|
||||||
new_idx
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn gensym(&self, val: T) -> Name {
|
|
||||||
let mut vect = self.vect.borrow_mut();
|
|
||||||
let new_idx = Name((*vect).len() as u32);
|
|
||||||
// leave out of .map to avoid colliding
|
|
||||||
(*vect).push(val);
|
|
||||||
new_idx
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get(&self, idx: Name) -> T {
|
|
||||||
let vect = self.vect.borrow();
|
|
||||||
(*vect)[idx.usize()].clone()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
let vect = self.vect.borrow();
|
|
||||||
(*vect).len()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
|
|
||||||
where T: Borrow<Q>, Q: Eq + Hash<Hasher> {
|
|
||||||
let map = self.map.borrow();
|
|
||||||
match (*map).get(val) {
|
|
||||||
Some(v) => Some(*v),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn clear(&self) {
|
|
||||||
*self.map.borrow_mut() = HashMap::new();
|
|
||||||
*self.vect.borrow_mut() = Vec::new();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// when traits can extend traits, we should extend index<Name,T> to get []
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
impl<T: Eq + Hash + Clone + 'static> Interner<T> {
|
impl<T: Eq + Hash + Clone + 'static> Interner<T> {
|
||||||
pub fn new() -> Interner<T> {
|
pub fn new() -> Interner<T> {
|
||||||
Interner {
|
Interner {
|
||||||
@ -275,15 +209,6 @@ impl StrInterner {
|
|||||||
self.vect.borrow().len()
|
self.vect.borrow().len()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(stage0)]
|
|
||||||
pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
|
|
||||||
where RcStr: Borrow<Q>, Q: Eq + Hash<Hasher> {
|
|
||||||
match (*self.map.borrow()).get(val) {
|
|
||||||
Some(v) => Some(*v),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#[cfg(not(stage0))]
|
|
||||||
pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
|
pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
|
||||||
where RcStr: Borrow<Q>, Q: Eq + Hash {
|
where RcStr: Borrow<Q>, Q: Eq + Hash {
|
||||||
match (*self.map.borrow()).get(val) {
|
match (*self.map.borrow()).get(val) {
|
||||||
|
@ -1,3 +1,12 @@
|
|||||||
|
S 2015-02-19 522d09d
|
||||||
|
freebsd-x86_64 7ea14ef85a25bca70a310a2cd660b356cf61abc7
|
||||||
|
linux-i386 26e3caa1ce1c482b9941a6bdc64b3e65d036c200
|
||||||
|
linux-x86_64 44f514aabb4e4049e4db9a4e1fdeb16f6cee60f2
|
||||||
|
macos-i386 157910592224083df56f5f31ced3e6f3dc9b1de0
|
||||||
|
macos-x86_64 56c28aa0e14ec6991ad6ca213568f1155561105d
|
||||||
|
winnt-i386 da0f7a3fbc913fbb177917f2850bb41501affb5c
|
||||||
|
winnt-x86_64 22bd816ccd2690fc9804b27ca525f603be8aeaa5
|
||||||
|
|
||||||
S 2015-02-17 f1bb6c2
|
S 2015-02-17 f1bb6c2
|
||||||
freebsd-x86_64 59f3a2c6350c170804fb65838e1b504eeab89105
|
freebsd-x86_64 59f3a2c6350c170804fb65838e1b504eeab89105
|
||||||
linux-i386 191ed5ec4f17e32d36abeade55a1c6085e51245c
|
linux-i386 191ed5ec4f17e32d36abeade55a1c6085e51245c
|
||||||
|
Loading…
Reference in New Issue
Block a user