# The Rust Programming Language
This is a compiler for Rust, including standard libraries, tools and
-documentation.
+documentation. Rust is a systems programming language that is fast,
+memory safe and multithreaded, but does not employ a garbage collector
+or otherwise impose significant runtime overhead.
## Quick Start
-Read ["Installing Rust"][install] from [The Book][trpl].
+Read ["Installing Rust"] from [The Book].
-[install]: http://doc.rust-lang.org/book/installing-rust.html
-[trpl]: http://doc.rust-lang.org/book/index.html
+["Installing Rust"]: http://doc.rust-lang.org/book/installing-rust.html
+[The Book]: http://doc.rust-lang.org/book/index.html
## Building from Source
* `curl`
* `git`
-2. Download and build Rust:
-
- You can either download a [tarball] or build directly from the [repo].
-
- To build from the [tarball] do:
-
- $ curl -O https://static.rust-lang.org/dist/rustc-nightly-src.tar.gz
- $ tar -xzf rustc-nightly-src.tar.gz
- $ cd rustc-nightly
-
- Or to build from the [repo] do:
+2. Clone the [source] with `git`:
$ git clone https://github.com/rust-lang/rust.git
$ cd rust
- Now that you have Rust's source code, you can configure and build it:
+[source]: https://github.com/rust-lang/rust
+
+3. Build and install:
$ ./configure
$ make && make install
When complete, `make install` will place several programs into
`/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the
- API-documentation tool.
+ API-documentation tool. This install does not include [Cargo],
+ Rust's package manager, which you may also want to build.
+
+[Cargo]: https://github.com/rust-lang/cargo
### Building on Windows
$ ./configure
$ make && make install
-[repo]: https://github.com/rust-lang/rust
-[tarball]: https://static.rust-lang.org/dist/rustc-nightly-src.tar.gz
-
## Notes
Since the Rust compiler is written in Rust, it must be built by a
Rust currently needs about 1.5 GiB of RAM to build without swapping; if it hits
swap, it will take a very long time to build.
-There is a lot more documentation in the [wiki].
+There is more advice about hacking on Rust in [CONTRIBUTING.md].
-[wiki]: https://github.com/rust-lang/rust/wiki
+[CONTRIBUTING.md]: https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md
## Getting help
To contribute to Rust, please see [CONTRIBUTING.md](CONTRIBUTING.md).
+Rust has an [IRC] culture and most real-time collaboration happens in a
+variety of channels on Mozilla's IRC network, irc.mozilla.org. The
+most popular channel is [#rust], a venue for general discussion about
+Rust, and a good place to ask for help,
+
+[IRC]: https://en.wikipedia.org/wiki/Internet_Relay_Chat
+[#rust]: irc://irc.mozilla.org/rust
+
## License
Rust is primarily distributed under the terms of both the MIT license
make_dir $h/test/run-pass-fulldeps
make_dir $h/test/run-fail
make_dir $h/test/compile-fail
+ make_dir $h/test/parse-fail
make_dir $h/test/compile-fail-fulldeps
make_dir $h/test/bench
make_dir $h/test/perf
check-lite: cleantestlibs cleantmptestlogs \
$(foreach crate,$(TEST_TARGET_CRATES),check-stage2-$(crate)) \
check-stage2-rpass check-stage2-rpass-valgrind \
- check-stage2-rfail check-stage2-cfail check-stage2-rmake
+ check-stage2-rfail check-stage2-cfail check-stage2-pfail check-stage2-rmake
$(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
# Only check the 'reference' tests: rpass/cfail/rfail/rmake.
check-ref: cleantestlibs cleantmptestlogs check-stage2-rpass check-stage2-rpass-valgrind \
- check-stage2-rfail check-stage2-cfail check-stage2-rmake
+ check-stage2-rfail check-stage2-cfail check-stage2-pfail check-stage2-rmake
$(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
# Only check the docs.
check-stage$(1)-T-$(2)-H-$(3)-rpass-exec \
check-stage$(1)-T-$(2)-H-$(3)-rfail-exec \
check-stage$(1)-T-$(2)-H-$(3)-cfail-exec \
+ check-stage$(1)-T-$(2)-H-$(3)-pfail-exec \
check-stage$(1)-T-$(2)-H-$(3)-rpass-valgrind-exec \
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-cfail-full-exec \
RPASS_FULL_TESTS := $(RPASS_FULL_RS)
CFAIL_FULL_TESTS := $(CFAIL_FULL_RS)
RFAIL_TESTS := $(RFAIL_RS)
-CFAIL_TESTS := $(CFAIL_RS) $(PFAIL_RS)
+CFAIL_TESTS := $(CFAIL_RS)
+PFAIL_TESTS := $(PFAIL_RS)
BENCH_TESTS := $(BENCH_RS)
PERF_TESTS := $(PERF_RS)
PRETTY_TESTS := $(PRETTY_RS)
CTEST_MODE_cfail = compile-fail
CTEST_RUNTOOL_cfail = $(CTEST_RUNTOOL)
+CTEST_SRC_BASE_pfail = parse-fail
+CTEST_BUILD_BASE_pfail = parse-fail
+CTEST_MODE_pfail = parse-fail
+CTEST_RUNTOOL_pfail = $(CTEST_RUNTOOL)
+
CTEST_SRC_BASE_bench = bench
CTEST_BUILD_BASE_bench = bench
CTEST_MODE_bench = run-pass
CTEST_DEPS_cfail-full_$(1)-T-$(2)-H-$(3) = $$(CFAIL_FULL_TESTS) $$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
CTEST_DEPS_rfail_$(1)-T-$(2)-H-$(3) = $$(RFAIL_TESTS)
CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_TESTS)
+CTEST_DEPS_pfail_$(1)-T-$(2)-H-$(3) = $$(PFAIL_TESTS)
CTEST_DEPS_bench_$(1)-T-$(2)-H-$(3) = $$(BENCH_TESTS)
CTEST_DEPS_perf_$(1)-T-$(2)-H-$(3) = $$(PERF_TESTS)
CTEST_DEPS_debuginfo-gdb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_GDB_TESTS)
endef
-CTEST_NAMES = rpass rpass-valgrind rpass-full cfail-full rfail cfail bench perf debuginfo-gdb debuginfo-lldb codegen
+CTEST_NAMES = rpass rpass-valgrind rpass-full cfail-full rfail cfail pfail bench perf debuginfo-gdb debuginfo-lldb codegen
$(foreach host,$(CFG_HOST), \
$(eval $(foreach target,$(CFG_TARGET), \
cfail-full \
rfail \
cfail \
+ pfail \
bench \
perf \
rmake \
#[derive(Clone, Copy, PartialEq, Debug)]
pub enum Mode {
CompileFail,
+ ParseFail,
RunFail,
RunPass,
RunPassValgrind,
fn from_str(s: &str) -> Result<Mode, ()> {
match s {
"compile-fail" => Ok(CompileFail),
+ "parse-fail" => Ok(ParseFail),
"run-fail" => Ok(RunFail),
"run-pass" => Ok(RunPass),
"run-pass-valgrind" => Ok(RunPassValgrind),
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(match *self {
CompileFail => "compile-fail",
+ ParseFail => "parse-fail",
RunFail => "run-fail",
RunPass => "run-pass",
RunPassValgrind => "run-pass-valgrind",
#![feature(test)]
#![feature(unicode)]
#![feature(env)]
+#![feature(core)]
#![deny(warnings)]
reqopt("", "aux-base", "directory to find auxiliary test files", "PATH"),
reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET"),
reqopt("", "mode", "which sort of compile tests to run",
- "(compile-fail|run-fail|run-pass|run-pass-valgrind|pretty|debug-info)"),
+ "(compile-fail|parse-fail|run-fail|run-pass|run-pass-valgrind|pretty|debug-info)"),
optflag("", "ignored", "run tests marked as ignored"),
optopt("", "runtool", "supervisor program to run tests under \
(eg. emulator, valgrind)", "PROGRAM"),
use self::TargetLocation::*;
use common::Config;
-use common::{CompileFail, Pretty, RunFail, RunPass, RunPassValgrind, DebugInfoGdb};
+use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind, DebugInfoGdb};
use common::{Codegen, DebugInfoLldb};
use errors;
use header::TestProps;
debug!("loaded props");
match config.mode {
CompileFail => run_cfail_test(&config, &props, &testfile),
+ ParseFail => run_cfail_test(&config, &props, &testfile),
RunFail => run_rfail_test(&config, &props, &testfile),
RunPass => run_rpass_test(&config, &props, &testfile),
RunPassValgrind => run_valgrind_test(&config, &props, &testfile),
let proc_res = compile_test(config, props, testfile);
if proc_res.status.success() {
- fatal_proc_rec("compile-fail test compiled successfully!",
+ fatal_proc_rec(&format!("{} test compiled successfully!", config.mode)[],
&proc_res);
}
.unwrap()
.to_string();
- script_str.push_str(&format!("command script import {}\n", &rust_pp_module_abs_path[])[]);
+ script_str.push_str(&format!("command script import {}\n", &rust_pp_module_abs_path[..])[]);
script_str.push_str("type summary add --no-value ");
script_str.push_str("--python-function lldb_rust_formatters.print_val ");
script_str.push_str("-x \".*\" --category Rust\n");
// FIXME (#9639): This needs to handle non-utf8 paths
let mut link_args = vec!("-L".to_string(),
aux_dir.as_str().unwrap().to_string());
- link_args.extend(extra_args.iter().map(|s| s.clone()));
+ link_args.extend(extra_args.iter().cloned());
let args = make_compile_args(config,
props,
link_args,
Two examples of paths with type arguments:
```
-# struct HashMap<K, V>;
+# struct HashMap<K, V>(K,V);
# fn f() {
# fn id<T>(t: T) -> T { t }
type T = HashMap<i32,String>; // Type arguments used in a type expression
trait is in scope) to pointers to the trait name, used as a type.
```
-# trait Shape { }
+# trait Shape { fn dummy(&self) { } }
# impl Shape for i32 { }
# let mycircle = 0i32;
let myshape: Box<Shape> = Box::new(mycircle) as Box<Shape>;
Traits may inherit from other traits. For example, in
```
-trait Shape { fn area() -> f64; }
-trait Circle : Shape { fn radius() -> f64; }
+trait Shape { fn area(&self) -> f64; }
+trait Circle : Shape { fn radius(&self) -> f64; }
```
the syntax `Circle : Shape` means that types that implement `Circle` must also
are written after the `impl` keyword.
```
-# trait Seq<T> { }
+# trait Seq<T> { fn dummy(&self, _: T) { } }
impl<T> Seq<T> for Vec<T> {
/* ... */
}
```{rust}
let vec: Vec<i32> = vec![1, 2, 3];
let arr: [i32; 3] = [1, 2, 3];
-let s: &[i32] = &vec[];
+let s: &[i32] = &vec[..];
```
As you can see, the `vec!` macro allows you to create a `Vec<T>` easily. The
}
fn main() {
- let prompt = CString::from_slice(b"[my-awesome-shell] $");
- unsafe {
+ let prompt = CString::new("[my-awesome-shell] $").unwrap();
+ unsafe {
rl_prompt = prompt.as_ptr();
println!("{:?}", rl_prompt);
The `extern` makes this function adhere to the C calling convention, as
discussed above in "[Foreign Calling
-Conventions](guide-ffi.html#foreign-calling-conventions)". The `no_mangle`
+Conventions](ffi.html#foreign-calling-conventions)". The `no_mangle`
attribute turns off Rust's name mangling, so that it is easier to link to.
fn main() {
let v = vec!["match_this", "1"];
- match &v[] {
+ match &v[..] {
["match_this", second] => println!("The second element is {}", second),
_ => {},
}
use core::atomic;
use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst};
-use core::borrow::BorrowFrom;
use core::fmt;
use core::cmp::{Ordering};
use core::default::Default;
}
}
-impl<T> BorrowFrom<Arc<T>> for T {
- fn borrow_from(owned: &Arc<T>) -> &T {
- &**owned
- }
-}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Deref for Arc<T> {
type Target = T;
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")]
+impl<T: Hash> Hash for Arc<T> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ (**self).hash(state)
+ }
+}
#[cfg(test)]
mod tests {
//! A pointer type for heap allocation.
//!
-//! `Box<T>`, casually referred to as a 'box', provides the simplest form of heap allocation in
-//! Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of
-//! scope.
+//! `Box<T>`, casually referred to as a 'box', provides the simplest form of
+//! heap allocation in Rust. Boxes provide ownership for this allocation, and
+//! drop their contents when they go out of scope.
//!
-//! Boxes are useful in two situations: recursive data structures, and occasionally when returning
-//! data. [The Pointer chapter of the Book](../../../book/pointers.html#best-practices-1) explains
-//! these cases in detail.
+//! Boxes are useful in two situations: recursive data structures, and
+//! occasionally when returning data. [The Pointer chapter of the
+//! Book](../../../book/pointers.html#best-practices-1) explains these cases in
+//! detail.
//!
//! # Examples
//!
use core::ptr::Unique;
use core::raw::TraitObject;
-/// A value that represents the heap. This is the default place that the `box` keyword allocates
-/// into when no place is supplied.
+/// A value that represents the heap. This is the default place that the `box`
+/// keyword allocates into when no place is supplied.
///
/// The following two examples are equivalent:
///
#[stable(feature = "rust1", since = "1.0.0")]
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")]
+impl<T: ?Sized + Hash> Hash for Box<T> {
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ (**self).hash(state);
+ }
+}
/// Extension methods for an owning `Any` trait object.
#[unstable(feature = "alloc",
#![feature(unboxed_closures)]
#![feature(unsafe_no_drop_flag)]
#![feature(core)]
-#![feature(hash)]
#![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")),
feature(libc))]
#![stable(feature = "rust1", since = "1.0.0")]
-use core::borrow::BorrowFrom;
use core::cell::Cell;
use core::clone::Clone;
use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
use core::default::Default;
use core::fmt;
-use core::hash::{self, Hash};
+use core::hash::{Hasher, Hash};
use core::marker;
use core::mem::{transmute, min_align_of, size_of, forget};
use core::nonzero::NonZero;
}
}
-impl<T> BorrowFrom<Rc<T>> for T {
- fn borrow_from(owned: &Rc<T>) -> &T {
- &**owned
- }
-}
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Deref for Rc<T> {
type Target = T;
}
// FIXME (#18248) Make `T` `Sized?`
-impl<S: hash::Hasher, T: Hash<S>> Hash<S> for Rc<T> {
+#[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")]
+impl<T: Hash> Hash for Rc<T> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ (**self).hash(state);
+ }
+}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Display> fmt::Display for Rc<T> {
head: RefCell<Chunk>,
copy_head: RefCell<Chunk>,
chunks: RefCell<Vec<Chunk>>,
- _invariant: marker::InvariantLifetime<'longer_than_self>,
+ _marker: marker::PhantomData<*mut &'longer_than_self()>,
}
impl<'a> Arena<'a> {
head: RefCell::new(chunk(initial_size, false)),
copy_head: RefCell::new(chunk(initial_size, true)),
chunks: RefCell::new(Vec::new()),
- _invariant: marker::InvariantLifetime,
+ _marker: marker::PhantomData,
}
}
}
}
struct TypedArenaChunk<T> {
+ marker: marker::PhantomData<T>,
+
/// Pointer to the next arena segment.
next: *mut TypedArenaChunk<T>,
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> FromIterator<T> for BinaryHeap<T> {
- fn from_iter<Iter: Iterator<Item=T>>(iter: Iter) -> BinaryHeap<T> {
- BinaryHeap::from_vec(iter.collect())
+ fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> BinaryHeap<T> {
+ BinaryHeap::from_vec(iter.into_iter().collect())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> Extend<T> for BinaryHeap<T> {
- fn extend<Iter: Iterator<Item=T>>(&mut self, iter: Iter) {
+ fn extend<I: IntoIterator<Item=T>>(&mut self, iterable: I) {
+ let iter = iterable.into_iter();
let (lower, _) = iter.size_hint();
self.reserve(lower);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// FIXME(Gankro): Bitv and BitvSet are very tightly coupled. Ideally (for
-// maintenance), they should be in separate files/modules, with BitvSet only
-// using Bitv's public API. This will be hard for performance though, because
-// `Bitv` will not want to leak its internal representation while its internal
+// FIXME(Gankro): BitVec and BitSet are very tightly coupled. Ideally (for
+// maintenance), they should be in separate files/modules, with BitSet only
+// using BitVec's public API. This will be hard for performance though, because
+// `BitVec` will not want to leak its internal representation while its internal
// representation as `u32`s must be assumed for best performance.
-// FIXME(tbu-): `Bitv`'s methods shouldn't be `union`, `intersection`, but
+// FIXME(tbu-): `BitVec`'s methods shouldn't be `union`, `intersection`, but
// rather `or` and `and`.
// (1) Be careful, most things can overflow here because the amount of bits in
// methods rely on it (for *CORRECTNESS*).
// (3) Make sure that the unused bits in the last word are zeroed out, again
// other methods rely on it for *CORRECTNESS*.
-// (4) `BitvSet` is tightly coupled with `Bitv`, so any changes you make in
-// `Bitv` will need to be reflected in `BitvSet`.
+// (4) `BitSet` is tightly coupled with `BitVec`, so any changes you make in
+// `BitVec` will need to be reflected in `BitSet`.
//! Collections implemented with bit vectors.
//!
//! [sieve]: http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
//!
//! ```
-//! use std::collections::{BitvSet, Bitv};
+//! use std::collections::{BitSet, BitVec};
//! use std::num::Float;
//! use std::iter;
//!
//! let max_prime = 10000;
//!
-//! // Store the primes as a BitvSet
+//! // Store the primes as a BitSet
//! let primes = {
//! // Assume all numbers are prime to begin, and then we
//! // cross off non-primes progressively
-//! let mut bv = Bitv::from_elem(max_prime, true);
+//! let mut bv = BitVec::from_elem(max_prime, true);
//!
//! // Neither 0 nor 1 are prime
//! bv.set(0, false);
//! for j in iter::range_step(i * i, max_prime, i) { bv.set(j, false) }
//! }
//! }
-//! BitvSet::from_bitv(bv)
+//! BitSet::from_bit_vec(bv)
//! };
//!
//! // Simple primality tests below our max bound
//! }
//! println!("");
//!
-//! // We can manipulate the internal Bitv
+//! // We can manipulate the internal BitVec
//! let num_primes = primes.get_ref().iter().filter(|x| *x).count();
//! println!("There are {} primes below {}", num_primes, max_prime);
//! ```
use core::ops::Index;
use core::slice;
use core::{u8, u32, usize};
-use bitv_set; //so meta
+use bit_set; //so meta
use Vec;
// Take two BitV's, and return iterators of their words, where the shorter one
// has been padded with 0's
-fn match_words <'a,'b>(a: &'a Bitv, b: &'b Bitv) -> (MatchWords<'a>, MatchWords<'b>) {
+fn match_words <'a,'b>(a: &'a BitVec, b: &'b BitVec) -> (MatchWords<'a>, MatchWords<'b>) {
let a_len = a.storage.len();
let b_len = b.storage.len();
/// # Examples
///
/// ```rust
-/// use std::collections::Bitv;
+/// use std::collections::BitVec;
///
-/// let mut bv = Bitv::from_elem(10, false);
+/// let mut bv = BitVec::from_elem(10, false);
///
/// // insert all primes less than 10
/// bv.set(2, true);
/// ```
#[unstable(feature = "collections",
reason = "RFC 509")]
-pub struct Bitv {
+pub struct BitVec {
/// Internal representation of the bit vector
storage: Vec<u32>,
/// The number of valid bits in the internal representation
}
// FIXME(Gankro): NopeNopeNopeNopeNope (wait for IndexGet to be a thing)
-impl Index<usize> for Bitv {
+impl Index<usize> for BitVec {
type Output = bool;
#[inline]
!0u32 >> (u32::BITS - bits % u32::BITS) % u32::BITS
}
-impl Bitv {
+impl BitVec {
/// Applies the given operation to the blocks of self and other, and sets
/// self to be the result. This relies on the caller not to corrupt the
/// last word.
#[inline]
- fn process<F>(&mut self, other: &Bitv, mut op: F) -> bool where F: FnMut(u32, u32) -> u32 {
+ fn process<F>(&mut self, other: &BitVec, mut op: F) -> bool where F: FnMut(u32, u32) -> u32 {
assert_eq!(self.len(), other.len());
// This could theoretically be a `debug_assert!`.
assert_eq!(self.storage.len(), other.storage.len());
}
/// An operation might screw up the unused bits in the last block of the
- /// `Bitv`. As per (3), it's assumed to be all 0s. This method fixes it up.
+ /// `BitVec`. As per (3), it's assumed to be all 0s. This method fixes it up.
fn fix_last_block(&mut self) {
let extra_bits = self.len() % u32::BITS;
if extra_bits > 0 {
}
}
- /// Creates an empty `Bitv`.
+ /// Creates an empty `BitVec`.
///
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
- /// let mut bv = Bitv::new();
+ /// use std::collections::BitVec;
+ /// let mut bv = BitVec::new();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn new() -> Bitv {
- Bitv { storage: Vec::new(), nbits: 0 }
+ pub fn new() -> BitVec {
+ BitVec { storage: Vec::new(), nbits: 0 }
}
- /// Creates a `Bitv` that holds `nbits` elements, setting each element
+ /// Creates a `BitVec` that holds `nbits` elements, setting each element
/// to `bit`.
///
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let mut bv = Bitv::from_elem(10, false);
+ /// let mut bv = BitVec::from_elem(10, false);
/// assert_eq!(bv.len(), 10);
/// for x in bv.iter() {
/// assert_eq!(x, false);
/// }
/// ```
- pub fn from_elem(nbits: usize, bit: bool) -> Bitv {
+ pub fn from_elem(nbits: usize, bit: bool) -> BitVec {
let nblocks = blocks_for_bits(nbits);
- let mut bitv = Bitv {
+ let mut bit_vec = BitVec {
storage: repeat(if bit { !0u32 } else { 0u32 }).take(nblocks).collect(),
nbits: nbits
};
- bitv.fix_last_block();
- bitv
+ bit_vec.fix_last_block();
+ bit_vec
}
- /// Constructs a new, empty `Bitv` with the specified capacity.
+ /// Constructs a new, empty `BitVec` with the specified capacity.
///
/// The bitvector will be able to hold at least `capacity` bits without
/// reallocating. If `capacity` is 0, it will not allocate.
/// It is important to note that this function does not specify the
/// *length* of the returned bitvector, but only the *capacity*.
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn with_capacity(nbits: usize) -> Bitv {
- Bitv {
+ pub fn with_capacity(nbits: usize) -> BitVec {
+ BitVec {
storage: Vec::with_capacity(blocks_for_bits(nbits)),
nbits: 0,
}
}
- /// Transforms a byte-vector into a `Bitv`. Each byte becomes eight bits,
+ /// Transforms a byte-vector into a `BitVec`. Each byte becomes eight bits,
/// with the most significant bits of each byte coming first. Each
/// bit becomes `true` if equal to 1 or `false` if equal to 0.
///
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let bv = Bitv::from_bytes(&[0b10100000, 0b00010010]);
+ /// let bv = BitVec::from_bytes(&[0b10100000, 0b00010010]);
/// assert!(bv.eq_vec(&[true, false, true, false,
/// false, false, false, false,
/// false, false, false, true,
/// false, false, true, false]));
/// ```
- pub fn from_bytes(bytes: &[u8]) -> Bitv {
+ pub fn from_bytes(bytes: &[u8]) -> BitVec {
let len = bytes.len().checked_mul(u8::BITS).expect("capacity overflow");
- let mut bitv = Bitv::with_capacity(len);
+ let mut bit_vec = BitVec::with_capacity(len);
let complete_words = bytes.len() / 4;
let extra_bytes = bytes.len() % 4;
- bitv.nbits = len;
+ bit_vec.nbits = len;
for i in 0..complete_words {
- bitv.storage.push(
+ bit_vec.storage.push(
((reverse_bits(bytes[i * 4 + 0]) as u32) << 0) |
((reverse_bits(bytes[i * 4 + 1]) as u32) << 8) |
((reverse_bits(bytes[i * 4 + 2]) as u32) << 16) |
for (i, &byte) in bytes[complete_words*4..].iter().enumerate() {
last_word |= (reverse_bits(byte) as u32) << (i * 8);
}
- bitv.storage.push(last_word);
+ bit_vec.storage.push(last_word);
}
- bitv
+ bit_vec
}
- /// Creates a `Bitv` of the specified length where the value at each index
+ /// Creates a `BitVec` of the specified length where the value at each index
/// is `f(index)`.
///
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let bv = Bitv::from_fn(5, |i| { i % 2 == 0 });
+ /// let bv = BitVec::from_fn(5, |i| { i % 2 == 0 });
/// assert!(bv.eq_vec(&[true, false, true, false, true]));
/// ```
- pub fn from_fn<F>(len: usize, mut f: F) -> Bitv where F: FnMut(usize) -> bool {
- let mut bitv = Bitv::from_elem(len, false);
+ pub fn from_fn<F>(len: usize, mut f: F) -> BitVec where F: FnMut(usize) -> bool {
+ let mut bit_vec = BitVec::from_elem(len, false);
for i in 0..len {
- bitv.set(i, f(i));
+ bit_vec.set(i, f(i));
}
- bitv
+ bit_vec
}
/// Retrieves the value at index `i`, or `None` if the index is out of bounds.
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let bv = Bitv::from_bytes(&[0b01100000]);
+ /// let bv = BitVec::from_bytes(&[0b01100000]);
/// assert_eq!(bv.get(0), Some(false));
/// assert_eq!(bv.get(1), Some(true));
/// assert_eq!(bv.get(100), None);
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let mut bv = Bitv::from_elem(5, false);
+ /// let mut bv = BitVec::from_elem(5, false);
/// bv.set(3, true);
/// assert_eq!(bv[3], true);
/// ```
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
/// let before = 0b01100000;
/// let after = 0b11111111;
///
- /// let mut bv = Bitv::from_bytes(&[before]);
+ /// let mut bv = BitVec::from_bytes(&[before]);
/// bv.set_all();
- /// assert_eq!(bv, Bitv::from_bytes(&[after]));
+ /// assert_eq!(bv, BitVec::from_bytes(&[after]));
/// ```
#[inline]
pub fn set_all(&mut self) {
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
/// let before = 0b01100000;
/// let after = 0b10011111;
///
- /// let mut bv = Bitv::from_bytes(&[before]);
+ /// let mut bv = BitVec::from_bytes(&[before]);
/// bv.negate();
- /// assert_eq!(bv, Bitv::from_bytes(&[after]));
+ /// assert_eq!(bv, BitVec::from_bytes(&[after]));
/// ```
#[inline]
pub fn negate(&mut self) {
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
/// let a = 0b01100100;
/// let b = 0b01011010;
/// let res = 0b01111110;
///
- /// let mut a = Bitv::from_bytes(&[a]);
- /// let b = Bitv::from_bytes(&[b]);
+ /// let mut a = BitVec::from_bytes(&[a]);
+ /// let b = BitVec::from_bytes(&[b]);
///
/// assert!(a.union(&b));
- /// assert_eq!(a, Bitv::from_bytes(&[res]));
+ /// assert_eq!(a, BitVec::from_bytes(&[res]));
/// ```
#[inline]
- pub fn union(&mut self, other: &Bitv) -> bool {
+ pub fn union(&mut self, other: &BitVec) -> bool {
self.process(other, |w1, w2| w1 | w2)
}
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
/// let a = 0b01100100;
/// let b = 0b01011010;
/// let res = 0b01000000;
///
- /// let mut a = Bitv::from_bytes(&[a]);
- /// let b = Bitv::from_bytes(&[b]);
+ /// let mut a = BitVec::from_bytes(&[a]);
+ /// let b = BitVec::from_bytes(&[b]);
///
/// assert!(a.intersect(&b));
- /// assert_eq!(a, Bitv::from_bytes(&[res]));
+ /// assert_eq!(a, BitVec::from_bytes(&[res]));
/// ```
#[inline]
- pub fn intersect(&mut self, other: &Bitv) -> bool {
+ pub fn intersect(&mut self, other: &BitVec) -> bool {
self.process(other, |w1, w2| w1 & w2)
}
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
/// let a = 0b01100100;
/// let b = 0b01011010;
/// let a_b = 0b00100100; // a - b
/// let b_a = 0b00011010; // b - a
///
- /// let mut bva = Bitv::from_bytes(&[a]);
- /// let bvb = Bitv::from_bytes(&[b]);
+ /// let mut bva = BitVec::from_bytes(&[a]);
+ /// let bvb = BitVec::from_bytes(&[b]);
///
/// assert!(bva.difference(&bvb));
- /// assert_eq!(bva, Bitv::from_bytes(&[a_b]));
+ /// assert_eq!(bva, BitVec::from_bytes(&[a_b]));
///
- /// let bva = Bitv::from_bytes(&[a]);
- /// let mut bvb = Bitv::from_bytes(&[b]);
+ /// let bva = BitVec::from_bytes(&[a]);
+ /// let mut bvb = BitVec::from_bytes(&[b]);
///
/// assert!(bvb.difference(&bva));
- /// assert_eq!(bvb, Bitv::from_bytes(&[b_a]));
+ /// assert_eq!(bvb, BitVec::from_bytes(&[b_a]));
/// ```
#[inline]
- pub fn difference(&mut self, other: &Bitv) -> bool {
+ pub fn difference(&mut self, other: &BitVec) -> bool {
self.process(other, |w1, w2| w1 & !w2)
}
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let mut bv = Bitv::from_elem(5, true);
+ /// let mut bv = BitVec::from_elem(5, true);
/// assert_eq!(bv.all(), true);
///
/// bv.set(1, false);
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let bv = Bitv::from_bytes(&[0b01110100, 0b10010010]);
+ /// let bv = BitVec::from_bytes(&[0b01110100, 0b10010010]);
/// assert_eq!(bv.iter().filter(|x| *x).count(), 7);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn iter(&self) -> Iter {
- Iter { bitv: self, next_idx: 0, end_idx: self.nbits }
+ Iter { bit_vec: self, next_idx: 0, end_idx: self.nbits }
}
/// Returns `true` if all bits are 0.
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let mut bv = Bitv::from_elem(10, false);
+ /// let mut bv = BitVec::from_elem(10, false);
/// assert_eq!(bv.none(), true);
///
/// bv.set(3, true);
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let mut bv = Bitv::from_elem(10, false);
+ /// let mut bv = BitVec::from_elem(10, false);
/// assert_eq!(bv.any(), false);
///
/// bv.set(3, true);
}
/// Organises the bits into bytes, such that the first bit in the
- /// `Bitv` becomes the high-order bit of the first byte. If the
- /// size of the `Bitv` is not a multiple of eight then trailing bits
+ /// `BitVec` becomes the high-order bit of the first byte. If the
+ /// size of the `BitVec` is not a multiple of eight then trailing bits
/// will be filled-in with `false`.
///
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let mut bv = Bitv::from_elem(3, true);
+ /// let mut bv = BitVec::from_elem(3, true);
/// bv.set(1, false);
///
/// assert_eq!(bv.to_bytes(), vec!(0b10100000));
///
- /// let mut bv = Bitv::from_elem(9, false);
+ /// let mut bv = BitVec::from_elem(9, false);
/// bv.set(2, true);
/// bv.set(8, true);
///
/// assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000));
/// ```
pub fn to_bytes(&self) -> Vec<u8> {
- fn bit(bitv: &Bitv, byte: usize, bit: usize) -> u8 {
+ fn bit(bit_vec: &BitVec, byte: usize, bit: usize) -> u8 {
let offset = byte * 8 + bit;
- if offset >= bitv.nbits {
+ if offset >= bit_vec.nbits {
0
} else {
- (bitv[offset] as u8) << (7 - bit)
+ (bit_vec[offset] as u8) << (7 - bit)
}
}
).collect()
}
- /// Compares a `Bitv` to a slice of `bool`s.
- /// Both the `Bitv` and slice must have the same length.
+ /// Compares a `BitVec` to a slice of `bool`s.
+ /// Both the `BitVec` and slice must have the same length.
///
/// # Panics
///
- /// Panics if the `Bitv` and slice are of different length.
+ /// Panics if the `BitVec` and slice are of different length.
///
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let bv = Bitv::from_bytes(&[0b10100000]);
+ /// let bv = BitVec::from_bytes(&[0b10100000]);
///
/// assert!(bv.eq_vec(&[true, false, true, false,
/// false, false, false, false]));
iter::order::eq(self.iter(), v.iter().cloned())
}
- /// Shortens a `Bitv`, dropping excess elements.
+ /// Shortens a `BitVec`, dropping excess elements.
///
/// If `len` is greater than the vector's current length, this has no
/// effect.
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let mut bv = Bitv::from_bytes(&[0b01001011]);
+ /// let mut bv = BitVec::from_bytes(&[0b01001011]);
/// bv.truncate(2);
/// assert!(bv.eq_vec(&[false, true]));
/// ```
}
/// Reserves capacity for at least `additional` more bits to be inserted in the given
- /// `Bitv`. The collection may reserve more space to avoid frequent reallocations.
+ /// `BitVec`. The collection may reserve more space to avoid frequent reallocations.
///
/// # Panics
///
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let mut bv = Bitv::from_elem(3, false);
+ /// let mut bv = BitVec::from_elem(3, false);
/// bv.reserve(10);
/// assert_eq!(bv.len(), 3);
/// assert!(bv.capacity() >= 13);
}
/// Reserves the minimum capacity for exactly `additional` more bits to be inserted in the
- /// given `Bitv`. Does nothing if the capacity is already sufficient.
+ /// given `BitVec`. Does nothing if the capacity is already sufficient.
///
/// Note that the allocator may give the collection more space than it requests. Therefore
/// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let mut bv = Bitv::from_elem(3, false);
+ /// let mut bv = BitVec::from_elem(3, false);
/// bv.reserve(10);
/// assert_eq!(bv.len(), 3);
/// assert!(bv.capacity() >= 13);
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let mut bv = Bitv::new();
+ /// let mut bv = BitVec::new();
/// bv.reserve(10);
/// assert!(bv.capacity() >= 10);
/// ```
self.storage.capacity().checked_mul(u32::BITS).unwrap_or(usize::MAX)
}
- /// Grows the `Bitv` in-place, adding `n` copies of `value` to the `Bitv`.
+ /// Grows the `BitVec` in-place, adding `n` copies of `value` to the `BitVec`.
///
/// # Panics
///
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let mut bv = Bitv::from_bytes(&[0b01001011]);
+ /// let mut bv = BitVec::from_bytes(&[0b01001011]);
/// bv.grow(2, true);
/// assert_eq!(bv.len(), 10);
/// assert_eq!(bv.to_bytes(), vec!(0b01001011, 0b11000000));
self.fix_last_block();
}
- /// Removes the last bit from the Bitv, and returns it. Returns None if the Bitv is empty.
+ /// Removes the last bit from the BitVec, and returns it. Returns None if the BitVec is empty.
///
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let mut bv = Bitv::from_bytes(&[0b01001001]);
+ /// let mut bv = BitVec::from_bytes(&[0b01001001]);
/// assert_eq!(bv.pop(), Some(true));
/// assert_eq!(bv.pop(), Some(false));
/// assert_eq!(bv.len(), 6);
/// # Examples
///
/// ```
- /// use std::collections::Bitv;
+ /// use std::collections::BitVec;
///
- /// let mut bv = Bitv::new();
+ /// let mut bv = BitVec::new();
/// bv.push(true);
/// bv.push(false);
/// assert!(bv.eq_vec(&[true, false]));
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl Default for Bitv {
+impl Default for BitVec {
#[inline]
- fn default() -> Bitv { Bitv::new() }
+ fn default() -> BitVec { BitVec::new() }
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl FromIterator<bool> for Bitv {
- fn from_iter<I:Iterator<Item=bool>>(iterator: I) -> Bitv {
- let mut ret = Bitv::new();
- ret.extend(iterator);
+impl FromIterator<bool> for BitVec {
+ fn from_iter<I: IntoIterator<Item=bool>>(iter: I) -> BitVec {
+ let mut ret = BitVec::new();
+ ret.extend(iter);
ret
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl Extend<bool> for Bitv {
+impl Extend<bool> for BitVec {
#[inline]
- fn extend<I: Iterator<Item=bool>>(&mut self, iterator: I) {
+ fn extend<I: IntoIterator<Item=bool>>(&mut self, iterable: I) {
+ let iterator = iterable.into_iter();
let (min, _) = iterator.size_hint();
self.reserve(min);
for element in iterator {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl Clone for Bitv {
+impl Clone for BitVec {
#[inline]
- fn clone(&self) -> Bitv {
- Bitv { storage: self.storage.clone(), nbits: self.nbits }
+ fn clone(&self) -> BitVec {
+ BitVec { storage: self.storage.clone(), nbits: self.nbits }
}
#[inline]
- fn clone_from(&mut self, source: &Bitv) {
+ fn clone_from(&mut self, source: &BitVec) {
self.nbits = source.nbits;
self.storage.clone_from(&source.storage);
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl PartialOrd for Bitv {
+impl PartialOrd for BitVec {
#[inline]
- fn partial_cmp(&self, other: &Bitv) -> Option<Ordering> {
+ fn partial_cmp(&self, other: &BitVec) -> Option<Ordering> {
iter::order::partial_cmp(self.iter(), other.iter())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl Ord for Bitv {
+impl Ord for BitVec {
#[inline]
- fn cmp(&self, other: &Bitv) -> Ordering {
+ fn cmp(&self, other: &BitVec) -> Ordering {
iter::order::cmp(self.iter(), other.iter())
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for Bitv {
+impl fmt::Debug for BitVec {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
for bit in self {
try!(write!(fmt, "{}", if bit { 1u32 } else { 0u32 }));
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Bitv {
+#[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() {
}
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(stage0))]
+impl hash::Hash for BitVec {
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ self.nbits.hash(state);
+ for elem in self.blocks() {
+ elem.hash(state);
+ }
+ }
+}
#[stable(feature = "rust1", since = "1.0.0")]
-impl cmp::PartialEq for Bitv {
+impl cmp::PartialEq for BitVec {
#[inline]
- fn eq(&self, other: &Bitv) -> bool {
+ fn eq(&self, other: &BitVec) -> bool {
if self.nbits != other.nbits {
return false;
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl cmp::Eq for Bitv {}
+impl cmp::Eq for BitVec {}
-/// An iterator for `Bitv`.
+/// An iterator for `BitVec`.
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct Iter<'a> {
- bitv: &'a Bitv,
+ bit_vec: &'a BitVec,
next_idx: usize,
end_idx: usize,
}
if self.next_idx != self.end_idx {
let idx = self.next_idx;
self.next_idx += 1;
- Some(self.bitv[idx])
+ Some(self.bit_vec[idx])
} else {
None
}
fn next_back(&mut self) -> Option<bool> {
if self.next_idx != self.end_idx {
self.end_idx -= 1;
- Some(self.bitv[self.end_idx])
+ Some(self.bit_vec[self.end_idx])
} else {
None
}
if index >= self.indexable() {
None
} else {
- Some(self.bitv[index])
+ Some(self.bit_vec[index])
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> IntoIterator for &'a Bitv {
+impl<'a> IntoIterator for &'a BitVec {
type Item = bool;
type IntoIter = Iter<'a>;
/// # Examples
///
/// ```
-/// use std::collections::{BitvSet, Bitv};
+/// use std::collections::{BitSet, BitVec};
///
/// // It's a regular set
-/// let mut s = BitvSet::new();
+/// let mut s = BitSet::new();
/// s.insert(0);
/// s.insert(3);
/// s.insert(7);
/// println!("There is no 7");
/// }
///
-/// // Can initialize from a `Bitv`
-/// let other = BitvSet::from_bitv(Bitv::from_bytes(&[0b11010000]));
+/// // Can initialize from a `BitVec`
+/// let other = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11010000]));
///
/// s.union_with(&other);
///
/// println!("{}", x);
/// }
///
-/// // Can convert back to a `Bitv`
-/// let bv: Bitv = s.into_bitv();
+/// // Can convert back to a `BitVec`
+/// let bv: BitVec = s.into_bit_vec();
/// assert!(bv[3]);
/// ```
#[derive(Clone)]
#[unstable(feature = "collections",
reason = "RFC 509")]
-pub struct BitvSet {
- bitv: Bitv,
+pub struct BitSet {
+ bit_vec: BitVec,
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl Default for BitvSet {
+impl Default for BitSet {
#[inline]
- fn default() -> BitvSet { BitvSet::new() }
+ fn default() -> BitSet { BitSet::new() }
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl FromIterator<usize> for BitvSet {
- fn from_iter<I:Iterator<Item=usize>>(iterator: I) -> BitvSet {
- let mut ret = BitvSet::new();
- ret.extend(iterator);
+impl FromIterator<usize> for BitSet {
+ fn from_iter<I: IntoIterator<Item=usize>>(iter: I) -> BitSet {
+ let mut ret = BitSet::new();
+ ret.extend(iter);
ret
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl Extend<usize> for BitvSet {
+impl Extend<usize> for BitSet {
#[inline]
- fn extend<I: Iterator<Item=usize>>(&mut self, iterator: I) {
- for i in iterator {
+ fn extend<I: IntoIterator<Item=usize>>(&mut self, iter: I) {
+ for i in iter {
self.insert(i);
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl PartialOrd for BitvSet {
+impl PartialOrd for BitSet {
#[inline]
- fn partial_cmp(&self, other: &BitvSet) -> Option<Ordering> {
+ fn partial_cmp(&self, other: &BitSet) -> Option<Ordering> {
let (a_iter, b_iter) = match_words(self.get_ref(), other.get_ref());
iter::order::partial_cmp(a_iter, b_iter)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl Ord for BitvSet {
+impl Ord for BitSet {
#[inline]
- fn cmp(&self, other: &BitvSet) -> Ordering {
+ fn cmp(&self, other: &BitSet) -> Ordering {
let (a_iter, b_iter) = match_words(self.get_ref(), other.get_ref());
iter::order::cmp(a_iter, b_iter)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl cmp::PartialEq for BitvSet {
+impl cmp::PartialEq for BitSet {
#[inline]
- fn eq(&self, other: &BitvSet) -> bool {
+ fn eq(&self, other: &BitSet) -> bool {
let (a_iter, b_iter) = match_words(self.get_ref(), other.get_ref());
iter::order::eq(a_iter, b_iter)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl cmp::Eq for BitvSet {}
+impl cmp::Eq for BitSet {}
-impl BitvSet {
- /// Creates a new empty `BitvSet`.
+impl BitSet {
+ /// Creates a new empty `BitSet`.
///
/// # Examples
///
/// ```
- /// use std::collections::BitvSet;
+ /// use std::collections::BitSet;
///
- /// let mut s = BitvSet::new();
+ /// let mut s = BitSet::new();
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn new() -> BitvSet {
- BitvSet { bitv: Bitv::new() }
+ pub fn new() -> BitSet {
+ BitSet { bit_vec: BitVec::new() }
}
- /// Creates a new `BitvSet` with initially no contents, able to
+ /// Creates a new `BitSet` with initially no contents, able to
/// hold `nbits` elements without resizing.
///
/// # Examples
///
/// ```
- /// use std::collections::BitvSet;
+ /// use std::collections::BitSet;
///
- /// let mut s = BitvSet::with_capacity(100);
+ /// let mut s = BitSet::with_capacity(100);
/// assert!(s.capacity() >= 100);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn with_capacity(nbits: usize) -> BitvSet {
- let bitv = Bitv::from_elem(nbits, false);
- BitvSet::from_bitv(bitv)
+ pub fn with_capacity(nbits: usize) -> BitSet {
+ let bit_vec = BitVec::from_elem(nbits, false);
+ BitSet::from_bit_vec(bit_vec)
}
- /// Creates a new `BitvSet` from the given bit vector.
+ /// Creates a new `BitSet` from the given bit vector.
///
/// # Examples
///
/// ```
- /// use std::collections::{Bitv, BitvSet};
+ /// use std::collections::{BitVec, BitSet};
///
- /// let bv = Bitv::from_bytes(&[0b01100000]);
- /// let s = BitvSet::from_bitv(bv);
+ /// let bv = BitVec::from_bytes(&[0b01100000]);
+ /// let s = BitSet::from_bit_vec(bv);
///
/// // Print 1, 2 in arbitrary order
/// for x in s.iter() {
/// }
/// ```
#[inline]
- pub fn from_bitv(bitv: Bitv) -> BitvSet {
- BitvSet { bitv: bitv }
+ pub fn from_bit_vec(bit_vec: BitVec) -> BitSet {
+ BitSet { bit_vec: bit_vec }
+ }
+
+ /// Deprecated: use `from_bit_vec`.
+ #[inline]
+ #[deprecated(since = "1.0.0", reason = "renamed to from_bit_vec")]
+ #[unstable(feature = "collections")]
+ pub fn from_bitv(bit_vec: BitVec) -> BitSet {
+ BitSet { bit_vec: bit_vec }
}
/// Returns the capacity in bits for this bit vector. Inserting any
/// # Examples
///
/// ```
- /// use std::collections::BitvSet;
+ /// use std::collections::BitSet;
///
- /// let mut s = BitvSet::with_capacity(100);
+ /// let mut s = BitSet::with_capacity(100);
/// assert!(s.capacity() >= 100);
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn capacity(&self) -> usize {
- self.bitv.capacity()
+ self.bit_vec.capacity()
}
- /// Reserves capacity for the given `BitvSet` to contain `len` distinct elements. In the case
- /// of `BitvSet` this means reallocations will not occur as long as all inserted elements
+ /// Reserves capacity for the given `BitSet` to contain `len` distinct elements. In the case
+ /// of `BitSet` this means reallocations will not occur as long as all inserted elements
/// are less than `len`.
///
/// The collection may reserve more space to avoid frequent reallocations.
/// # Examples
///
/// ```
- /// use std::collections::BitvSet;
+ /// use std::collections::BitSet;
///
- /// let mut s = BitvSet::new();
+ /// let mut s = BitSet::new();
/// s.reserve_len(10);
/// assert!(s.capacity() >= 10);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn reserve_len(&mut self, len: usize) {
- let cur_len = self.bitv.len();
+ let cur_len = self.bit_vec.len();
if len >= cur_len {
- self.bitv.reserve(len - cur_len);
+ self.bit_vec.reserve(len - cur_len);
}
}
- /// Reserves the minimum capacity for the given `BitvSet` to contain `len` distinct elements.
- /// In the case of `BitvSet` this means reallocations will not occur as long as all inserted
+ /// Reserves the minimum capacity for the given `BitSet` to contain `len` distinct elements.
+ /// In the case of `BitSet` this means reallocations will not occur as long as all inserted
/// elements are less than `len`.
///
/// Note that the allocator may give the collection more space than it requests. Therefore
/// # Examples
///
/// ```
- /// use std::collections::BitvSet;
+ /// use std::collections::BitSet;
///
- /// let mut s = BitvSet::new();
+ /// let mut s = BitSet::new();
/// s.reserve_len_exact(10);
/// assert!(s.capacity() >= 10);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn reserve_len_exact(&mut self, len: usize) {
- let cur_len = self.bitv.len();
+ let cur_len = self.bit_vec.len();
if len >= cur_len {
- self.bitv.reserve_exact(len - cur_len);
+ self.bit_vec.reserve_exact(len - cur_len);
}
}
/// # Examples
///
/// ```
- /// use std::collections::BitvSet;
+ /// use std::collections::BitSet;
///
- /// let mut s = BitvSet::new();
+ /// let mut s = BitSet::new();
/// s.insert(0);
/// s.insert(3);
///
- /// let bv = s.into_bitv();
+ /// let bv = s.into_bit_vec();
/// assert!(bv[0]);
/// assert!(bv[3]);
/// ```
#[inline]
- pub fn into_bitv(self) -> Bitv {
- self.bitv
+ pub fn into_bit_vec(self) -> BitVec {
+ self.bit_vec
}
/// Returns a reference to the underlying bit vector.
/// # Examples
///
/// ```
- /// use std::collections::BitvSet;
+ /// use std::collections::BitSet;
///
- /// let mut s = BitvSet::new();
+ /// let mut s = BitSet::new();
/// s.insert(0);
///
/// let bv = s.get_ref();
/// assert_eq!(bv[0], true);
/// ```
#[inline]
- pub fn get_ref(&self) -> &Bitv {
- &self.bitv
+ pub fn get_ref(&self) -> &BitVec {
+ &self.bit_vec
}
#[inline]
- fn other_op<F>(&mut self, other: &BitvSet, mut f: F) where F: FnMut(u32, u32) -> u32 {
- // Unwrap Bitvs
- let self_bitv = &mut self.bitv;
- let other_bitv = &other.bitv;
+ fn other_op<F>(&mut self, other: &BitSet, mut f: F) where F: FnMut(u32, u32) -> u32 {
+ // Unwrap BitVecs
+ let self_bit_vec = &mut self.bit_vec;
+ let other_bit_vec = &other.bit_vec;
- let self_len = self_bitv.len();
- let other_len = other_bitv.len();
+ let self_len = self_bit_vec.len();
+ let other_len = other_bit_vec.len();
// Expand the vector if necessary
if self_len < other_len {
- self_bitv.grow(other_len - self_len, false);
+ self_bit_vec.grow(other_len - self_len, false);
}
// virtually pad other with 0's for equal lengths
let other_words = {
- let (_, result) = match_words(self_bitv, other_bitv);
+ let (_, result) = match_words(self_bit_vec, other_bit_vec);
result
};
// Apply values found in other
for (i, w) in other_words {
- let old = self_bitv.storage[i];
+ let old = self_bit_vec.storage[i];
let new = f(old, w);
- self_bitv.storage[i] = new;
+ self_bit_vec.storage[i] = new;
}
}
/// # Examples
///
/// ```
- /// use std::collections::BitvSet;
+ /// use std::collections::BitSet;
///
- /// let mut s = BitvSet::new();
+ /// let mut s = BitSet::new();
/// s.insert(32183231);
/// s.remove(&32183231);
///
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn shrink_to_fit(&mut self) {
- let bitv = &mut self.bitv;
+ let bit_vec = &mut self.bit_vec;
// Obtain original length
- let old_len = bitv.storage.len();
+ let old_len = bit_vec.storage.len();
// Obtain coarse trailing zero length
- let n = bitv.storage.iter().rev().take_while(|&&n| n == 0).count();
+ let n = bit_vec.storage.iter().rev().take_while(|&&n| n == 0).count();
// Truncate
let trunc_len = cmp::max(old_len - n, 1);
- bitv.storage.truncate(trunc_len);
- bitv.nbits = trunc_len * u32::BITS;
+ bit_vec.storage.truncate(trunc_len);
+ bit_vec.nbits = trunc_len * u32::BITS;
}
- /// Iterator over each u32 stored in the `BitvSet`.
+ /// Iterator over each u32 stored in the `BitSet`.
///
/// # Examples
///
/// ```
- /// use std::collections::{Bitv, BitvSet};
+ /// use std::collections::{BitVec, BitSet};
///
- /// let s = BitvSet::from_bitv(Bitv::from_bytes(&[0b01001010]));
+ /// let s = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01001010]));
///
/// // Print 1, 4, 6 in arbitrary order
/// for x in s.iter() {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn iter(&self) -> bitv_set::Iter {
+ pub fn iter(&self) -> bit_set::Iter {
SetIter {set: self, next_idx: 0}
}
/// # Examples
///
/// ```
- /// use std::collections::{Bitv, BitvSet};
+ /// use std::collections::{BitVec, BitSet};
///
- /// let a = BitvSet::from_bitv(Bitv::from_bytes(&[0b01101000]));
- /// let b = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100000]));
+ /// let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101000]));
+ /// let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000]));
///
/// // Print 0, 1, 2, 4 in arbitrary order
/// for x in a.union(&b) {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn union<'a>(&'a self, other: &'a BitvSet) -> Union<'a> {
+ pub fn union<'a>(&'a self, other: &'a BitSet) -> Union<'a> {
fn or(w1: u32, w2: u32) -> u32 { w1 | w2 }
Union(TwoBitPositions {
/// # Examples
///
/// ```
- /// use std::collections::{Bitv, BitvSet};
+ /// use std::collections::{BitVec, BitSet};
///
- /// let a = BitvSet::from_bitv(Bitv::from_bytes(&[0b01101000]));
- /// let b = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100000]));
+ /// let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101000]));
+ /// let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000]));
///
/// // Print 2
/// for x in a.intersection(&b) {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn intersection<'a>(&'a self, other: &'a BitvSet) -> Intersection<'a> {
+ pub fn intersection<'a>(&'a self, other: &'a BitSet) -> Intersection<'a> {
fn bitand(w1: u32, w2: u32) -> u32 { w1 & w2 }
- let min = cmp::min(self.bitv.len(), other.bitv.len());
+ let min = cmp::min(self.bit_vec.len(), other.bit_vec.len());
Intersection(TwoBitPositions {
set: self,
other: other,
/// # Examples
///
/// ```
- /// use std::collections::{BitvSet, Bitv};
+ /// use std::collections::{BitSet, BitVec};
///
- /// let a = BitvSet::from_bitv(Bitv::from_bytes(&[0b01101000]));
- /// let b = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100000]));
+ /// let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101000]));
+ /// let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000]));
///
/// // Print 1, 4 in arbitrary order
/// for x in a.difference(&b) {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn difference<'a>(&'a self, other: &'a BitvSet) -> Difference<'a> {
+ pub fn difference<'a>(&'a self, other: &'a BitSet) -> Difference<'a> {
fn diff(w1: u32, w2: u32) -> u32 { w1 & !w2 }
Difference(TwoBitPositions {
/// # Examples
///
/// ```
- /// use std::collections::{BitvSet, Bitv};
+ /// use std::collections::{BitSet, BitVec};
///
- /// let a = BitvSet::from_bitv(Bitv::from_bytes(&[0b01101000]));
- /// let b = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100000]));
+ /// let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101000]));
+ /// let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100000]));
///
/// // Print 0, 1, 4 in arbitrary order
/// for x in a.symmetric_difference(&b) {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn symmetric_difference<'a>(&'a self, other: &'a BitvSet) -> SymmetricDifference<'a> {
+ pub fn symmetric_difference<'a>(&'a self, other: &'a BitSet) -> SymmetricDifference<'a> {
fn bitxor(w1: u32, w2: u32) -> u32 { w1 ^ w2 }
SymmetricDifference(TwoBitPositions {
/// # Examples
///
/// ```
- /// use std::collections::{BitvSet, Bitv};
+ /// use std::collections::{BitSet, BitVec};
///
/// let a = 0b01101000;
/// let b = 0b10100000;
/// let res = 0b11101000;
///
- /// let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[a]));
- /// let b = BitvSet::from_bitv(Bitv::from_bytes(&[b]));
- /// let res = BitvSet::from_bitv(Bitv::from_bytes(&[res]));
+ /// let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[a]));
+ /// let b = BitSet::from_bit_vec(BitVec::from_bytes(&[b]));
+ /// let res = BitSet::from_bit_vec(BitVec::from_bytes(&[res]));
///
/// a.union_with(&b);
/// assert_eq!(a, res);
/// ```
#[inline]
- pub fn union_with(&mut self, other: &BitvSet) {
+ pub fn union_with(&mut self, other: &BitSet) {
self.other_op(other, |w1, w2| w1 | w2);
}
/// # Examples
///
/// ```
- /// use std::collections::{BitvSet, Bitv};
+ /// use std::collections::{BitSet, BitVec};
///
/// let a = 0b01101000;
/// let b = 0b10100000;
/// let res = 0b00100000;
///
- /// let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[a]));
- /// let b = BitvSet::from_bitv(Bitv::from_bytes(&[b]));
- /// let res = BitvSet::from_bitv(Bitv::from_bytes(&[res]));
+ /// let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[a]));
+ /// let b = BitSet::from_bit_vec(BitVec::from_bytes(&[b]));
+ /// let res = BitSet::from_bit_vec(BitVec::from_bytes(&[res]));
///
/// a.intersect_with(&b);
/// assert_eq!(a, res);
/// ```
#[inline]
- pub fn intersect_with(&mut self, other: &BitvSet) {
+ pub fn intersect_with(&mut self, other: &BitSet) {
self.other_op(other, |w1, w2| w1 & w2);
}
/// # Examples
///
/// ```
- /// use std::collections::{BitvSet, Bitv};
+ /// use std::collections::{BitSet, BitVec};
///
/// let a = 0b01101000;
/// let b = 0b10100000;
/// let a_b = 0b01001000; // a - b
/// let b_a = 0b10000000; // b - a
///
- /// let mut bva = BitvSet::from_bitv(Bitv::from_bytes(&[a]));
- /// let bvb = BitvSet::from_bitv(Bitv::from_bytes(&[b]));
- /// let bva_b = BitvSet::from_bitv(Bitv::from_bytes(&[a_b]));
- /// let bvb_a = BitvSet::from_bitv(Bitv::from_bytes(&[b_a]));
+ /// let mut bva = BitSet::from_bit_vec(BitVec::from_bytes(&[a]));
+ /// let bvb = BitSet::from_bit_vec(BitVec::from_bytes(&[b]));
+ /// let bva_b = BitSet::from_bit_vec(BitVec::from_bytes(&[a_b]));
+ /// let bvb_a = BitSet::from_bit_vec(BitVec::from_bytes(&[b_a]));
///
/// bva.difference_with(&bvb);
/// assert_eq!(bva, bva_b);
///
- /// let bva = BitvSet::from_bitv(Bitv::from_bytes(&[a]));
- /// let mut bvb = BitvSet::from_bitv(Bitv::from_bytes(&[b]));
+ /// let bva = BitSet::from_bit_vec(BitVec::from_bytes(&[a]));
+ /// let mut bvb = BitSet::from_bit_vec(BitVec::from_bytes(&[b]));
///
/// bvb.difference_with(&bva);
/// assert_eq!(bvb, bvb_a);
/// ```
#[inline]
- pub fn difference_with(&mut self, other: &BitvSet) {
+ pub fn difference_with(&mut self, other: &BitSet) {
self.other_op(other, |w1, w2| w1 & !w2);
}
/// # Examples
///
/// ```
- /// use std::collections::{BitvSet, Bitv};
+ /// use std::collections::{BitSet, BitVec};
///
/// let a = 0b01101000;
/// let b = 0b10100000;
/// let res = 0b11001000;
///
- /// let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[a]));
- /// let b = BitvSet::from_bitv(Bitv::from_bytes(&[b]));
- /// let res = BitvSet::from_bitv(Bitv::from_bytes(&[res]));
+ /// let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[a]));
+ /// let b = BitSet::from_bit_vec(BitVec::from_bytes(&[b]));
+ /// let res = BitSet::from_bit_vec(BitVec::from_bytes(&[res]));
///
/// a.symmetric_difference_with(&b);
/// assert_eq!(a, res);
/// ```
#[inline]
- pub fn symmetric_difference_with(&mut self, other: &BitvSet) {
+ pub fn symmetric_difference_with(&mut self, other: &BitSet) {
self.other_op(other, |w1, w2| w1 ^ w2);
}
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn len(&self) -> usize {
- self.bitv.blocks().fold(0, |acc, n| acc + n.count_ones())
+ self.bit_vec.blocks().fold(0, |acc, n| acc + n.count_ones())
}
/// Returns whether there are no bits set in this set
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn is_empty(&self) -> bool {
- self.bitv.none()
+ self.bit_vec.none()
}
/// Clears all bits in this set
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn clear(&mut self) {
- self.bitv.clear();
+ self.bit_vec.clear();
}
/// Returns `true` if this set contains the specified integer.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn contains(&self, value: &usize) -> bool {
- let bitv = &self.bitv;
- *value < bitv.nbits && bitv[*value]
+ let bit_vec = &self.bit_vec;
+ *value < bit_vec.nbits && bit_vec[*value]
}
/// Returns `true` if the set has no elements in common with `other`.
/// This is equivalent to checking for an empty intersection.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn is_disjoint(&self, other: &BitvSet) -> bool {
+ pub fn is_disjoint(&self, other: &BitSet) -> bool {
self.intersection(other).next().is_none()
}
/// Returns `true` if the set is a subset of another.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn is_subset(&self, other: &BitvSet) -> bool {
- let self_bitv = &self.bitv;
- let other_bitv = &other.bitv;
- let other_blocks = blocks_for_bits(other_bitv.len());
+ pub fn is_subset(&self, other: &BitSet) -> bool {
+ let self_bit_vec = &self.bit_vec;
+ let other_bit_vec = &other.bit_vec;
+ let other_blocks = blocks_for_bits(other_bit_vec.len());
// Check that `self` intersect `other` is self
- self_bitv.blocks().zip(other_bitv.blocks()).all(|(w1, w2)| w1 & w2 == w1) &&
+ self_bit_vec.blocks().zip(other_bit_vec.blocks()).all(|(w1, w2)| w1 & w2 == w1) &&
// Make sure if `self` has any more blocks than `other`, they're all 0
- self_bitv.blocks().skip(other_blocks).all(|w| w == 0)
+ self_bit_vec.blocks().skip(other_blocks).all(|w| w == 0)
}
/// Returns `true` if the set is a superset of another.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn is_superset(&self, other: &BitvSet) -> bool {
+ pub fn is_superset(&self, other: &BitSet) -> bool {
other.is_subset(self)
}
}
// Ensure we have enough space to hold the new element
- let len = self.bitv.len();
+ let len = self.bit_vec.len();
if value >= len {
- self.bitv.grow(value - len + 1, false)
+ self.bit_vec.grow(value - len + 1, false)
}
- self.bitv.set(value, true);
+ self.bit_vec.set(value, true);
return true;
}
return false;
}
- self.bitv.set(*value, false);
+ self.bit_vec.set(*value, false);
return true;
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl fmt::Debug for BitvSet {
+impl fmt::Debug for BitSet {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- try!(write!(fmt, "BitvSet {{"));
+ try!(write!(fmt, "BitSet {{"));
let mut first = true;
for n in self {
if !first {
}
}
-impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for BitvSet {
+#[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")]
+#[cfg(not(stage0))]
+impl hash::Hash for BitSet {
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ for pos in self {
+ pos.hash(state);
+ }
+ }
+}
-/// An iterator for `BitvSet`.
+/// An iterator for `BitSet`.
#[derive(Clone)]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SetIter<'a> {
- set: &'a BitvSet,
+ set: &'a BitSet,
next_idx: usize
}
-/// An iterator combining two `BitvSet` iterators.
+/// An iterator combining two `BitSet` iterators.
#[derive(Clone)]
struct TwoBitPositions<'a> {
- set: &'a BitvSet,
- other: &'a BitvSet,
+ set: &'a BitSet,
+ other: &'a BitSet,
merge: fn(u32, u32) -> u32,
current_word: u32,
next_idx: usize
type Item = usize;
fn next(&mut self) -> Option<usize> {
- while self.next_idx < self.set.bitv.len() {
+ while self.next_idx < self.set.bit_vec.len() {
let idx = self.next_idx;
self.next_idx += 1;
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
- (0, Some(self.set.bitv.len() - self.next_idx))
+ (0, Some(self.set.bit_vec.len() - self.next_idx))
}
}
type Item = usize;
fn next(&mut self) -> Option<usize> {
- while self.next_idx < self.set.bitv.len() ||
- self.next_idx < self.other.bitv.len() {
+ while self.next_idx < self.set.bit_vec.len() ||
+ self.next_idx < self.other.bit_vec.len() {
let bit_idx = self.next_idx % u32::BITS;
if bit_idx == 0 {
- let s_bitv = &self.set.bitv;
- let o_bitv = &self.other.bitv;
+ let s_bit_vec = &self.set.bit_vec;
+ let o_bit_vec = &self.other.bit_vec;
// Merging the two words is a bit of an awkward dance since
- // one Bitv might be longer than the other
+ // one BitVec might be longer than the other
let word_idx = self.next_idx / u32::BITS;
- let w1 = if word_idx < s_bitv.storage.len() {
- s_bitv.storage[word_idx]
+ let w1 = if word_idx < s_bit_vec.storage.len() {
+ s_bit_vec.storage[word_idx]
} else { 0 };
- let w2 = if word_idx < o_bitv.storage.len() {
- o_bitv.storage[word_idx]
+ let w2 = if word_idx < o_bit_vec.storage.len() {
+ o_bit_vec.storage[word_idx]
} else { 0 };
self.current_word = (self.merge)(w1, w2);
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
- let cap = cmp::max(self.set.bitv.len(), self.other.bitv.len());
+ let cap = cmp::max(self.set.bit_vec.len(), self.other.bit_vec.len());
(0, Some(cap - self.next_idx))
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> IntoIterator for &'a BitvSet {
+impl<'a> IntoIterator for &'a BitSet {
type Item = usize;
type IntoIter = SetIter<'a>;
use prelude::*;
use core::u32;
- use super::Bitv;
+ use super::BitVec;
#[test]
fn test_to_str() {
- let zerolen = Bitv::new();
+ let zerolen = BitVec::new();
assert_eq!(format!("{:?}", zerolen), "");
- let eightbits = Bitv::from_elem(8, false);
+ let eightbits = BitVec::from_elem(8, false);
assert_eq!(format!("{:?}", eightbits), "00000000")
}
#[test]
fn test_0_elements() {
- let act = Bitv::new();
+ let act = BitVec::new();
let exp = Vec::new();
assert!(act.eq_vec(&exp));
assert!(act.none() && act.all());
#[test]
fn test_1_element() {
- let mut act = Bitv::from_elem(1, false);
+ let mut act = BitVec::from_elem(1, false);
assert!(act.eq_vec(&[false]));
assert!(act.none() && !act.all());
- act = Bitv::from_elem(1, true);
+ act = BitVec::from_elem(1, true);
assert!(act.eq_vec(&[true]));
assert!(!act.none() && act.all());
}
#[test]
fn test_2_elements() {
- let mut b = Bitv::from_elem(2, false);
+ let mut b = BitVec::from_elem(2, false);
b.set(0, true);
b.set(1, false);
assert_eq!(format!("{:?}", b), "10");
let mut act;
// all 0
- act = Bitv::from_elem(10, false);
+ act = BitVec::from_elem(10, false);
assert!((act.eq_vec(
&[false, false, false, false, false, false, false, false, false, false])));
assert!(act.none() && !act.all());
// all 1
- act = Bitv::from_elem(10, true);
+ act = BitVec::from_elem(10, true);
assert!((act.eq_vec(&[true, true, true, true, true, true, true, true, true, true])));
assert!(!act.none() && act.all());
// mixed
- act = Bitv::from_elem(10, false);
+ act = BitVec::from_elem(10, false);
act.set(0, true);
act.set(1, true);
act.set(2, true);
assert!(!act.none() && !act.all());
// mixed
- act = Bitv::from_elem(10, false);
+ act = BitVec::from_elem(10, false);
act.set(5, true);
act.set(6, true);
act.set(7, true);
assert!(!act.none() && !act.all());
// mixed
- act = Bitv::from_elem(10, false);
+ act = BitVec::from_elem(10, false);
act.set(0, true);
act.set(3, true);
act.set(6, true);
let mut act;
// all 0
- act = Bitv::from_elem(31, false);
+ act = BitVec::from_elem(31, false);
assert!(act.eq_vec(
&[false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false,
assert!(act.none() && !act.all());
// all 1
- act = Bitv::from_elem(31, true);
+ act = BitVec::from_elem(31, true);
assert!(act.eq_vec(
&[true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, true,
assert!(!act.none() && act.all());
// mixed
- act = Bitv::from_elem(31, false);
+ act = BitVec::from_elem(31, false);
act.set(0, true);
act.set(1, true);
act.set(2, true);
assert!(!act.none() && !act.all());
// mixed
- act = Bitv::from_elem(31, false);
+ act = BitVec::from_elem(31, false);
act.set(16, true);
act.set(17, true);
act.set(18, true);
assert!(!act.none() && !act.all());
// mixed
- act = Bitv::from_elem(31, false);
+ act = BitVec::from_elem(31, false);
act.set(24, true);
act.set(25, true);
act.set(26, true);
assert!(!act.none() && !act.all());
// mixed
- act = Bitv::from_elem(31, false);
+ act = BitVec::from_elem(31, false);
act.set(3, true);
act.set(17, true);
act.set(30, true);
let mut act;
// all 0
- act = Bitv::from_elem(32, false);
+ act = BitVec::from_elem(32, false);
assert!(act.eq_vec(
&[false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false,
assert!(act.none() && !act.all());
// all 1
- act = Bitv::from_elem(32, true);
+ act = BitVec::from_elem(32, true);
assert!(act.eq_vec(
&[true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, true,
assert!(!act.none() && act.all());
// mixed
- act = Bitv::from_elem(32, false);
+ act = BitVec::from_elem(32, false);
act.set(0, true);
act.set(1, true);
act.set(2, true);
assert!(!act.none() && !act.all());
// mixed
- act = Bitv::from_elem(32, false);
+ act = BitVec::from_elem(32, false);
act.set(16, true);
act.set(17, true);
act.set(18, true);
assert!(!act.none() && !act.all());
// mixed
- act = Bitv::from_elem(32, false);
+ act = BitVec::from_elem(32, false);
act.set(24, true);
act.set(25, true);
act.set(26, true);
assert!(!act.none() && !act.all());
// mixed
- act = Bitv::from_elem(32, false);
+ act = BitVec::from_elem(32, false);
act.set(3, true);
act.set(17, true);
act.set(30, true);
let mut act;
// all 0
- act = Bitv::from_elem(33, false);
+ act = BitVec::from_elem(33, false);
assert!(act.eq_vec(
&[false, false, false, false, false, false, false, false, false, false, false,
false, false, false, false, false, false, false, false, false, false, false,
assert!(act.none() && !act.all());
// all 1
- act = Bitv::from_elem(33, true);
+ act = BitVec::from_elem(33, true);
assert!(act.eq_vec(
&[true, true, true, true, true, true, true, true, true, true, true, true, true,
true, true, true, true, true, true, true, true, true, true, true, true, true,
assert!(!act.none() && act.all());
// mixed
- act = Bitv::from_elem(33, false);
+ act = BitVec::from_elem(33, false);
act.set(0, true);
act.set(1, true);
act.set(2, true);
assert!(!act.none() && !act.all());
// mixed
- act = Bitv::from_elem(33, false);
+ act = BitVec::from_elem(33, false);
act.set(16, true);
act.set(17, true);
act.set(18, true);
assert!(!act.none() && !act.all());
// mixed
- act = Bitv::from_elem(33, false);
+ act = BitVec::from_elem(33, false);
act.set(24, true);
act.set(25, true);
act.set(26, true);
assert!(!act.none() && !act.all());
// mixed
- act = Bitv::from_elem(33, false);
+ act = BitVec::from_elem(33, false);
act.set(3, true);
act.set(17, true);
act.set(30, true);
#[test]
fn test_equal_differing_sizes() {
- let v0 = Bitv::from_elem(10, false);
- let v1 = Bitv::from_elem(11, false);
+ let v0 = BitVec::from_elem(10, false);
+ let v1 = BitVec::from_elem(11, false);
assert!(v0 != v1);
}
#[test]
fn test_equal_greatly_differing_sizes() {
- let v0 = Bitv::from_elem(10, false);
- let v1 = Bitv::from_elem(110, false);
+ let v0 = BitVec::from_elem(10, false);
+ let v1 = BitVec::from_elem(110, false);
assert!(v0 != v1);
}
#[test]
fn test_equal_sneaky_small() {
- let mut a = Bitv::from_elem(1, false);
+ let mut a = BitVec::from_elem(1, false);
a.set(0, true);
- let mut b = Bitv::from_elem(1, true);
+ let mut b = BitVec::from_elem(1, true);
b.set(0, true);
assert_eq!(a, b);
#[test]
fn test_equal_sneaky_big() {
- let mut a = Bitv::from_elem(100, false);
+ let mut a = BitVec::from_elem(100, false);
for i in 0..100 {
a.set(i, true);
}
- let mut b = Bitv::from_elem(100, true);
+ let mut b = BitVec::from_elem(100, true);
for i in 0..100 {
b.set(i, true);
}
#[test]
fn test_from_bytes() {
- let bitv = Bitv::from_bytes(&[0b10110110, 0b00000000, 0b11111111]);
+ let bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]);
let str = concat!("10110110", "00000000", "11111111");
- assert_eq!(format!("{:?}", bitv), str);
+ assert_eq!(format!("{:?}", bit_vec), str);
}
#[test]
fn test_to_bytes() {
- let mut bv = Bitv::from_elem(3, true);
+ let mut bv = BitVec::from_elem(3, true);
bv.set(1, false);
assert_eq!(bv.to_bytes(), vec!(0b10100000));
- let mut bv = Bitv::from_elem(9, false);
+ let mut bv = BitVec::from_elem(9, false);
bv.set(2, true);
bv.set(8, true);
assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000));
#[test]
fn test_from_bools() {
let bools = vec![true, false, true, true];
- let bitv: Bitv = bools.iter().map(|n| *n).collect();
- assert_eq!(format!("{:?}", bitv), "1011");
+ let bit_vec: BitVec = bools.iter().map(|n| *n).collect();
+ assert_eq!(format!("{:?}", bit_vec), "1011");
}
#[test]
fn test_to_bools() {
let bools = vec![false, false, true, false, false, true, true, false];
- assert_eq!(Bitv::from_bytes(&[0b00100110]).iter().collect::<Vec<bool>>(), bools);
+ assert_eq!(BitVec::from_bytes(&[0b00100110]).iter().collect::<Vec<bool>>(), bools);
}
#[test]
- fn test_bitv_iterator() {
+ fn test_bit_vec_iterator() {
let bools = vec![true, false, true, true];
- let bitv: Bitv = bools.iter().map(|n| *n).collect();
+ let bit_vec: BitVec = bools.iter().map(|n| *n).collect();
- assert_eq!(bitv.iter().collect::<Vec<bool>>(), bools);
+ assert_eq!(bit_vec.iter().collect::<Vec<bool>>(), bools);
let long: Vec<_> = (0i32..10000).map(|i| i % 2 == 0).collect();
- let bitv: Bitv = long.iter().map(|n| *n).collect();
- assert_eq!(bitv.iter().collect::<Vec<bool>>(), long)
+ let bit_vec: BitVec = long.iter().map(|n| *n).collect();
+ assert_eq!(bit_vec.iter().collect::<Vec<bool>>(), long)
}
#[test]
fn test_small_difference() {
- let mut b1 = Bitv::from_elem(3, false);
- let mut b2 = Bitv::from_elem(3, false);
+ let mut b1 = BitVec::from_elem(3, false);
+ let mut b2 = BitVec::from_elem(3, false);
b1.set(0, true);
b1.set(1, true);
b2.set(1, true);
#[test]
fn test_big_difference() {
- let mut b1 = Bitv::from_elem(100, false);
- let mut b2 = Bitv::from_elem(100, false);
+ let mut b1 = BitVec::from_elem(100, false);
+ let mut b2 = BitVec::from_elem(100, false);
b1.set(0, true);
b1.set(40, true);
b2.set(40, true);
#[test]
fn test_small_clear() {
- let mut b = Bitv::from_elem(14, true);
+ let mut b = BitVec::from_elem(14, true);
assert!(!b.none() && b.all());
b.clear();
assert!(b.none() && !b.all());
#[test]
fn test_big_clear() {
- let mut b = Bitv::from_elem(140, true);
+ let mut b = BitVec::from_elem(140, true);
assert!(!b.none() && b.all());
b.clear();
assert!(b.none() && !b.all());
}
#[test]
- fn test_bitv_lt() {
- let mut a = Bitv::from_elem(5, false);
- let mut b = Bitv::from_elem(5, false);
+ fn test_bit_vec_lt() {
+ let mut a = BitVec::from_elem(5, false);
+ let mut b = BitVec::from_elem(5, false);
assert!(!(a < b) && !(b < a));
b.set(2, true);
#[test]
fn test_ord() {
- let mut a = Bitv::from_elem(5, false);
- let mut b = Bitv::from_elem(5, false);
+ let mut a = BitVec::from_elem(5, false);
+ let mut b = BitVec::from_elem(5, false);
assert!(a <= b && a >= b);
a.set(1, true);
#[test]
- fn test_small_bitv_tests() {
- let v = Bitv::from_bytes(&[0]);
+ fn test_small_bit_vec_tests() {
+ let v = BitVec::from_bytes(&[0]);
assert!(!v.all());
assert!(!v.any());
assert!(v.none());
- let v = Bitv::from_bytes(&[0b00010100]);
+ let v = BitVec::from_bytes(&[0b00010100]);
assert!(!v.all());
assert!(v.any());
assert!(!v.none());
- let v = Bitv::from_bytes(&[0xFF]);
+ let v = BitVec::from_bytes(&[0xFF]);
assert!(v.all());
assert!(v.any());
assert!(!v.none());
}
#[test]
- fn test_big_bitv_tests() {
- let v = Bitv::from_bytes(&[ // 88 bits
+ fn test_big_bit_vec_tests() {
+ let v = BitVec::from_bytes(&[ // 88 bits
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0]);
assert!(!v.any());
assert!(v.none());
- let v = Bitv::from_bytes(&[ // 88 bits
+ let v = BitVec::from_bytes(&[ // 88 bits
0, 0, 0b00010100, 0,
0, 0, 0, 0b00110100,
0, 0, 0]);
assert!(v.any());
assert!(!v.none());
- let v = Bitv::from_bytes(&[ // 88 bits
+ let v = BitVec::from_bytes(&[ // 88 bits
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF]);
}
#[test]
- fn test_bitv_push_pop() {
- let mut s = Bitv::from_elem(5 * u32::BITS - 2, false);
+ fn test_bit_vec_push_pop() {
+ let mut s = BitVec::from_elem(5 * u32::BITS - 2, false);
assert_eq!(s.len(), 5 * u32::BITS - 2);
assert_eq!(s[5 * u32::BITS - 3], false);
s.push(true);
}
#[test]
- fn test_bitv_truncate() {
- let mut s = Bitv::from_elem(5 * u32::BITS, true);
+ fn test_bit_vec_truncate() {
+ let mut s = BitVec::from_elem(5 * u32::BITS, true);
- assert_eq!(s, Bitv::from_elem(5 * u32::BITS, true));
+ assert_eq!(s, BitVec::from_elem(5 * u32::BITS, true));
assert_eq!(s.len(), 5 * u32::BITS);
s.truncate(4 * u32::BITS);
- assert_eq!(s, Bitv::from_elem(4 * u32::BITS, true));
+ assert_eq!(s, BitVec::from_elem(4 * u32::BITS, true));
assert_eq!(s.len(), 4 * u32::BITS);
// Truncating to a size > s.len() should be a noop
s.truncate(5 * u32::BITS);
- assert_eq!(s, Bitv::from_elem(4 * u32::BITS, true));
+ assert_eq!(s, BitVec::from_elem(4 * u32::BITS, true));
assert_eq!(s.len(), 4 * u32::BITS);
s.truncate(3 * u32::BITS - 10);
- assert_eq!(s, Bitv::from_elem(3 * u32::BITS - 10, true));
+ assert_eq!(s, BitVec::from_elem(3 * u32::BITS - 10, true));
assert_eq!(s.len(), 3 * u32::BITS - 10);
s.truncate(0);
- assert_eq!(s, Bitv::from_elem(0, true));
+ assert_eq!(s, BitVec::from_elem(0, true));
assert_eq!(s.len(), 0);
}
#[test]
- fn test_bitv_reserve() {
- let mut s = Bitv::from_elem(5 * u32::BITS, true);
+ fn test_bit_vec_reserve() {
+ let mut s = BitVec::from_elem(5 * u32::BITS, true);
// Check capacity
assert!(s.capacity() >= 5 * u32::BITS);
s.reserve(2 * u32::BITS);
}
#[test]
- fn test_bitv_grow() {
- let mut bitv = Bitv::from_bytes(&[0b10110110, 0b00000000, 0b10101010]);
- bitv.grow(32, true);
- assert_eq!(bitv, Bitv::from_bytes(&[0b10110110, 0b00000000, 0b10101010,
+ fn test_bit_vec_grow() {
+ let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010]);
+ bit_vec.grow(32, true);
+ assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010,
0xFF, 0xFF, 0xFF, 0xFF]));
- bitv.grow(64, false);
- assert_eq!(bitv, Bitv::from_bytes(&[0b10110110, 0b00000000, 0b10101010,
+ bit_vec.grow(64, false);
+ assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010,
0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0]));
- bitv.grow(16, true);
- assert_eq!(bitv, Bitv::from_bytes(&[0b10110110, 0b00000000, 0b10101010,
+ bit_vec.grow(16, true);
+ assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b10101010,
0xFF, 0xFF, 0xFF, 0xFF, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF]));
}
#[test]
- fn test_bitv_extend() {
- let mut bitv = Bitv::from_bytes(&[0b10110110, 0b00000000, 0b11111111]);
- let ext = Bitv::from_bytes(&[0b01001001, 0b10010010, 0b10111101]);
- bitv.extend(ext.iter());
- assert_eq!(bitv, Bitv::from_bytes(&[0b10110110, 0b00000000, 0b11111111,
+ fn test_bit_vec_extend() {
+ let mut bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]);
+ let ext = BitVec::from_bytes(&[0b01001001, 0b10010010, 0b10111101]);
+ bit_vec.extend(ext.iter());
+ assert_eq!(bit_vec, BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111,
0b01001001, 0b10010010, 0b10111101]));
}
}
#[cfg(test)]
-mod bitv_bench {
+mod bit_vec_bench {
use std::prelude::v1::*;
use std::rand;
use std::rand::Rng;
use std::u32;
use test::{Bencher, black_box};
- use super::Bitv;
+ use super::BitVec;
static BENCH_BITS : usize = 1 << 14;
#[bench]
fn bench_usize_small(b: &mut Bencher) {
let mut r = rng();
- let mut bitv = 0 as usize;
+ let mut bit_vec = 0 as usize;
b.iter(|| {
for _ in 0..100 {
- bitv |= 1 << ((r.next_u32() as usize) % u32::BITS);
+ bit_vec |= 1 << ((r.next_u32() as usize) % u32::BITS);
}
- black_box(&bitv);
+ black_box(&bit_vec);
});
}
#[bench]
- fn bench_bitv_set_big_fixed(b: &mut Bencher) {
+ fn bench_bit_set_big_fixed(b: &mut Bencher) {
let mut r = rng();
- let mut bitv = Bitv::from_elem(BENCH_BITS, false);
+ let mut bit_vec = BitVec::from_elem(BENCH_BITS, false);
b.iter(|| {
for _ in 0..100 {
- bitv.set((r.next_u32() as usize) % BENCH_BITS, true);
+ bit_vec.set((r.next_u32() as usize) % BENCH_BITS, true);
}
- black_box(&bitv);
+ black_box(&bit_vec);
});
}
#[bench]
- fn bench_bitv_set_big_variable(b: &mut Bencher) {
+ fn bench_bit_set_big_variable(b: &mut Bencher) {
let mut r = rng();
- let mut bitv = Bitv::from_elem(BENCH_BITS, false);
+ let mut bit_vec = BitVec::from_elem(BENCH_BITS, false);
b.iter(|| {
for _ in 0..100 {
- bitv.set((r.next_u32() as usize) % BENCH_BITS, r.gen());
+ bit_vec.set((r.next_u32() as usize) % BENCH_BITS, r.gen());
}
- black_box(&bitv);
+ black_box(&bit_vec);
});
}
#[bench]
- fn bench_bitv_set_small(b: &mut Bencher) {
+ fn bench_bit_set_small(b: &mut Bencher) {
let mut r = rng();
- let mut bitv = Bitv::from_elem(u32::BITS, false);
+ let mut bit_vec = BitVec::from_elem(u32::BITS, false);
b.iter(|| {
for _ in 0..100 {
- bitv.set((r.next_u32() as usize) % u32::BITS, true);
+ bit_vec.set((r.next_u32() as usize) % u32::BITS, true);
}
- black_box(&bitv);
+ black_box(&bit_vec);
});
}
#[bench]
- fn bench_bitv_big_union(b: &mut Bencher) {
- let mut b1 = Bitv::from_elem(BENCH_BITS, false);
- let b2 = Bitv::from_elem(BENCH_BITS, false);
+ fn bench_bit_vec_big_union(b: &mut Bencher) {
+ let mut b1 = BitVec::from_elem(BENCH_BITS, false);
+ let b2 = BitVec::from_elem(BENCH_BITS, false);
b.iter(|| {
b1.union(&b2)
})
}
#[bench]
- fn bench_bitv_small_iter(b: &mut Bencher) {
- let bitv = Bitv::from_elem(u32::BITS, false);
+ fn bench_bit_vec_small_iter(b: &mut Bencher) {
+ let bit_vec = BitVec::from_elem(u32::BITS, false);
b.iter(|| {
let mut sum = 0;
for _ in 0..10 {
- for pres in &bitv {
+ for pres in &bit_vec {
sum += pres as usize;
}
}
}
#[bench]
- fn bench_bitv_big_iter(b: &mut Bencher) {
- let bitv = Bitv::from_elem(BENCH_BITS, false);
+ fn bench_bit_vec_big_iter(b: &mut Bencher) {
+ let bit_vec = BitVec::from_elem(BENCH_BITS, false);
b.iter(|| {
let mut sum = 0;
- for pres in &bitv {
+ for pres in &bit_vec {
sum += pres as usize;
}
sum
#[cfg(test)]
-mod bitv_set_test {
+mod bit_set_test {
use prelude::*;
use std::iter::range_step;
- use super::{Bitv, BitvSet};
+ use super::{BitVec, BitSet};
#[test]
- fn test_bitv_set_show() {
- let mut s = BitvSet::new();
+ fn test_bit_set_show() {
+ let mut s = BitSet::new();
s.insert(1);
s.insert(10);
s.insert(50);
s.insert(2);
- assert_eq!("BitvSet {1, 2, 10, 50}", format!("{:?}", s));
+ assert_eq!("BitSet {1, 2, 10, 50}", format!("{:?}", s));
}
#[test]
- fn test_bitv_set_from_usizes() {
+ fn test_bit_set_from_usizes() {
let usizes = vec![0, 2, 2, 3];
- let a: BitvSet = usizes.into_iter().collect();
- let mut b = BitvSet::new();
+ let a: BitSet = usizes.into_iter().collect();
+ let mut b = BitSet::new();
b.insert(0);
b.insert(2);
b.insert(3);
}
#[test]
- fn test_bitv_set_iterator() {
+ fn test_bit_set_iterator() {
let usizes = vec![0, 2, 2, 3];
- let bitv: BitvSet = usizes.into_iter().collect();
+ let bit_vec: BitSet = usizes.into_iter().collect();
- let idxs: Vec<_> = bitv.iter().collect();
+ let idxs: Vec<_> = bit_vec.iter().collect();
assert_eq!(idxs, vec![0, 2, 3]);
- let long: BitvSet = (0..10000).filter(|&n| n % 2 == 0).collect();
+ let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect();
let real: Vec<_> = range_step(0, 10000, 2).collect();
let idxs: Vec<_> = long.iter().collect();
}
#[test]
- fn test_bitv_set_frombitv_init() {
+ fn test_bit_set_frombit_vec_init() {
let bools = [true, false];
let lengths = [10, 64, 100];
for &b in &bools {
for &l in &lengths {
- let bitset = BitvSet::from_bitv(Bitv::from_elem(l, b));
+ let bitset = BitSet::from_bit_vec(BitVec::from_elem(l, b));
assert_eq!(bitset.contains(&1), b);
assert_eq!(bitset.contains(&(l-1)), b);
assert!(!bitset.contains(&l));
}
#[test]
- fn test_bitv_masking() {
- let b = Bitv::from_elem(140, true);
- let mut bs = BitvSet::from_bitv(b);
+ fn test_bit_vec_masking() {
+ let b = BitVec::from_elem(140, true);
+ let mut bs = BitSet::from_bit_vec(b);
assert!(bs.contains(&139));
assert!(!bs.contains(&140));
assert!(bs.insert(150));
}
#[test]
- fn test_bitv_set_basic() {
- let mut b = BitvSet::new();
+ fn test_bit_set_basic() {
+ let mut b = BitSet::new();
assert!(b.insert(3));
assert!(!b.insert(3));
assert!(b.contains(&3));
}
#[test]
- fn test_bitv_set_intersection() {
- let mut a = BitvSet::new();
- let mut b = BitvSet::new();
+ fn test_bit_set_intersection() {
+ let mut a = BitSet::new();
+ let mut b = BitSet::new();
assert!(a.insert(11));
assert!(a.insert(1));
}
#[test]
- fn test_bitv_set_difference() {
- let mut a = BitvSet::new();
- let mut b = BitvSet::new();
+ fn test_bit_set_difference() {
+ let mut a = BitSet::new();
+ let mut b = BitSet::new();
assert!(a.insert(1));
assert!(a.insert(3));
}
#[test]
- fn test_bitv_set_symmetric_difference() {
- let mut a = BitvSet::new();
- let mut b = BitvSet::new();
+ fn test_bit_set_symmetric_difference() {
+ let mut a = BitSet::new();
+ let mut b = BitSet::new();
assert!(a.insert(1));
assert!(a.insert(3));
}
#[test]
- fn test_bitv_set_union() {
- let mut a = BitvSet::new();
- let mut b = BitvSet::new();
+ fn test_bit_set_union() {
+ let mut a = BitSet::new();
+ let mut b = BitSet::new();
assert!(a.insert(1));
assert!(a.insert(3));
assert!(a.insert(5));
}
#[test]
- fn test_bitv_set_subset() {
- let mut set1 = BitvSet::new();
- let mut set2 = BitvSet::new();
+ fn test_bit_set_subset() {
+ let mut set1 = BitSet::new();
+ let mut set2 = BitSet::new();
assert!(set1.is_subset(&set2)); // {} {}
set2.insert(100);
}
#[test]
- fn test_bitv_set_is_disjoint() {
- let a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010]));
- let b = BitvSet::from_bitv(Bitv::from_bytes(&[0b01000000]));
- let c = BitvSet::new();
- let d = BitvSet::from_bitv(Bitv::from_bytes(&[0b00110000]));
+ fn test_bit_set_is_disjoint() {
+ let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010]));
+ let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01000000]));
+ let c = BitSet::new();
+ let d = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00110000]));
assert!(!a.is_disjoint(&d));
assert!(!d.is_disjoint(&a));
}
#[test]
- fn test_bitv_set_union_with() {
+ fn test_bit_set_union_with() {
//a should grow to include larger elements
- let mut a = BitvSet::new();
+ let mut a = BitSet::new();
a.insert(0);
- let mut b = BitvSet::new();
+ let mut b = BitSet::new();
b.insert(5);
- let expected = BitvSet::from_bitv(Bitv::from_bytes(&[0b10000100]));
+ let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100]));
a.union_with(&b);
assert_eq!(a, expected);
// Standard
- let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010]));
- let mut b = BitvSet::from_bitv(Bitv::from_bytes(&[0b01100010]));
+ let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010]));
+ let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010]));
let c = a.clone();
a.union_with(&b);
b.union_with(&c);
}
#[test]
- fn test_bitv_set_intersect_with() {
+ fn test_bit_set_intersect_with() {
// Explicitly 0'ed bits
- let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010]));
- let mut b = BitvSet::from_bitv(Bitv::from_bytes(&[0b00000000]));
+ let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010]));
+ let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000]));
let c = a.clone();
a.intersect_with(&b);
b.intersect_with(&c);
assert!(b.is_empty());
// Uninitialized bits should behave like 0's
- let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010]));
- let mut b = BitvSet::new();
+ let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010]));
+ let mut b = BitSet::new();
let c = a.clone();
a.intersect_with(&b);
b.intersect_with(&c);
assert!(b.is_empty());
// Standard
- let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010]));
- let mut b = BitvSet::from_bitv(Bitv::from_bytes(&[0b01100010]));
+ let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010]));
+ let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010]));
let c = a.clone();
a.intersect_with(&b);
b.intersect_with(&c);
}
#[test]
- fn test_bitv_set_difference_with() {
+ fn test_bit_set_difference_with() {
// Explicitly 0'ed bits
- let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b00000000]));
- let b = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010]));
+ let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000]));
+ let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010]));
a.difference_with(&b);
assert!(a.is_empty());
// Uninitialized bits should behave like 0's
- let mut a = BitvSet::new();
- let b = BitvSet::from_bitv(Bitv::from_bytes(&[0b11111111]));
+ let mut a = BitSet::new();
+ let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11111111]));
a.difference_with(&b);
assert!(a.is_empty());
// Standard
- let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010]));
- let mut b = BitvSet::from_bitv(Bitv::from_bytes(&[0b01100010]));
+ let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010]));
+ let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01100010]));
let c = a.clone();
a.difference_with(&b);
b.difference_with(&c);
}
#[test]
- fn test_bitv_set_symmetric_difference_with() {
+ fn test_bit_set_symmetric_difference_with() {
//a should grow to include larger elements
- let mut a = BitvSet::new();
+ let mut a = BitSet::new();
a.insert(0);
a.insert(1);
- let mut b = BitvSet::new();
+ let mut b = BitSet::new();
b.insert(1);
b.insert(5);
- let expected = BitvSet::from_bitv(Bitv::from_bytes(&[0b10000100]));
+ let expected = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10000100]));
a.symmetric_difference_with(&b);
assert_eq!(a, expected);
- let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010]));
- let b = BitvSet::new();
+ let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010]));
+ let b = BitSet::new();
let c = a.clone();
a.symmetric_difference_with(&b);
assert_eq!(a, c);
// Standard
- let mut a = BitvSet::from_bitv(Bitv::from_bytes(&[0b11100010]));
- let mut b = BitvSet::from_bitv(Bitv::from_bytes(&[0b01101010]));
+ let mut a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b11100010]));
+ let mut b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b01101010]));
let c = a.clone();
a.symmetric_difference_with(&b);
b.symmetric_difference_with(&c);
}
#[test]
- fn test_bitv_set_eq() {
- let a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010]));
- let b = BitvSet::from_bitv(Bitv::from_bytes(&[0b00000000]));
- let c = BitvSet::new();
+ fn test_bit_set_eq() {
+ let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010]));
+ let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000]));
+ let c = BitSet::new();
assert!(a == a);
assert!(a != b);
}
#[test]
- fn test_bitv_set_cmp() {
- let a = BitvSet::from_bitv(Bitv::from_bytes(&[0b10100010]));
- let b = BitvSet::from_bitv(Bitv::from_bytes(&[0b00000000]));
- let c = BitvSet::new();
+ fn test_bit_set_cmp() {
+ let a = BitSet::from_bit_vec(BitVec::from_bytes(&[0b10100010]));
+ let b = BitSet::from_bit_vec(BitVec::from_bytes(&[0b00000000]));
+ let c = BitSet::new();
assert_eq!(a.cmp(&b), Greater);
assert_eq!(a.cmp(&c), Greater);
}
#[test]
- fn test_bitv_remove() {
- let mut a = BitvSet::new();
+ fn test_bit_vec_remove() {
+ let mut a = BitSet::new();
assert!(a.insert(1));
assert!(a.remove(&1));
}
#[test]
- fn test_bitv_clone() {
- let mut a = BitvSet::new();
+ fn test_bit_vec_clone() {
+ let mut a = BitSet::new();
assert!(a.insert(1));
assert!(a.insert(100));
#[cfg(test)]
-mod bitv_set_bench {
+mod bit_set_bench {
use std::prelude::v1::*;
use std::rand;
use std::rand::Rng;
use std::u32;
use test::{Bencher, black_box};
- use super::{Bitv, BitvSet};
+ use super::{BitVec, BitSet};
static BENCH_BITS : usize = 1 << 14;
}
#[bench]
- fn bench_bitvset_small(b: &mut Bencher) {
+ fn bench_bit_vecset_small(b: &mut Bencher) {
let mut r = rng();
- let mut bitv = BitvSet::new();
+ let mut bit_vec = BitSet::new();
b.iter(|| {
for _ in 0..100 {
- bitv.insert((r.next_u32() as usize) % u32::BITS);
+ bit_vec.insert((r.next_u32() as usize) % u32::BITS);
}
- black_box(&bitv);
+ black_box(&bit_vec);
});
}
#[bench]
- fn bench_bitvset_big(b: &mut Bencher) {
+ fn bench_bit_vecset_big(b: &mut Bencher) {
let mut r = rng();
- let mut bitv = BitvSet::new();
+ let mut bit_vec = BitSet::new();
b.iter(|| {
for _ in 0..100 {
- bitv.insert((r.next_u32() as usize) % BENCH_BITS);
+ bit_vec.insert((r.next_u32() as usize) % BENCH_BITS);
}
- black_box(&bitv);
+ black_box(&bit_vec);
});
}
#[bench]
- fn bench_bitvset_iter(b: &mut Bencher) {
- let bitv = BitvSet::from_bitv(Bitv::from_fn(BENCH_BITS,
+ fn bench_bit_vecset_iter(b: &mut Bencher) {
+ let bit_vec = BitSet::from_bit_vec(BitVec::from_fn(BENCH_BITS,
|idx| {idx % 3 == 0}));
b.iter(|| {
let mut sum = 0;
- for idx in &bitv {
+ for idx in &bit_vec {
sum += idx as usize;
}
sum
--- /dev/null
+// 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 {
+ /// 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 {
+ 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 {
+ type Target = B;
+
+ fn deref(&self) -> &B {
+ match *self {
+ Borrowed(borrowed) => borrowed,
+ Owned(ref owned) => owned.borrow()
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
+ #[inline]
+ fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
+ Ord::cmp(&**self, &**other)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> where
+ B: PartialEq<C> + ToOwned, C: ToOwned,
+{
+ #[inline]
+ fn eq(&self, other: &Cow<'b, C>) -> bool {
+ PartialEq::eq(&**self, &**other)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned,
+{
+ #[inline]
+ fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<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")]
+#[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
+{
+ #[inline]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ 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
+ }
+}
--- /dev/null
+// 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
+ }
+}
use core::prelude::*;
-use core::borrow::BorrowFrom;
use core::cmp::Ordering;
use core::default::Default;
use core::fmt::Debug;
use core::{iter, fmt, mem};
use Bound::{self, Included, Excluded, Unbounded};
-use ring_buf::RingBuf;
+use borrow::Borrow;
+use vec_deque::VecDeque;
use self::Continuation::{Continue, Finished};
use self::StackOp::*;
/// An abstract base over-which all other BTree iterators are built.
struct AbsIter<T> {
- traversals: RingBuf<T>,
+ traversals: VecDeque<T>,
size: usize,
}
/// assert_eq!(map.get(&2), None);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V> where Q: BorrowFrom<K> + Ord {
+ pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V> where K: Borrow<Q>, Q: Ord {
let mut cur_node = &self.root;
loop {
match Node::search(cur_node, key) {
/// assert_eq!(map.contains_key(&2), false);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool where Q: BorrowFrom<K> + Ord {
+ pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool where K: Borrow<Q>, Q: Ord {
self.get(key).is_some()
}
/// ```
// See `get` for implementation notes, this is basically a copy-paste with mut's added
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom<K> + Ord {
+ pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V> where K: Borrow<Q>, Q: Ord {
// temp_node is a Borrowck hack for having a mutable value outlive a loop iteration
let mut temp_node = &mut self.root;
loop {
/// assert_eq!(map.remove(&1), None);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V> where Q: BorrowFrom<K> + Ord {
+ pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V> where K: Borrow<Q>, Q: Ord {
// See `swap` for a more thorough description of the stuff going on in here
let mut stack = stack::PartialSearchStack::new(self);
loop {
use super::super::node::handle;
use vec::Vec;
+ struct InvariantLifetime<'id>(
+ marker::PhantomData<::core::cell::Cell<&'id ()>>);
+
+ impl<'id> InvariantLifetime<'id> {
+ fn new() -> InvariantLifetime<'id> {
+ InvariantLifetime(marker::PhantomData)
+ }
+ }
+
/// A generic mutable reference, identical to `&mut` except for the fact that its lifetime
/// parameter is invariant. This means that wherever an `IdRef` is expected, only an `IdRef`
/// with the exact requested lifetime can be used. This is in contrast to normal references,
/// where `&'static` can be used in any function expecting any lifetime reference.
pub struct IdRef<'id, T: 'id> {
inner: &'id mut T,
- marker: marker::InvariantLifetime<'id>
+ _marker: InvariantLifetime<'id>,
}
impl<'id, T> Deref for IdRef<'id, T> {
pub struct Pusher<'id, 'a, K:'a, V:'a> {
map: &'a mut BTreeMap<K, V>,
stack: Stack<K, V>,
- marker: marker::InvariantLifetime<'id>
+ _marker: InvariantLifetime<'id>,
}
impl<'a, K, V> PartialSearchStack<'a, K, V> {
let pusher = Pusher {
map: self.map,
stack: self.stack,
- marker: marker::InvariantLifetime
+ _marker: InvariantLifetime::new(),
};
let node = IdRef {
inner: unsafe { &mut *self.next },
- marker: marker::InvariantLifetime
+ _marker: InvariantLifetime::new(),
};
closure(pusher, node)
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
- fn from_iter<T: Iterator<Item=(K, V)>>(iter: T) -> BTreeMap<K, V> {
+ fn from_iter<T: IntoIterator<Item=(K, V)>>(iter: T) -> BTreeMap<K, V> {
let mut map = BTreeMap::new();
map.extend(iter);
map
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
#[inline]
- fn extend<T: Iterator<Item=(K, V)>>(&mut self, iter: T) {
+ fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) {
for (k, v) in iter {
self.insert(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) {
}
}
}
+#[cfg(not(stage0))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<K: Hash, V: Hash> Hash for BTreeMap<K, V> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ for elt in self {
+ elt.hash(state);
+ }
+ }
+}
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, V> Default for BTreeMap<K, V> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, Q: ?Sized, V> Index<Q> for BTreeMap<K, V>
- where Q: BorrowFrom<K> + Ord
+ where K: Borrow<Q>, Q: Ord
{
type Output = V;
#[stable(feature = "rust1", since = "1.0.0")]
impl<K: Ord, Q: ?Sized, V> IndexMut<Q> for BTreeMap<K, V>
- where Q: BorrowFrom<K> + Ord
+ where K: Borrow<Q>, Q: Ord
{
fn index_mut(&mut self, key: &Q) -> &mut V {
self.get_mut(key).expect("no entry found for key")
pub fn iter(&self) -> Iter<K, V> {
let len = self.len();
// NB. The initial capacity for ringbuf is large enough to avoid reallocs in many cases.
- let mut lca = RingBuf::new();
+ let mut lca = VecDeque::new();
lca.push_back(Traverse::traverse(&self.root));
Iter {
inner: AbsIter {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn iter_mut(&mut self) -> IterMut<K, V> {
let len = self.len();
- let mut lca = RingBuf::new();
+ let mut lca = VecDeque::new();
lca.push_back(Traverse::traverse(&mut self.root));
IterMut {
inner: AbsIter {
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_iter(self) -> IntoIter<K, V> {
let len = self.len();
- let mut lca = RingBuf::new();
+ let mut lca = VecDeque::new();
lca.push_back(Traverse::traverse(self.root));
IntoIter {
inner: AbsIter {
// A deque that encodes two search paths containing (left-to-right):
// a series of truncated-from-the-left iterators, the LCA's doubly-truncated iterator,
// and a series of truncated-from-the-right iterators.
- let mut traversals = RingBuf::new();
+ let mut traversals = VecDeque::new();
let (root, min, max) = ($root, $min, $max);
let mut leftmost = None;
use core::prelude::*;
-use core::borrow::BorrowFrom;
use core::cmp::Ordering::{Greater, Less, Equal};
use core::iter::Zip;
+use core::marker::PhantomData;
use core::ops::{Deref, DerefMut, Index, IndexMut};
use core::ptr::Unique;
use core::{slice, mem, ptr, cmp, num, raw};
-use alloc::heap;
+use alloc::heap::{self, EMPTY};
+
+use borrow::Borrow;
/// Represents the result of an Insertion: either the item fit, or the node had to split
pub enum InsertionResult<K, V> {
keys: Unique<K>,
vals: Unique<V>,
- // In leaf nodes, this will be null, and no space will be allocated for edges.
- edges: Unique<Node<K, V>>,
+ // In leaf nodes, this will be None, and no space will be allocated for edges.
+ edges: Option<Unique<Node<K, V>>>,
// At any given time, there will be `_len` keys, `_len` values, and (in an internal node)
// `_len + 1` edges. In a leaf node, there will never be any edges.
#[unsafe_destructor]
impl<K, V> Drop for Node<K, V> {
fn drop(&mut self) {
- if self.keys.ptr.is_null() {
- // We have already cleaned up this node.
+ if self.keys.is_null() {
+ // Since we have #[unsafe_no_drop_flag], we have to watch
+ // out for a null value being stored in self.keys. (Using
+ // null is technically a violation of the `Unique`
+ // requirements, though.)
return;
}
self.destroy();
}
- self.keys.ptr = ptr::null_mut();
+ self.keys = unsafe { Unique::new(0 as *mut K) };
}
}
let (vals_offset, edges_offset) = calculate_offsets_generic::<K, V>(capacity, false);
Node {
- keys: Unique(buffer as *mut K),
- vals: Unique(buffer.offset(vals_offset as isize) as *mut V),
- edges: Unique(buffer.offset(edges_offset as isize) as *mut Node<K, V>),
+ keys: Unique::new(buffer as *mut K),
+ vals: Unique::new(buffer.offset(vals_offset as isize) as *mut V),
+ edges: Some(Unique::new(buffer.offset(edges_offset as isize) as *mut Node<K, V>)),
_len: 0,
_capacity: capacity,
}
let (vals_offset, _) = calculate_offsets_generic::<K, V>(capacity, true);
Node {
- keys: Unique(buffer as *mut K),
- vals: Unique(unsafe { buffer.offset(vals_offset as isize) as *mut V }),
- edges: Unique(ptr::null_mut()),
+ keys: unsafe { Unique::new(buffer as *mut K) },
+ vals: unsafe { Unique::new(buffer.offset(vals_offset as isize) as *mut V) },
+ edges: None,
_len: 0,
_capacity: capacity,
}
unsafe fn destroy(&mut self) {
let (alignment, size) =
calculate_allocation_generic::<K, V>(self.capacity(), self.is_leaf());
- heap::deallocate(self.keys.ptr as *mut u8, size, alignment);
+ heap::deallocate(*self.keys as *mut u8, size, alignment);
}
#[inline]
pub fn as_slices<'a>(&'a self) -> (&'a [K], &'a [V]) {
unsafe {(
mem::transmute(raw::Slice {
- data: self.keys.ptr,
+ data: *self.keys as *const K,
len: self.len()
}),
mem::transmute(raw::Slice {
- data: self.vals.ptr,
+ data: *self.vals as *const V,
len: self.len()
})
)}
&[]
} else {
unsafe {
+ let data = match self.edges {
+ None => heap::EMPTY as *const Node<K,V>,
+ Some(ref p) => **p as *const Node<K,V>,
+ };
mem::transmute(raw::Slice {
- data: self.edges.ptr,
+ data: data,
len: self.len() + 1
})
}
#[derive(Copy)]
pub struct Handle<NodeRef, Type, NodeType> {
node: NodeRef,
- index: usize
+ index: usize,
+ marker: PhantomData<(Type, NodeType)>,
}
pub mod handle {
/// `Found` will be yielded with the matching index. If it doesn't find an exact match,
/// `GoDown` will be yielded with the index of the subtree the key must lie in.
pub fn search<Q: ?Sized, NodeRef: Deref<Target=Node<K, V>>>(node: NodeRef, key: &Q)
- -> SearchResult<NodeRef> where Q: BorrowFrom<K> + Ord {
+ -> SearchResult<NodeRef> where K: Borrow<Q>, Q: Ord {
// FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V).
// For the B configured as of this writing (B = 6), binary search was *significantly*
// worse for usizes.
match node.as_slices_internal().search_linear(key) {
- (index, true) => Found(Handle { node: node, index: index }),
- (index, false) => GoDown(Handle { node: node, index: index }),
+ (index, true) => Found(Handle { node: node, index: index, marker: PhantomData }),
+ (index, false) => GoDown(Handle { node: node, index: index, marker: PhantomData }),
}
}
}
/// If the node has any children
pub fn is_leaf(&self) -> bool {
- self.edges.ptr.is_null()
+ self.edges.is_none()
}
/// if the node has too few elements
pub fn as_raw(&mut self) -> Handle<*mut Node<K, V>, Type, NodeType> {
Handle {
node: &mut *self.node as *mut _,
- index: self.index
+ index: self.index,
+ marker: PhantomData,
}
}
}
pub unsafe fn from_raw<'a>(&'a self) -> Handle<&'a Node<K, V>, Type, NodeType> {
Handle {
node: &*self.node,
- index: self.index
+ index: self.index,
+ marker: PhantomData,
}
}
pub unsafe fn from_raw_mut<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, Type, NodeType> {
Handle {
node: &mut *self.node,
- index: self.index
+ index: self.index,
+ marker: PhantomData,
}
}
}
if self.node.is_leaf() {
Leaf(Handle {
node: self.node,
- index: self.index
+ index: self.index,
+ marker: PhantomData,
})
} else {
Internal(Handle {
node: self.node,
- index: self.index
+ index: self.index,
+ marker: PhantomData,
})
}
}
unsafe fn left_kv<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::KV, NodeType> {
Handle {
node: &mut *self.node,
- index: self.index - 1
+ index: self.index - 1,
+ marker: PhantomData,
}
}
unsafe fn right_kv<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::KV, NodeType> {
Handle {
node: &mut *self.node,
- index: self.index
+ index: self.index,
+ marker: PhantomData,
}
}
}
pub fn into_left_edge(self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> {
Handle {
node: &mut *self.node,
- index: self.index
+ index: self.index,
+ marker: PhantomData,
}
}
}
pub fn left_edge<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> {
Handle {
node: &mut *self.node,
- index: self.index
+ index: self.index,
+ marker: PhantomData,
}
}
pub fn right_edge<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> {
Handle {
node: &mut *self.node,
- index: self.index + 1
+ index: self.index + 1,
+ marker: PhantomData,
}
}
}
debug_assert!(index < self.len(), "kv_handle index out of bounds");
Handle {
node: self,
- index: index
+ index: index,
+ marker: PhantomData,
}
}
vals: RawItems::from_slice(self.vals()),
edges: RawItems::from_slice(self.edges()),
- ptr: self.keys.ptr as *mut u8,
+ ptr: *self.keys as *mut u8,
capacity: self.capacity(),
is_leaf: self.is_leaf()
},
impl<'a, K: Ord + 'a, V: 'a> $NodeSlice<'a, K, V> {
/// Performs linear search in a slice. Returns a tuple of (index, is_exact_match).
fn search_linear<Q: ?Sized>(&self, key: &Q) -> (usize, bool)
- where Q: BorrowFrom<K> + Ord {
+ where K: Borrow<Q>, Q: Ord {
for (i, k) in self.keys.iter().enumerate() {
- match key.cmp(BorrowFrom::borrow_from(k)) {
+ match key.cmp(k.borrow()) {
Greater => {},
Equal => return (i, true),
Less => return (i, false),
use core::prelude::*;
-use core::borrow::BorrowFrom;
use core::cmp::Ordering::{self, Less, Greater, Equal};
use core::default::Default;
use core::fmt::Debug;
use core::iter::{Peekable, Map, FromIterator, IntoIterator};
use core::ops::{BitOr, BitAnd, BitXor, Sub};
+use borrow::Borrow;
use btree_map::{BTreeMap, Keys};
use Bound;
/// assert_eq!(set.contains(&4), false);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
+ pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool where T: Borrow<Q>, Q: Ord {
self.map.contains_key(value)
}
/// assert_eq!(set.remove(&2), false);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
+ pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool where T: Borrow<Q>, Q: Ord {
self.map.remove(value).is_some()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> FromIterator<T> for BTreeSet<T> {
- fn from_iter<Iter: Iterator<Item=T>>(iter: Iter) -> BTreeSet<T> {
+ fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> BTreeSet<T> {
let mut set = BTreeSet::new();
set.extend(iter);
set
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> Extend<T> for BTreeSet<T> {
#[inline]
- fn extend<Iter: Iterator<Item=T>>(&mut self, iter: Iter) {
+ fn extend<Iter: IntoIterator<Item=T>>(&mut self, iter: Iter) {
for elem in iter {
self.insert(elem);
}
+++ /dev/null
-// Copyright 2012-2015 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 doubly-linked list with owned nodes.
-//!
-//! The `DList` allows pushing and popping elements at either end and is thus
-//! efficiently usable as a double-ended queue.
-
-// DList is constructed like a singly-linked list over the field `next`.
-// including the last link being None; each Node owns its `next` field.
-//
-// Backlinks over DList::prev are raw pointers that form a full chain in
-// the reverse direction.
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-use core::prelude::*;
-
-use alloc::boxed::Box;
-use core::cmp::Ordering;
-use core::default::Default;
-use core::fmt;
-use core::hash::{Writer, Hasher, Hash};
-use core::iter::{self, FromIterator, IntoIterator};
-use core::mem;
-use core::ptr;
-
-/// A doubly-linked list.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct DList<T> {
- length: usize,
- list_head: Link<T>,
- list_tail: Rawlink<Node<T>>,
-}
-
-type Link<T> = Option<Box<Node<T>>>;
-
-struct Rawlink<T> {
- p: *mut T,
-}
-
-impl<T> Copy for Rawlink<T> {}
-unsafe impl<T:'static+Send> Send for Rawlink<T> {}
-unsafe impl<T:Send+Sync> Sync for Rawlink<T> {}
-
-struct Node<T> {
- next: Link<T>,
- prev: Rawlink<Node<T>>,
- value: T,
-}
-
-/// An iterator over references to the items of a `DList`.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Iter<'a, T:'a> {
- head: &'a Link<T>,
- tail: Rawlink<Node<T>>,
- nelem: usize,
-}
-
-// FIXME #19839: deriving is too aggressive on the bounds (T doesn't need to be Clone).
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Clone for Iter<'a, T> {
- fn clone(&self) -> Iter<'a, T> {
- Iter {
- head: self.head.clone(),
- tail: self.tail,
- nelem: self.nelem,
- }
- }
-}
-
-/// An iterator over mutable references to the items of a `DList`.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct IterMut<'a, T:'a> {
- list: &'a mut DList<T>,
- head: Rawlink<Node<T>>,
- tail: Rawlink<Node<T>>,
- nelem: usize,
-}
-
-/// An iterator over mutable references to the items of a `DList`.
-#[derive(Clone)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct IntoIter<T> {
- list: DList<T>
-}
-
-/// Rawlink is a type like Option<T> but for holding a raw pointer
-impl<T> Rawlink<T> {
- /// Like Option::None for Rawlink
- fn none() -> Rawlink<T> {
- Rawlink{p: ptr::null_mut()}
- }
-
- /// Like Option::Some for Rawlink
- fn some(n: &mut T) -> Rawlink<T> {
- Rawlink{p: n}
- }
-
- /// Convert the `Rawlink` into an Option value
- fn resolve_immut<'a>(&self) -> Option<&'a T> {
- unsafe {
- mem::transmute(self.p.as_ref())
- }
- }
-
- /// Convert the `Rawlink` into an Option value
- fn resolve<'a>(&mut self) -> Option<&'a mut T> {
- if self.p.is_null() {
- None
- } else {
- Some(unsafe { mem::transmute(self.p) })
- }
- }
-
- /// Return the `Rawlink` and replace with `Rawlink::none()`
- fn take(&mut self) -> Rawlink<T> {
- mem::replace(self, Rawlink::none())
- }
-}
-
-impl<T> Clone for Rawlink<T> {
- #[inline]
- fn clone(&self) -> Rawlink<T> {
- Rawlink{p: self.p}
- }
-}
-
-impl<T> Node<T> {
- fn new(v: T) -> Node<T> {
- Node{value: v, next: None, prev: Rawlink::none()}
- }
-}
-
-/// Set the .prev field on `next`, then return `Some(next)`
-fn link_with_prev<T>(mut next: Box<Node<T>>, prev: Rawlink<Node<T>>)
- -> Link<T> {
- next.prev = prev;
- Some(next)
-}
-
-// private methods
-impl<T> DList<T> {
- /// Add a Node first in the list
- #[inline]
- fn push_front_node(&mut self, mut new_head: Box<Node<T>>) {
- match self.list_head {
- None => {
- self.list_tail = Rawlink::some(&mut *new_head);
- self.list_head = link_with_prev(new_head, Rawlink::none());
- }
- Some(ref mut head) => {
- new_head.prev = Rawlink::none();
- head.prev = Rawlink::some(&mut *new_head);
- mem::swap(head, &mut new_head);
- head.next = Some(new_head);
- }
- }
- self.length += 1;
- }
-
- /// Remove the first Node and return it, or None if the list is empty
- #[inline]
- fn pop_front_node(&mut self) -> Option<Box<Node<T>>> {
- self.list_head.take().map(|mut front_node| {
- self.length -= 1;
- match front_node.next.take() {
- Some(node) => self.list_head = link_with_prev(node, Rawlink::none()),
- None => self.list_tail = Rawlink::none()
- }
- front_node
- })
- }
-
- /// Add a Node last in the list
- #[inline]
- fn push_back_node(&mut self, mut new_tail: Box<Node<T>>) {
- match self.list_tail.resolve() {
- None => return self.push_front_node(new_tail),
- Some(tail) => {
- self.list_tail = Rawlink::some(&mut *new_tail);
- tail.next = link_with_prev(new_tail, Rawlink::some(tail));
- }
- }
- self.length += 1;
- }
-
- /// Remove the last Node and return it, or None if the list is empty
- #[inline]
- fn pop_back_node(&mut self) -> Option<Box<Node<T>>> {
- self.list_tail.resolve().map_or(None, |tail| {
- self.length -= 1;
- self.list_tail = tail.prev;
- match tail.prev.resolve() {
- None => self.list_head.take(),
- Some(tail_prev) => tail_prev.next.take()
- }
- })
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Default for DList<T> {
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- fn default() -> DList<T> { DList::new() }
-}
-
-impl<T> DList<T> {
- /// Creates an empty `DList`.
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn new() -> DList<T> {
- DList{list_head: None, list_tail: Rawlink::none(), length: 0}
- }
-
- /// Moves all elements from `other` to the end of the list.
- ///
- /// This reuses all the nodes from `other` and moves them into `self`. After
- /// this operation, `other` becomes empty.
- ///
- /// This operation should compute in O(1) time and O(1) memory.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut a = DList::new();
- /// let mut b = DList::new();
- /// a.push_back(1);
- /// a.push_back(2);
- /// b.push_back(3);
- /// b.push_back(4);
- ///
- /// a.append(&mut b);
- ///
- /// for e in a.iter() {
- /// println!("{}", e); // prints 1, then 2, then 3, then 4
- /// }
- /// println!("{}", b.len()); // prints 0
- /// ```
- pub fn append(&mut self, other: &mut DList<T>) {
- match self.list_tail.resolve() {
- None => {
- self.length = other.length;
- self.list_head = other.list_head.take();
- self.list_tail = other.list_tail.take();
- },
- Some(tail) => {
- // Carefully empty `other`.
- let o_tail = other.list_tail.take();
- let o_length = other.length;
- match other.list_head.take() {
- None => return,
- Some(node) => {
- tail.next = link_with_prev(node, self.list_tail);
- self.list_tail = o_tail;
- self.length += o_length;
- }
- }
- }
- }
- other.length = 0;
- }
-
- /// Provides a forward iterator.
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn iter(&self) -> Iter<T> {
- Iter{nelem: self.len(), head: &self.list_head, tail: self.list_tail}
- }
-
- /// Provides a forward iterator with mutable references.
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn iter_mut(&mut self) -> IterMut<T> {
- let head_raw = match self.list_head {
- Some(ref mut h) => Rawlink::some(&mut **h),
- None => Rawlink::none(),
- };
- IterMut{
- nelem: self.len(),
- head: head_raw,
- tail: self.list_tail,
- list: self
- }
- }
-
- /// Consumes the list into an iterator yielding elements by value.
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn into_iter(self) -> IntoIter<T> {
- IntoIter{list: self}
- }
-
- /// Returns `true` if the `DList` is empty.
- ///
- /// This operation should compute in O(1) time.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut dl = DList::new();
- /// assert!(dl.is_empty());
- ///
- /// dl.push_front("foo");
- /// assert!(!dl.is_empty());
- /// ```
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn is_empty(&self) -> bool {
- self.list_head.is_none()
- }
-
- /// Returns the length of the `DList`.
- ///
- /// This operation should compute in O(1) time.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut dl = DList::new();
- ///
- /// dl.push_front(2);
- /// assert_eq!(dl.len(), 1);
- ///
- /// dl.push_front(1);
- /// assert_eq!(dl.len(), 2);
- ///
- /// dl.push_back(3);
- /// assert_eq!(dl.len(), 3);
- ///
- /// ```
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn len(&self) -> usize {
- self.length
- }
-
- /// Removes all elements from the `DList`.
- ///
- /// This operation should compute in O(n) time.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut dl = DList::new();
- ///
- /// dl.push_front(2);
- /// dl.push_front(1);
- /// assert_eq!(dl.len(), 2);
- /// assert_eq!(dl.front(), Some(&1));
- ///
- /// dl.clear();
- /// assert_eq!(dl.len(), 0);
- /// assert_eq!(dl.front(), None);
- ///
- /// ```
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn clear(&mut self) {
- *self = DList::new()
- }
-
- /// Provides a reference to the front element, or `None` if the list is
- /// empty.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut dl = DList::new();
- /// assert_eq!(dl.front(), None);
- ///
- /// dl.push_front(1);
- /// assert_eq!(dl.front(), Some(&1));
- ///
- /// ```
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn front(&self) -> Option<&T> {
- self.list_head.as_ref().map(|head| &head.value)
- }
-
- /// Provides a mutable reference to the front element, or `None` if the list
- /// is empty.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut dl = DList::new();
- /// assert_eq!(dl.front(), None);
- ///
- /// dl.push_front(1);
- /// assert_eq!(dl.front(), Some(&1));
- ///
- /// match dl.front_mut() {
- /// None => {},
- /// Some(x) => *x = 5,
- /// }
- /// assert_eq!(dl.front(), Some(&5));
- ///
- /// ```
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn front_mut(&mut self) -> Option<&mut T> {
- self.list_head.as_mut().map(|head| &mut head.value)
- }
-
- /// Provides a reference to the back element, or `None` if the list is
- /// empty.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut dl = DList::new();
- /// assert_eq!(dl.back(), None);
- ///
- /// dl.push_back(1);
- /// assert_eq!(dl.back(), Some(&1));
- ///
- /// ```
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn back(&self) -> Option<&T> {
- self.list_tail.resolve_immut().as_ref().map(|tail| &tail.value)
- }
-
- /// Provides a mutable reference to the back element, or `None` if the list
- /// is empty.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut dl = DList::new();
- /// assert_eq!(dl.back(), None);
- ///
- /// dl.push_back(1);
- /// assert_eq!(dl.back(), Some(&1));
- ///
- /// match dl.back_mut() {
- /// None => {},
- /// Some(x) => *x = 5,
- /// }
- /// assert_eq!(dl.back(), Some(&5));
- ///
- /// ```
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn back_mut(&mut self) -> Option<&mut T> {
- self.list_tail.resolve().map(|tail| &mut tail.value)
- }
-
- /// Adds an element first in the list.
- ///
- /// This operation should compute in O(1) time.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut dl = DList::new();
- ///
- /// dl.push_front(2);
- /// assert_eq!(dl.front().unwrap(), &2);
- ///
- /// dl.push_front(1);
- /// assert_eq!(dl.front().unwrap(), &1);
- ///
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn push_front(&mut self, elt: T) {
- self.push_front_node(box Node::new(elt))
- }
-
- /// Removes the first element and returns it, or `None` if the list is
- /// empty.
- ///
- /// This operation should compute in O(1) time.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut d = DList::new();
- /// assert_eq!(d.pop_front(), None);
- ///
- /// d.push_front(1);
- /// d.push_front(3);
- /// assert_eq!(d.pop_front(), Some(3));
- /// assert_eq!(d.pop_front(), Some(1));
- /// assert_eq!(d.pop_front(), None);
- ///
- /// ```
- ///
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn pop_front(&mut self) -> Option<T> {
- self.pop_front_node().map(|box Node{value, ..}| value)
- }
-
- /// Appends an element to the back of a list
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut d = DList::new();
- /// d.push_back(1);
- /// d.push_back(3);
- /// assert_eq!(3, *d.back().unwrap());
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn push_back(&mut self, elt: T) {
- self.push_back_node(box Node::new(elt))
- }
-
- /// Removes the last element from a list and returns it, or `None` if
- /// it is empty.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut d = DList::new();
- /// assert_eq!(d.pop_back(), None);
- /// d.push_back(1);
- /// d.push_back(3);
- /// assert_eq!(d.pop_back(), Some(3));
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn pop_back(&mut self) -> Option<T> {
- self.pop_back_node().map(|box Node{value, ..}| value)
- }
-
- /// Splits the list into two at the given index. Returns everything after the given index,
- /// including the index.
- ///
- /// # Panics
- ///
- /// Panics if `at > len`.
- ///
- /// This operation should compute in O(n) time.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut d = DList::new();
- ///
- /// d.push_front(1);
- /// d.push_front(2);
- /// d.push_front(3);
- ///
- /// let mut splitted = d.split_off(2);
- ///
- /// assert_eq!(splitted.pop_front(), Some(1));
- /// assert_eq!(splitted.pop_front(), None);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn split_off(&mut self, at: usize) -> DList<T> {
- let len = self.len();
- assert!(at <= len, "Cannot split off at a nonexistent index");
- if at == 0 {
- return mem::replace(self, DList::new());
- } else if at == len {
- return DList::new();
- }
-
- // Below, we iterate towards the `i-1`th node, either from the start or the end,
- // depending on which would be faster.
- let mut split_node = if at - 1 <= len - 1 - (at - 1) {
- let mut iter = self.iter_mut();
- // instead of skipping using .skip() (which creates a new struct),
- // we skip manually so we can access the head field without
- // depending on implementation details of Skip
- for _ in 0..at - 1 {
- iter.next();
- }
- iter.head
- } else {
- // better off starting from the end
- let mut iter = self.iter_mut();
- for _ in 0..len - 1 - (at - 1) {
- iter.next_back();
- }
- iter.tail
- };
-
- let mut splitted_list = DList {
- list_head: None,
- list_tail: self.list_tail,
- length: len - at
- };
-
- mem::swap(&mut split_node.resolve().unwrap().next, &mut splitted_list.list_head);
- self.list_tail = split_node;
- self.length = at;
-
- splitted_list
- }
-}
-
-#[unsafe_destructor]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Drop for DList<T> {
- fn drop(&mut self) {
- // Dissolve the dlist in backwards direction
- // Just dropping the list_head can lead to stack exhaustion
- // when length is >> 1_000_000
- let mut tail = self.list_tail;
- loop {
- match tail.resolve() {
- None => break,
- Some(prev) => {
- prev.next.take(); // release Box<Node<T>>
- tail = prev.prev;
- }
- }
- }
- self.length = 0;
- self.list_head = None;
- self.list_tail = Rawlink::none();
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, A> Iterator for Iter<'a, A> {
- type Item = &'a A;
-
- #[inline]
- fn next(&mut self) -> Option<&'a A> {
- if self.nelem == 0 {
- return None;
- }
- self.head.as_ref().map(|head| {
- self.nelem -= 1;
- self.head = &head.next;
- &head.value
- })
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.nelem, Some(self.nelem))
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, A> DoubleEndedIterator for Iter<'a, A> {
- #[inline]
- fn next_back(&mut self) -> Option<&'a A> {
- if self.nelem == 0 {
- return None;
- }
- self.tail.resolve_immut().as_ref().map(|prev| {
- self.nelem -= 1;
- self.tail = prev.prev;
- &prev.value
- })
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, A> ExactSizeIterator for Iter<'a, A> {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, A> Iterator for IterMut<'a, A> {
- type Item = &'a mut A;
- #[inline]
- fn next(&mut self) -> Option<&'a mut A> {
- if self.nelem == 0 {
- return None;
- }
- self.head.resolve().map(|next| {
- self.nelem -= 1;
- self.head = match next.next {
- Some(ref mut node) => Rawlink::some(&mut **node),
- None => Rawlink::none(),
- };
- &mut next.value
- })
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.nelem, Some(self.nelem))
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
- #[inline]
- fn next_back(&mut self) -> Option<&'a mut A> {
- if self.nelem == 0 {
- return None;
- }
- self.tail.resolve().map(|prev| {
- self.nelem -= 1;
- self.tail = prev.prev;
- &mut prev.value
- })
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, A> ExactSizeIterator for IterMut<'a, A> {}
-
-// private methods for IterMut
-impl<'a, A> IterMut<'a, A> {
- fn insert_next_node(&mut self, mut ins_node: Box<Node<A>>) {
- // Insert before `self.head` so that it is between the
- // previously yielded element and self.head.
- //
- // The inserted node will not appear in further iteration.
- match self.head.resolve() {
- None => { self.list.push_back_node(ins_node); }
- Some(node) => {
- let prev_node = match node.prev.resolve() {
- None => return self.list.push_front_node(ins_node),
- Some(prev) => prev,
- };
- let node_own = prev_node.next.take().unwrap();
- ins_node.next = link_with_prev(node_own, Rawlink::some(&mut *ins_node));
- prev_node.next = link_with_prev(ins_node, Rawlink::some(prev_node));
- self.list.length += 1;
- }
- }
- }
-}
-
-impl<'a, A> IterMut<'a, A> {
- /// Inserts `elt` just after the element most recently returned by `.next()`.
- /// The inserted element does not appear in the iteration.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut list: DList<_> = vec![1, 3, 4].into_iter().collect();
- ///
- /// {
- /// let mut it = list.iter_mut();
- /// assert_eq!(it.next().unwrap(), &1);
- /// // insert `2` after `1`
- /// it.insert_next(2);
- /// }
- /// {
- /// let vec: Vec<_> = list.into_iter().collect();
- /// assert_eq!(vec, vec![1, 2, 3, 4]);
- /// }
- /// ```
- #[inline]
- #[unstable(feature = "collections",
- reason = "this is probably better handled by a cursor type -- we'll see")]
- pub fn insert_next(&mut self, elt: A) {
- self.insert_next_node(box Node::new(elt))
- }
-
- /// Provides a reference to the next element, without changing the iterator.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::DList;
- ///
- /// let mut list: DList<_> = vec![1, 2, 3].into_iter().collect();
- ///
- /// let mut it = list.iter_mut();
- /// assert_eq!(it.next().unwrap(), &1);
- /// assert_eq!(it.peek_next().unwrap(), &2);
- /// // We just peeked at 2, so it was not consumed from the iterator.
- /// assert_eq!(it.next().unwrap(), &2);
- /// ```
- #[inline]
- #[unstable(feature = "collections",
- reason = "this is probably better handled by a cursor type -- we'll see")]
- pub fn peek_next(&mut self) -> Option<&mut A> {
- if self.nelem == 0 {
- return None
- }
- self.head.resolve().map(|head| &mut head.value)
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A> Iterator for IntoIter<A> {
- type Item = A;
-
- #[inline]
- fn next(&mut self) -> Option<A> { self.list.pop_front() }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- (self.list.length, Some(self.list.length))
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A> DoubleEndedIterator for IntoIter<A> {
- #[inline]
- fn next_back(&mut self) -> Option<A> { self.list.pop_back() }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A> FromIterator<A> for DList<A> {
- fn from_iter<T: Iterator<Item=A>>(iterator: T) -> DList<A> {
- let mut ret = DList::new();
- ret.extend(iterator);
- ret
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> IntoIterator for DList<T> {
- type Item = T;
- type IntoIter = IntoIter<T>;
-
- fn into_iter(self) -> IntoIter<T> {
- self.into_iter()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> IntoIterator for &'a DList<T> {
- type Item = &'a T;
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Iter<'a, T> {
- self.iter()
- }
-}
-
-impl<'a, T> IntoIterator for &'a mut DList<T> {
- type Item = &'a mut T;
- type IntoIter = IterMut<'a, T>;
-
- fn into_iter(mut self) -> IterMut<'a, T> {
- self.iter_mut()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A> Extend<A> for DList<A> {
- fn extend<T: Iterator<Item=A>>(&mut self, iterator: T) {
- for elt in iterator { self.push_back(elt); }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A: PartialEq> PartialEq for DList<A> {
- fn eq(&self, other: &DList<A>) -> bool {
- self.len() == other.len() &&
- iter::order::eq(self.iter(), other.iter())
- }
-
- fn ne(&self, other: &DList<A>) -> bool {
- self.len() != other.len() ||
- iter::order::ne(self.iter(), other.iter())
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Eq> Eq for DList<A> {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A: PartialOrd> PartialOrd for DList<A> {
- fn partial_cmp(&self, other: &DList<A>) -> Option<Ordering> {
- iter::order::partial_cmp(self.iter(), other.iter())
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Ord> Ord for DList<A> {
- #[inline]
- fn cmp(&self, other: &DList<A>) -> Ordering {
- iter::order::cmp(self.iter(), other.iter())
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Clone> Clone for DList<A> {
- fn clone(&self) -> DList<A> {
- self.iter().map(|x| x.clone()).collect()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A: fmt::Debug> fmt::Debug for DList<A> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- try!(write!(f, "DList ["));
-
- for (i, e) in self.iter().enumerate() {
- if i != 0 { try!(write!(f, ", ")); }
- try!(write!(f, "{:?}", *e));
- }
-
- write!(f, "]")
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for DList<A> {
- fn hash(&self, state: &mut S) {
- self.len().hash(state);
- for elt in self {
- elt.hash(state);
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use prelude::*;
- use std::rand;
- use std::hash::{self, SipHasher};
- use std::thread;
- use test::Bencher;
- use test;
-
- use super::{DList, Node};
-
- pub fn check_links<T>(list: &DList<T>) {
- let mut len = 0;
- let mut last_ptr: Option<&Node<T>> = None;
- let mut node_ptr: &Node<T>;
- match list.list_head {
- None => { assert_eq!(0, list.length); return }
- Some(ref node) => node_ptr = &**node,
- }
- loop {
- match (last_ptr, node_ptr.prev.resolve_immut()) {
- (None , None ) => {}
- (None , _ ) => panic!("prev link for list_head"),
- (Some(p), Some(pptr)) => {
- assert_eq!(p as *const Node<T>, pptr as *const Node<T>);
- }
- _ => panic!("prev link is none, not good"),
- }
- match node_ptr.next {
- Some(ref next) => {
- last_ptr = Some(node_ptr);
- node_ptr = &**next;
- len += 1;
- }
- None => {
- len += 1;
- break;
- }
- }
- }
- assert_eq!(len, list.length);
- }
-
- #[test]
- fn test_basic() {
- let mut m = DList::new();
- assert_eq!(m.pop_front(), None);
- assert_eq!(m.pop_back(), None);
- assert_eq!(m.pop_front(), None);
- m.push_front(box 1);
- assert_eq!(m.pop_front(), Some(box 1));
- m.push_back(box 2);
- m.push_back(box 3);
- assert_eq!(m.len(), 2);
- assert_eq!(m.pop_front(), Some(box 2));
- assert_eq!(m.pop_front(), Some(box 3));
- assert_eq!(m.len(), 0);
- assert_eq!(m.pop_front(), None);
- m.push_back(box 1);
- m.push_back(box 3);
- m.push_back(box 5);
- m.push_back(box 7);
- assert_eq!(m.pop_front(), Some(box 1));
-
- let mut n = DList::new();
- n.push_front(2);
- n.push_front(3);
- {
- assert_eq!(n.front().unwrap(), &3);
- let x = n.front_mut().unwrap();
- assert_eq!(*x, 3);
- *x = 0;
- }
- {
- assert_eq!(n.back().unwrap(), &2);
- let y = n.back_mut().unwrap();
- assert_eq!(*y, 2);
- *y = 1;
- }
- assert_eq!(n.pop_front(), Some(0));
- assert_eq!(n.pop_front(), Some(1));
- }
-
- #[cfg(test)]
- fn generate_test() -> DList<i32> {
- list_from(&[0,1,2,3,4,5,6])
- }
-
- #[cfg(test)]
- fn list_from<T: Clone>(v: &[T]) -> DList<T> {
- v.iter().map(|x| (*x).clone()).collect()
- }
-
- #[test]
- fn test_append() {
- // Empty to empty
- {
- let mut m = DList::<i32>::new();
- let mut n = DList::new();
- m.append(&mut n);
- check_links(&m);
- assert_eq!(m.len(), 0);
- assert_eq!(n.len(), 0);
- }
- // Non-empty to empty
- {
- let mut m = DList::new();
- let mut n = DList::new();
- n.push_back(2);
- m.append(&mut n);
- check_links(&m);
- assert_eq!(m.len(), 1);
- assert_eq!(m.pop_back(), Some(2));
- assert_eq!(n.len(), 0);
- check_links(&m);
- }
- // Empty to non-empty
- {
- let mut m = DList::new();
- let mut n = DList::new();
- m.push_back(2);
- m.append(&mut n);
- check_links(&m);
- assert_eq!(m.len(), 1);
- assert_eq!(m.pop_back(), Some(2));
- check_links(&m);
- }
-
- // Non-empty to non-empty
- let v = vec![1,2,3,4,5];
- let u = vec![9,8,1,2,3,4,5];
- let mut m = list_from(&v);
- let mut n = list_from(&u);
- m.append(&mut n);
- check_links(&m);
- let mut sum = v;
- sum.push_all(&u);
- assert_eq!(sum.len(), m.len());
- for elt in sum {
- assert_eq!(m.pop_front(), Some(elt))
- }
- assert_eq!(n.len(), 0);
- // let's make sure it's working properly, since we
- // did some direct changes to private members
- n.push_back(3);
- assert_eq!(n.len(), 1);
- assert_eq!(n.pop_front(), Some(3));
- check_links(&n);
- }
-
- #[test]
- fn test_split_off() {
- // singleton
- {
- let mut m = DList::new();
- m.push_back(1);
-
- let p = m.split_off(0);
- assert_eq!(m.len(), 0);
- assert_eq!(p.len(), 1);
- assert_eq!(p.back(), Some(&1));
- assert_eq!(p.front(), Some(&1));
- }
-
- // not singleton, forwards
- {
- let u = vec![1,2,3,4,5];
- let mut m = list_from(&u);
- let mut n = m.split_off(2);
- assert_eq!(m.len(), 2);
- assert_eq!(n.len(), 3);
- for elt in 1..3 {
- assert_eq!(m.pop_front(), Some(elt));
- }
- for elt in 3..6 {
- assert_eq!(n.pop_front(), Some(elt));
- }
- }
- // not singleton, backwards
- {
- let u = vec![1,2,3,4,5];
- let mut m = list_from(&u);
- let mut n = m.split_off(4);
- assert_eq!(m.len(), 4);
- assert_eq!(n.len(), 1);
- for elt in 1..5 {
- assert_eq!(m.pop_front(), Some(elt));
- }
- for elt in 5..6 {
- assert_eq!(n.pop_front(), Some(elt));
- }
- }
-
- // no-op on the last index
- {
- let mut m = DList::new();
- m.push_back(1);
-
- let p = m.split_off(1);
- assert_eq!(m.len(), 1);
- assert_eq!(p.len(), 0);
- assert_eq!(m.back(), Some(&1));
- assert_eq!(m.front(), Some(&1));
- }
-
- }
-
- #[test]
- fn test_iterator() {
- let m = generate_test();
- for (i, elt) in m.iter().enumerate() {
- assert_eq!(i as i32, *elt);
- }
- let mut n = DList::new();
- assert_eq!(n.iter().next(), None);
- n.push_front(4);
- let mut it = n.iter();
- assert_eq!(it.size_hint(), (1, Some(1)));
- assert_eq!(it.next().unwrap(), &4);
- assert_eq!(it.size_hint(), (0, Some(0)));
- assert_eq!(it.next(), None);
- }
-
- #[test]
- fn test_iterator_clone() {
- let mut n = DList::new();
- n.push_back(2);
- n.push_back(3);
- n.push_back(4);
- let mut it = n.iter();
- it.next();
- let mut jt = it.clone();
- assert_eq!(it.next(), jt.next());
- assert_eq!(it.next_back(), jt.next_back());
- assert_eq!(it.next(), jt.next());
- }
-
- #[test]
- fn test_iterator_double_end() {
- let mut n = DList::new();
- assert_eq!(n.iter().next(), None);
- n.push_front(4);
- n.push_front(5);
- n.push_front(6);
- let mut it = n.iter();
- assert_eq!(it.size_hint(), (3, Some(3)));
- assert_eq!(it.next().unwrap(), &6);
- assert_eq!(it.size_hint(), (2, Some(2)));
- assert_eq!(it.next_back().unwrap(), &4);
- assert_eq!(it.size_hint(), (1, Some(1)));
- assert_eq!(it.next_back().unwrap(), &5);
- assert_eq!(it.next_back(), None);
- assert_eq!(it.next(), None);
- }
-
- #[test]
- fn test_rev_iter() {
- let m = generate_test();
- for (i, elt) in m.iter().rev().enumerate() {
- assert_eq!((6 - i) as i32, *elt);
- }
- let mut n = DList::new();
- assert_eq!(n.iter().rev().next(), None);
- n.push_front(4);
- let mut it = n.iter().rev();
- assert_eq!(it.size_hint(), (1, Some(1)));
- assert_eq!(it.next().unwrap(), &4);
- assert_eq!(it.size_hint(), (0, Some(0)));
- assert_eq!(it.next(), None);
- }
-
- #[test]
- fn test_mut_iter() {
- let mut m = generate_test();
- let mut len = m.len();
- for (i, elt) in m.iter_mut().enumerate() {
- assert_eq!(i as i32, *elt);
- len -= 1;
- }
- assert_eq!(len, 0);
- let mut n = DList::new();
- assert!(n.iter_mut().next().is_none());
- n.push_front(4);
- n.push_back(5);
- let mut it = n.iter_mut();
- assert_eq!(it.size_hint(), (2, Some(2)));
- assert!(it.next().is_some());
- assert!(it.next().is_some());
- assert_eq!(it.size_hint(), (0, Some(0)));
- assert!(it.next().is_none());
- }
-
- #[test]
- fn test_iterator_mut_double_end() {
- let mut n = DList::new();
- assert!(n.iter_mut().next_back().is_none());
- n.push_front(4);
- n.push_front(5);
- n.push_front(6);
- let mut it = n.iter_mut();
- assert_eq!(it.size_hint(), (3, Some(3)));
- assert_eq!(*it.next().unwrap(), 6);
- assert_eq!(it.size_hint(), (2, Some(2)));
- assert_eq!(*it.next_back().unwrap(), 4);
- assert_eq!(it.size_hint(), (1, Some(1)));
- assert_eq!(*it.next_back().unwrap(), 5);
- assert!(it.next_back().is_none());
- assert!(it.next().is_none());
- }
-
- #[test]
- fn test_insert_prev() {
- let mut m = list_from(&[0,2,4,6,8]);
- let len = m.len();
- {
- let mut it = m.iter_mut();
- it.insert_next(-2);
- loop {
- match it.next() {
- None => break,
- Some(elt) => {
- it.insert_next(*elt + 1);
- match it.peek_next() {
- Some(x) => assert_eq!(*x, *elt + 2),
- None => assert_eq!(8, *elt),
- }
- }
- }
- }
- it.insert_next(0);
- it.insert_next(1);
- }
- check_links(&m);
- assert_eq!(m.len(), 3 + len * 2);
- assert_eq!(m.into_iter().collect::<Vec<_>>(), vec![-2,0,1,2,3,4,5,6,7,8,9,0,1]);
- }
-
- #[test]
- fn test_mut_rev_iter() {
- let mut m = generate_test();
- for (i, elt) in m.iter_mut().rev().enumerate() {
- assert_eq!((6 - i) as i32, *elt);
- }
- let mut n = DList::new();
- assert!(n.iter_mut().rev().next().is_none());
- n.push_front(4);
- let mut it = n.iter_mut().rev();
- assert!(it.next().is_some());
- assert!(it.next().is_none());
- }
-
- #[test]
- fn test_send() {
- let n = list_from(&[1,2,3]);
- thread::spawn(move || {
- check_links(&n);
- let a: &[_] = &[&1,&2,&3];
- assert_eq!(a, n.iter().collect::<Vec<_>>());
- }).join().ok().unwrap();
- }
-
- #[test]
- fn test_eq() {
- let mut n = list_from(&[]);
- let mut m = list_from(&[]);
- assert!(n == m);
- n.push_front(1);
- assert!(n != m);
- m.push_back(1);
- assert!(n == m);
-
- let n = list_from(&[2,3,4]);
- let m = list_from(&[1,2,3]);
- assert!(n != m);
- }
-
- #[test]
- fn test_hash() {
- let mut x = DList::new();
- let mut y = DList::new();
-
- assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y));
-
- x.push_back(1);
- x.push_back(2);
- x.push_back(3);
-
- y.push_front(3);
- y.push_front(2);
- y.push_front(1);
-
- assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y));
- }
-
- #[test]
- fn test_ord() {
- let n = list_from(&[]);
- let m = list_from(&[1,2,3]);
- assert!(n < m);
- assert!(m > n);
- assert!(n <= n);
- assert!(n >= n);
- }
-
- #[test]
- fn test_ord_nan() {
- let nan = 0.0f64/0.0;
- let n = list_from(&[nan]);
- let m = list_from(&[nan]);
- assert!(!(n < m));
- assert!(!(n > m));
- assert!(!(n <= m));
- assert!(!(n >= m));
-
- let n = list_from(&[nan]);
- let one = list_from(&[1.0f64]);
- assert!(!(n < one));
- assert!(!(n > one));
- assert!(!(n <= one));
- assert!(!(n >= one));
-
- let u = list_from(&[1.0f64,2.0,nan]);
- let v = list_from(&[1.0f64,2.0,3.0]);
- assert!(!(u < v));
- assert!(!(u > v));
- assert!(!(u <= v));
- assert!(!(u >= v));
-
- let s = list_from(&[1.0f64,2.0,4.0,2.0]);
- let t = list_from(&[1.0f64,2.0,3.0,2.0]);
- assert!(!(s < t));
- assert!(s > one);
- assert!(!(s <= one));
- assert!(s >= one);
- }
-
- #[test]
- fn test_fuzz() {
- for _ in 0..25 {
- fuzz_test(3);
- fuzz_test(16);
- fuzz_test(189);
- }
- }
-
- #[test]
- fn test_show() {
- let list: DList<_> = (0..10).collect();
- assert_eq!(format!("{:?}", list), "DList [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
-
- let list: DList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect();
- assert_eq!(format!("{:?}", list), "DList [\"just\", \"one\", \"test\", \"more\"]");
- }
-
- #[cfg(test)]
- fn fuzz_test(sz: i32) {
- let mut m: DList<_> = DList::new();
- let mut v = vec![];
- for i in 0..sz {
- check_links(&m);
- let r: u8 = rand::random();
- match r % 6 {
- 0 => {
- m.pop_back();
- v.pop();
- }
- 1 => {
- if !v.is_empty() {
- m.pop_front();
- v.remove(0);
- }
- }
- 2 | 4 => {
- m.push_front(-i);
- v.insert(0, -i);
- }
- 3 | 5 | _ => {
- m.push_back(i);
- v.push(i);
- }
- }
- }
-
- check_links(&m);
-
- let mut i = 0;
- for (a, &b) in m.into_iter().zip(v.iter()) {
- i += 1;
- assert_eq!(a, b);
- }
- assert_eq!(i, v.len());
- }
-
- #[bench]
- fn bench_collect_into(b: &mut test::Bencher) {
- let v = &[0; 64];
- b.iter(|| {
- let _: DList<_> = v.iter().cloned().collect();
- })
- }
-
- #[bench]
- fn bench_push_front(b: &mut test::Bencher) {
- let mut m: DList<_> = DList::new();
- b.iter(|| {
- m.push_front(0);
- })
- }
-
- #[bench]
- fn bench_push_back(b: &mut test::Bencher) {
- let mut m: DList<_> = DList::new();
- b.iter(|| {
- m.push_back(0);
- })
- }
-
- #[bench]
- fn bench_push_back_pop_back(b: &mut test::Bencher) {
- let mut m: DList<_> = DList::new();
- b.iter(|| {
- m.push_back(0);
- m.pop_back();
- })
- }
-
- #[bench]
- fn bench_push_front_pop_front(b: &mut test::Bencher) {
- let mut m: DList<_> = DList::new();
- b.iter(|| {
- m.push_front(0);
- m.pop_front();
- })
- }
-
- #[bench]
- fn bench_iter(b: &mut test::Bencher) {
- let v = &[0; 128];
- let m: DList<_> = v.iter().cloned().collect();
- b.iter(|| {
- assert!(m.iter().count() == 128);
- })
- }
- #[bench]
- fn bench_iter_mut(b: &mut test::Bencher) {
- let v = &[0; 128];
- let mut m: DList<_> = v.iter().cloned().collect();
- b.iter(|| {
- assert!(m.iter_mut().count() == 128);
- })
- }
- #[bench]
- fn bench_iter_rev(b: &mut test::Bencher) {
- let v = &[0; 128];
- let m: DList<_> = v.iter().cloned().collect();
- b.iter(|| {
- assert!(m.iter().rev().count() == 128);
- })
- }
- #[bench]
- fn bench_iter_mut_rev(b: &mut test::Bencher) {
- let v = &[0; 128];
- let mut m: DList<_> = v.iter().cloned().collect();
- b.iter(|| {
- assert!(m.iter_mut().rev().count() == 128);
- })
- }
-}
//! representation to hold C-like enum variants.
use core::prelude::*;
+use core::marker;
use core::fmt;
use core::num::Int;
use core::iter::{FromIterator, IntoIterator};
pub struct EnumSet<E> {
// We must maintain the invariant that no bits are set
// for which no variant exists
- bits: usize
+ bits: usize,
+ marker: marker::PhantomData<E>,
}
impl<E> Copy for EnumSet<E> {}
#[unstable(feature = "collections",
reason = "matches collection reform specification, waiting for dust to settle")]
pub fn new() -> EnumSet<E> {
- EnumSet {bits: 0}
+ EnumSet {bits: 0, marker: marker::PhantomData}
}
/// Returns the number of elements in the given `EnumSet`.
/// Returns the union of both `EnumSets`.
pub fn union(&self, e: EnumSet<E>) -> EnumSet<E> {
- EnumSet {bits: self.bits | e.bits}
+ EnumSet {bits: self.bits | e.bits,
+ marker: marker::PhantomData}
}
/// Returns the intersection of both `EnumSets`.
pub fn intersection(&self, e: EnumSet<E>) -> EnumSet<E> {
- EnumSet {bits: self.bits & e.bits}
+ EnumSet {bits: self.bits & e.bits,
+ marker: marker::PhantomData}
}
/// Adds an enum to the `EnumSet`, and returns `true` if it wasn't there before
type Output = EnumSet<E>;
fn sub(self, e: EnumSet<E>) -> EnumSet<E> {
- EnumSet {bits: self.bits & !e.bits}
+ EnumSet {bits: self.bits & !e.bits, marker: marker::PhantomData}
}
}
type Output = EnumSet<E>;
fn bitor(self, e: EnumSet<E>) -> EnumSet<E> {
- EnumSet {bits: self.bits | e.bits}
+ EnumSet {bits: self.bits | e.bits, marker: marker::PhantomData}
}
}
type Output = EnumSet<E>;
fn bitand(self, e: EnumSet<E>) -> EnumSet<E> {
- EnumSet {bits: self.bits & e.bits}
+ EnumSet {bits: self.bits & e.bits, marker: marker::PhantomData}
}
}
type Output = EnumSet<E>;
fn bitxor(self, e: EnumSet<E>) -> EnumSet<E> {
- EnumSet {bits: self.bits ^ e.bits}
+ EnumSet {bits: self.bits ^ e.bits, marker: marker::PhantomData}
}
}
pub struct Iter<E> {
index: usize,
bits: usize,
+ marker: marker::PhantomData<E>,
}
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
Iter {
index: self.index,
bits: self.bits,
+ marker: marker::PhantomData,
}
}
}
impl<E:CLike> Iter<E> {
fn new(bits: usize) -> Iter<E> {
- Iter { index: 0, bits: bits }
+ Iter { index: 0, bits: bits, marker: marker::PhantomData }
}
}
}
impl<E:CLike> FromIterator<E> for EnumSet<E> {
- fn from_iter<I:Iterator<Item=E>>(iterator: I) -> EnumSet<E> {
+ fn from_iter<I: IntoIterator<Item=E>>(iter: I) -> EnumSet<E> {
let mut ret = EnumSet::new();
- ret.extend(iterator);
+ ret.extend(iter);
ret
}
}
}
impl<E:CLike> Extend<E> for EnumSet<E> {
- fn extend<I: Iterator<Item=E>>(&mut self, iterator: I) {
- for element in iterator {
+ fn extend<I: IntoIterator<Item=E>>(&mut self, iter: I) {
+ for element in iter {
self.insert(element);
}
}
#![feature(box_syntax)]
#![feature(box_patterns)]
#![feature(core)]
-#![feature(hash)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#[cfg(test)] #[macro_use] extern crate log;
pub use binary_heap::BinaryHeap;
-pub use bitv::Bitv;
-pub use bitv_set::BitvSet;
+pub use bit_vec::BitVec;
+pub use bit_set::BitSet;
pub use btree_map::BTreeMap;
pub use btree_set::BTreeSet;
-pub use dlist::DList;
+pub use linked_list::LinkedList;
pub use enum_set::EnumSet;
-pub use ring_buf::RingBuf;
+pub use vec_deque::VecDeque;
pub use string::String;
pub use vec::Vec;
pub use vec_map::VecMap;
+#[deprecated(since = "1.0.0", reason = "renamed to vec_deque")]
+#[unstable(feature = "collections")]
+pub use vec_deque as ring_buf;
+
+#[deprecated(since = "1.0.0", reason = "renamed to linked_list")]
+#[unstable(feature = "collections")]
+pub use linked_list as dlist;
+
+#[deprecated(since = "1.0.0", reason = "renamed to bit_vec")]
+#[unstable(feature = "collections")]
+pub use bit_vec as bitv;
+
+#[deprecated(since = "1.0.0", reason = "renamed to bit_set")]
+#[unstable(feature = "collections")]
+pub use bit_set as bitv_set;
+
// Needed for the vec! macro
pub use alloc::boxed;
pub mod binary_heap;
mod bit;
mod btree;
-pub mod dlist;
+pub mod linked_list;
pub mod enum_set;
pub mod fmt;
-pub mod ring_buf;
+pub mod vec_deque;
pub mod slice;
pub mod str;
pub mod string;
pub mod vec;
pub mod vec_map;
+#[cfg(stage0)]
+#[path = "borrow_stage0.rs"]
+pub mod borrow;
+
+#[cfg(not(stage0))]
+pub mod borrow;
+
#[unstable(feature = "collections",
reason = "RFC 509")]
-pub mod bitv {
- pub use bit::{Bitv, Iter};
+pub mod bit_vec {
+ pub use bit::{BitVec, Iter};
+
+ #[deprecated(since = "1.0.0", reason = "renamed to BitVec")]
+ #[unstable(feature = "collections")]
+ pub use bit::BitVec as Bitv;
}
#[unstable(feature = "collections",
reason = "RFC 509")]
-pub mod bitv_set {
- pub use bit::{BitvSet, Union, Intersection, Difference, SymmetricDifference};
+pub mod bit_set {
+ pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference};
pub use bit::SetIter as Iter;
+
+ #[deprecated(since = "1.0.0", reason = "renamed to BitSet")]
+ #[unstable(feature = "collections")]
+ pub use bit::BitSet as BitvSet;
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(test)]
mod prelude {
// from core.
- pub use core::borrow::IntoCow;
pub use core::clone::Clone;
pub use core::cmp::{PartialEq, Eq, PartialOrd, Ord};
pub use core::cmp::Ordering::{Less, Equal, Greater};
pub use unicode::char::CharExt;
// from collections.
+ pub use borrow::IntoCow;
pub use slice::SliceConcatExt;
pub use string::{String, ToString};
pub use vec::Vec;
--- /dev/null
+// Copyright 2012-2015 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 doubly-linked list with owned nodes.
+//!
+//! The `LinkedList` allows pushing and popping elements at either end and is thus
+//! efficiently usable as a double-ended queue.
+
+// LinkedList is constructed like a singly-linked list over the field `next`.
+// including the last link being None; each Node owns its `next` field.
+//
+// Backlinks over LinkedList::prev are raw pointers that form a full chain in
+// the reverse direction.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use core::prelude::*;
+
+use alloc::boxed::Box;
+use core::cmp::Ordering;
+use core::default::Default;
+use core::fmt;
+use core::hash::{Hasher, Hash};
+#[cfg(stage0)]
+use core::hash::Writer;
+use core::iter::{self, FromIterator, IntoIterator};
+use core::mem;
+use core::ptr;
+
+#[deprecated(since = "1.0.0", reason = "renamed to LinkedList")]
+#[unstable(feature = "collections")]
+pub use LinkedList as DList;
+
+/// A doubly-linked list.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct LinkedList<T> {
+ length: usize,
+ list_head: Link<T>,
+ list_tail: Rawlink<Node<T>>,
+}
+
+type Link<T> = Option<Box<Node<T>>>;
+
+struct Rawlink<T> {
+ p: *mut T,
+}
+
+impl<T> Copy for Rawlink<T> {}
+unsafe impl<T:'static+Send> Send for Rawlink<T> {}
+unsafe impl<T:Send+Sync> Sync for Rawlink<T> {}
+
+struct Node<T> {
+ next: Link<T>,
+ prev: Rawlink<Node<T>>,
+ value: T,
+}
+
+/// An iterator over references to the items of a `LinkedList`.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Iter<'a, T:'a> {
+ head: &'a Link<T>,
+ tail: Rawlink<Node<T>>,
+ nelem: usize,
+}
+
+// FIXME #19839: deriving is too aggressive on the bounds (T doesn't need to be Clone).
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> Clone for Iter<'a, T> {
+ fn clone(&self) -> Iter<'a, T> {
+ Iter {
+ head: self.head.clone(),
+ tail: self.tail,
+ nelem: self.nelem,
+ }
+ }
+}
+
+/// An iterator over mutable references to the items of a `LinkedList`.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct IterMut<'a, T:'a> {
+ list: &'a mut LinkedList<T>,
+ head: Rawlink<Node<T>>,
+ tail: Rawlink<Node<T>>,
+ nelem: usize,
+}
+
+/// An iterator over mutable references to the items of a `LinkedList`.
+#[derive(Clone)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct IntoIter<T> {
+ list: LinkedList<T>
+}
+
+/// Rawlink is a type like Option<T> but for holding a raw pointer
+impl<T> Rawlink<T> {
+ /// Like Option::None for Rawlink
+ fn none() -> Rawlink<T> {
+ Rawlink{p: ptr::null_mut()}
+ }
+
+ /// Like Option::Some for Rawlink
+ fn some(n: &mut T) -> Rawlink<T> {
+ Rawlink{p: n}
+ }
+
+ /// Convert the `Rawlink` into an Option value
+ fn resolve_immut<'a>(&self) -> Option<&'a T> {
+ unsafe {
+ mem::transmute(self.p.as_ref())
+ }
+ }
+
+ /// Convert the `Rawlink` into an Option value
+ fn resolve<'a>(&mut self) -> Option<&'a mut T> {
+ if self.p.is_null() {
+ None
+ } else {
+ Some(unsafe { mem::transmute(self.p) })
+ }
+ }
+
+ /// Return the `Rawlink` and replace with `Rawlink::none()`
+ fn take(&mut self) -> Rawlink<T> {
+ mem::replace(self, Rawlink::none())
+ }
+}
+
+impl<T> Clone for Rawlink<T> {
+ #[inline]
+ fn clone(&self) -> Rawlink<T> {
+ Rawlink{p: self.p}
+ }
+}
+
+impl<T> Node<T> {
+ fn new(v: T) -> Node<T> {
+ Node{value: v, next: None, prev: Rawlink::none()}
+ }
+}
+
+/// Set the .prev field on `next`, then return `Some(next)`
+fn link_with_prev<T>(mut next: Box<Node<T>>, prev: Rawlink<Node<T>>)
+ -> Link<T> {
+ next.prev = prev;
+ Some(next)
+}
+
+// private methods
+impl<T> LinkedList<T> {
+ /// Add a Node first in the list
+ #[inline]
+ fn push_front_node(&mut self, mut new_head: Box<Node<T>>) {
+ match self.list_head {
+ None => {
+ self.list_tail = Rawlink::some(&mut *new_head);
+ self.list_head = link_with_prev(new_head, Rawlink::none());
+ }
+ Some(ref mut head) => {
+ new_head.prev = Rawlink::none();
+ head.prev = Rawlink::some(&mut *new_head);
+ mem::swap(head, &mut new_head);
+ head.next = Some(new_head);
+ }
+ }
+ self.length += 1;
+ }
+
+ /// Remove the first Node and return it, or None if the list is empty
+ #[inline]
+ fn pop_front_node(&mut self) -> Option<Box<Node<T>>> {
+ self.list_head.take().map(|mut front_node| {
+ self.length -= 1;
+ match front_node.next.take() {
+ Some(node) => self.list_head = link_with_prev(node, Rawlink::none()),
+ None => self.list_tail = Rawlink::none()
+ }
+ front_node
+ })
+ }
+
+ /// Add a Node last in the list
+ #[inline]
+ fn push_back_node(&mut self, mut new_tail: Box<Node<T>>) {
+ match self.list_tail.resolve() {
+ None => return self.push_front_node(new_tail),
+ Some(tail) => {
+ self.list_tail = Rawlink::some(&mut *new_tail);
+ tail.next = link_with_prev(new_tail, Rawlink::some(tail));
+ }
+ }
+ self.length += 1;
+ }
+
+ /// Remove the last Node and return it, or None if the list is empty
+ #[inline]
+ fn pop_back_node(&mut self) -> Option<Box<Node<T>>> {
+ self.list_tail.resolve().map_or(None, |tail| {
+ self.length -= 1;
+ self.list_tail = tail.prev;
+ match tail.prev.resolve() {
+ None => self.list_head.take(),
+ Some(tail_prev) => tail_prev.next.take()
+ }
+ })
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> Default for LinkedList<T> {
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn default() -> LinkedList<T> { LinkedList::new() }
+}
+
+impl<T> LinkedList<T> {
+ /// Creates an empty `LinkedList`.
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn new() -> LinkedList<T> {
+ LinkedList{list_head: None, list_tail: Rawlink::none(), length: 0}
+ }
+
+ /// Moves all elements from `other` to the end of the list.
+ ///
+ /// This reuses all the nodes from `other` and moves them into `self`. After
+ /// this operation, `other` becomes empty.
+ ///
+ /// This operation should compute in O(1) time and O(1) memory.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut a = LinkedList::new();
+ /// let mut b = LinkedList::new();
+ /// a.push_back(1);
+ /// a.push_back(2);
+ /// b.push_back(3);
+ /// b.push_back(4);
+ ///
+ /// a.append(&mut b);
+ ///
+ /// for e in a.iter() {
+ /// println!("{}", e); // prints 1, then 2, then 3, then 4
+ /// }
+ /// println!("{}", b.len()); // prints 0
+ /// ```
+ pub fn append(&mut self, other: &mut LinkedList<T>) {
+ match self.list_tail.resolve() {
+ None => {
+ self.length = other.length;
+ self.list_head = other.list_head.take();
+ self.list_tail = other.list_tail.take();
+ },
+ Some(tail) => {
+ // Carefully empty `other`.
+ let o_tail = other.list_tail.take();
+ let o_length = other.length;
+ match other.list_head.take() {
+ None => return,
+ Some(node) => {
+ tail.next = link_with_prev(node, self.list_tail);
+ self.list_tail = o_tail;
+ self.length += o_length;
+ }
+ }
+ }
+ }
+ other.length = 0;
+ }
+
+ /// Provides a forward iterator.
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn iter(&self) -> Iter<T> {
+ Iter{nelem: self.len(), head: &self.list_head, tail: self.list_tail}
+ }
+
+ /// Provides a forward iterator with mutable references.
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn iter_mut(&mut self) -> IterMut<T> {
+ let head_raw = match self.list_head {
+ Some(ref mut h) => Rawlink::some(&mut **h),
+ None => Rawlink::none(),
+ };
+ IterMut{
+ nelem: self.len(),
+ head: head_raw,
+ tail: self.list_tail,
+ list: self
+ }
+ }
+
+ /// Consumes the list into an iterator yielding elements by value.
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn into_iter(self) -> IntoIter<T> {
+ IntoIter{list: self}
+ }
+
+ /// Returns `true` if the `LinkedList` is empty.
+ ///
+ /// This operation should compute in O(1) time.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut dl = LinkedList::new();
+ /// assert!(dl.is_empty());
+ ///
+ /// dl.push_front("foo");
+ /// assert!(!dl.is_empty());
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn is_empty(&self) -> bool {
+ self.list_head.is_none()
+ }
+
+ /// Returns the length of the `LinkedList`.
+ ///
+ /// This operation should compute in O(1) time.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut dl = LinkedList::new();
+ ///
+ /// dl.push_front(2);
+ /// assert_eq!(dl.len(), 1);
+ ///
+ /// dl.push_front(1);
+ /// assert_eq!(dl.len(), 2);
+ ///
+ /// dl.push_back(3);
+ /// assert_eq!(dl.len(), 3);
+ ///
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn len(&self) -> usize {
+ self.length
+ }
+
+ /// Removes all elements from the `LinkedList`.
+ ///
+ /// This operation should compute in O(n) time.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut dl = LinkedList::new();
+ ///
+ /// dl.push_front(2);
+ /// dl.push_front(1);
+ /// assert_eq!(dl.len(), 2);
+ /// assert_eq!(dl.front(), Some(&1));
+ ///
+ /// dl.clear();
+ /// assert_eq!(dl.len(), 0);
+ /// assert_eq!(dl.front(), None);
+ ///
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn clear(&mut self) {
+ *self = LinkedList::new()
+ }
+
+ /// Provides a reference to the front element, or `None` if the list is
+ /// empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut dl = LinkedList::new();
+ /// assert_eq!(dl.front(), None);
+ ///
+ /// dl.push_front(1);
+ /// assert_eq!(dl.front(), Some(&1));
+ ///
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn front(&self) -> Option<&T> {
+ self.list_head.as_ref().map(|head| &head.value)
+ }
+
+ /// Provides a mutable reference to the front element, or `None` if the list
+ /// is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut dl = LinkedList::new();
+ /// assert_eq!(dl.front(), None);
+ ///
+ /// dl.push_front(1);
+ /// assert_eq!(dl.front(), Some(&1));
+ ///
+ /// match dl.front_mut() {
+ /// None => {},
+ /// Some(x) => *x = 5,
+ /// }
+ /// assert_eq!(dl.front(), Some(&5));
+ ///
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn front_mut(&mut self) -> Option<&mut T> {
+ self.list_head.as_mut().map(|head| &mut head.value)
+ }
+
+ /// Provides a reference to the back element, or `None` if the list is
+ /// empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut dl = LinkedList::new();
+ /// assert_eq!(dl.back(), None);
+ ///
+ /// dl.push_back(1);
+ /// assert_eq!(dl.back(), Some(&1));
+ ///
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn back(&self) -> Option<&T> {
+ self.list_tail.resolve_immut().as_ref().map(|tail| &tail.value)
+ }
+
+ /// Provides a mutable reference to the back element, or `None` if the list
+ /// is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut dl = LinkedList::new();
+ /// assert_eq!(dl.back(), None);
+ ///
+ /// dl.push_back(1);
+ /// assert_eq!(dl.back(), Some(&1));
+ ///
+ /// match dl.back_mut() {
+ /// None => {},
+ /// Some(x) => *x = 5,
+ /// }
+ /// assert_eq!(dl.back(), Some(&5));
+ ///
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn back_mut(&mut self) -> Option<&mut T> {
+ self.list_tail.resolve().map(|tail| &mut tail.value)
+ }
+
+ /// Adds an element first in the list.
+ ///
+ /// This operation should compute in O(1) time.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut dl = LinkedList::new();
+ ///
+ /// dl.push_front(2);
+ /// assert_eq!(dl.front().unwrap(), &2);
+ ///
+ /// dl.push_front(1);
+ /// assert_eq!(dl.front().unwrap(), &1);
+ ///
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn push_front(&mut self, elt: T) {
+ self.push_front_node(box Node::new(elt))
+ }
+
+ /// Removes the first element and returns it, or `None` if the list is
+ /// empty.
+ ///
+ /// This operation should compute in O(1) time.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut d = LinkedList::new();
+ /// assert_eq!(d.pop_front(), None);
+ ///
+ /// d.push_front(1);
+ /// d.push_front(3);
+ /// assert_eq!(d.pop_front(), Some(3));
+ /// assert_eq!(d.pop_front(), Some(1));
+ /// assert_eq!(d.pop_front(), None);
+ ///
+ /// ```
+ ///
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn pop_front(&mut self) -> Option<T> {
+ self.pop_front_node().map(|box Node{value, ..}| value)
+ }
+
+ /// Appends an element to the back of a list
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut d = LinkedList::new();
+ /// d.push_back(1);
+ /// d.push_back(3);
+ /// assert_eq!(3, *d.back().unwrap());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn push_back(&mut self, elt: T) {
+ self.push_back_node(box Node::new(elt))
+ }
+
+ /// Removes the last element from a list and returns it, or `None` if
+ /// it is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut d = LinkedList::new();
+ /// assert_eq!(d.pop_back(), None);
+ /// d.push_back(1);
+ /// d.push_back(3);
+ /// assert_eq!(d.pop_back(), Some(3));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn pop_back(&mut self) -> Option<T> {
+ self.pop_back_node().map(|box Node{value, ..}| value)
+ }
+
+ /// Splits the list into two at the given index. Returns everything after the given index,
+ /// including the index.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `at > len`.
+ ///
+ /// This operation should compute in O(n) time.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut d = LinkedList::new();
+ ///
+ /// d.push_front(1);
+ /// d.push_front(2);
+ /// d.push_front(3);
+ ///
+ /// let mut splitted = d.split_off(2);
+ ///
+ /// assert_eq!(splitted.pop_front(), Some(1));
+ /// assert_eq!(splitted.pop_front(), None);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn split_off(&mut self, at: usize) -> LinkedList<T> {
+ let len = self.len();
+ assert!(at <= len, "Cannot split off at a nonexistent index");
+ if at == 0 {
+ return mem::replace(self, LinkedList::new());
+ } else if at == len {
+ return LinkedList::new();
+ }
+
+ // Below, we iterate towards the `i-1`th node, either from the start or the end,
+ // depending on which would be faster.
+ let mut split_node = if at - 1 <= len - 1 - (at - 1) {
+ let mut iter = self.iter_mut();
+ // instead of skipping using .skip() (which creates a new struct),
+ // we skip manually so we can access the head field without
+ // depending on implementation details of Skip
+ for _ in 0..at - 1 {
+ iter.next();
+ }
+ iter.head
+ } else {
+ // better off starting from the end
+ let mut iter = self.iter_mut();
+ for _ in 0..len - 1 - (at - 1) {
+ iter.next_back();
+ }
+ iter.tail
+ };
+
+ let mut splitted_list = LinkedList {
+ list_head: None,
+ list_tail: self.list_tail,
+ length: len - at
+ };
+
+ mem::swap(&mut split_node.resolve().unwrap().next, &mut splitted_list.list_head);
+ self.list_tail = split_node;
+ self.length = at;
+
+ splitted_list
+ }
+}
+
+#[unsafe_destructor]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> Drop for LinkedList<T> {
+ fn drop(&mut self) {
+ // Dissolve the linked_list in backwards direction
+ // Just dropping the list_head can lead to stack exhaustion
+ // when length is >> 1_000_000
+ let mut tail = self.list_tail;
+ loop {
+ match tail.resolve() {
+ None => break,
+ Some(prev) => {
+ prev.next.take(); // release Box<Node<T>>
+ tail = prev.prev;
+ }
+ }
+ }
+ self.length = 0;
+ self.list_head = None;
+ self.list_tail = Rawlink::none();
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, A> Iterator for Iter<'a, A> {
+ type Item = &'a A;
+
+ #[inline]
+ fn next(&mut self) -> Option<&'a A> {
+ if self.nelem == 0 {
+ return None;
+ }
+ self.head.as_ref().map(|head| {
+ self.nelem -= 1;
+ self.head = &head.next;
+ &head.value
+ })
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.nelem, Some(self.nelem))
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, A> DoubleEndedIterator for Iter<'a, A> {
+ #[inline]
+ fn next_back(&mut self) -> Option<&'a A> {
+ if self.nelem == 0 {
+ return None;
+ }
+ self.tail.resolve_immut().as_ref().map(|prev| {
+ self.nelem -= 1;
+ self.tail = prev.prev;
+ &prev.value
+ })
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, A> ExactSizeIterator for Iter<'a, A> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, A> Iterator for IterMut<'a, A> {
+ type Item = &'a mut A;
+ #[inline]
+ fn next(&mut self) -> Option<&'a mut A> {
+ if self.nelem == 0 {
+ return None;
+ }
+ self.head.resolve().map(|next| {
+ self.nelem -= 1;
+ self.head = match next.next {
+ Some(ref mut node) => Rawlink::some(&mut **node),
+ None => Rawlink::none(),
+ };
+ &mut next.value
+ })
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.nelem, Some(self.nelem))
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, A> DoubleEndedIterator for IterMut<'a, A> {
+ #[inline]
+ fn next_back(&mut self) -> Option<&'a mut A> {
+ if self.nelem == 0 {
+ return None;
+ }
+ self.tail.resolve().map(|prev| {
+ self.nelem -= 1;
+ self.tail = prev.prev;
+ &mut prev.value
+ })
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, A> ExactSizeIterator for IterMut<'a, A> {}
+
+// private methods for IterMut
+impl<'a, A> IterMut<'a, A> {
+ fn insert_next_node(&mut self, mut ins_node: Box<Node<A>>) {
+ // Insert before `self.head` so that it is between the
+ // previously yielded element and self.head.
+ //
+ // The inserted node will not appear in further iteration.
+ match self.head.resolve() {
+ None => { self.list.push_back_node(ins_node); }
+ Some(node) => {
+ let prev_node = match node.prev.resolve() {
+ None => return self.list.push_front_node(ins_node),
+ Some(prev) => prev,
+ };
+ let node_own = prev_node.next.take().unwrap();
+ ins_node.next = link_with_prev(node_own, Rawlink::some(&mut *ins_node));
+ prev_node.next = link_with_prev(ins_node, Rawlink::some(prev_node));
+ self.list.length += 1;
+ }
+ }
+ }
+}
+
+impl<'a, A> IterMut<'a, A> {
+ /// Inserts `elt` just after the element most recently returned by `.next()`.
+ /// The inserted element does not appear in the iteration.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut list: LinkedList<_> = vec![1, 3, 4].into_iter().collect();
+ ///
+ /// {
+ /// let mut it = list.iter_mut();
+ /// assert_eq!(it.next().unwrap(), &1);
+ /// // insert `2` after `1`
+ /// it.insert_next(2);
+ /// }
+ /// {
+ /// let vec: Vec<_> = list.into_iter().collect();
+ /// assert_eq!(vec, vec![1, 2, 3, 4]);
+ /// }
+ /// ```
+ #[inline]
+ #[unstable(feature = "collections",
+ reason = "this is probably better handled by a cursor type -- we'll see")]
+ pub fn insert_next(&mut self, elt: A) {
+ self.insert_next_node(box Node::new(elt))
+ }
+
+ /// Provides a reference to the next element, without changing the iterator.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::LinkedList;
+ ///
+ /// let mut list: LinkedList<_> = vec![1, 2, 3].into_iter().collect();
+ ///
+ /// let mut it = list.iter_mut();
+ /// assert_eq!(it.next().unwrap(), &1);
+ /// assert_eq!(it.peek_next().unwrap(), &2);
+ /// // We just peeked at 2, so it was not consumed from the iterator.
+ /// assert_eq!(it.next().unwrap(), &2);
+ /// ```
+ #[inline]
+ #[unstable(feature = "collections",
+ reason = "this is probably better handled by a cursor type -- we'll see")]
+ pub fn peek_next(&mut self) -> Option<&mut A> {
+ if self.nelem == 0 {
+ return None
+ }
+ self.head.resolve().map(|head| &mut head.value)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A> Iterator for IntoIter<A> {
+ type Item = A;
+
+ #[inline]
+ fn next(&mut self) -> Option<A> { self.list.pop_front() }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ (self.list.length, Some(self.list.length))
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A> DoubleEndedIterator for IntoIter<A> {
+ #[inline]
+ fn next_back(&mut self) -> Option<A> { self.list.pop_back() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A> FromIterator<A> for LinkedList<A> {
+ fn from_iter<T: IntoIterator<Item=A>>(iter: T) -> LinkedList<A> {
+ let mut ret = DList::new();
+ ret.extend(iter);
+ ret
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> IntoIterator for LinkedList<T> {
+ type Item = T;
+ type IntoIter = IntoIter<T>;
+
+ fn into_iter(self) -> IntoIter<T> {
+ self.into_iter()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> IntoIterator for &'a LinkedList<T> {
+ type Item = &'a T;
+ type IntoIter = Iter<'a, T>;
+
+ fn into_iter(self) -> Iter<'a, T> {
+ self.iter()
+ }
+}
+
+impl<'a, T> IntoIterator for &'a mut LinkedList<T> {
+ type Item = &'a mut T;
+ type IntoIter = IterMut<'a, T>;
+
+ fn into_iter(mut self) -> IterMut<'a, T> {
+ self.iter_mut()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A> Extend<A> for LinkedList<A> {
+ fn extend<T: IntoIterator<Item=A>>(&mut self, iter: T) {
+ for elt in iter { self.push_back(elt); }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A: PartialEq> PartialEq for LinkedList<A> {
+ fn eq(&self, other: &LinkedList<A>) -> bool {
+ self.len() == other.len() &&
+ iter::order::eq(self.iter(), other.iter())
+ }
+
+ fn ne(&self, other: &LinkedList<A>) -> bool {
+ self.len() != other.len() ||
+ iter::order::ne(self.iter(), other.iter())
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A: Eq> Eq for LinkedList<A> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A: PartialOrd> PartialOrd for LinkedList<A> {
+ fn partial_cmp(&self, other: &LinkedList<A>) -> Option<Ordering> {
+ iter::order::partial_cmp(self.iter(), other.iter())
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A: Ord> Ord for LinkedList<A> {
+ #[inline]
+ fn cmp(&self, other: &LinkedList<A>) -> Ordering {
+ iter::order::cmp(self.iter(), other.iter())
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A: Clone> Clone for LinkedList<A> {
+ fn clone(&self) -> LinkedList<A> {
+ self.iter().cloned().collect()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A: fmt::Debug> fmt::Debug for LinkedList<A> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ try!(write!(f, "LinkedList ["));
+
+ for (i, e) in self.iter().enumerate() {
+ if i != 0 { try!(write!(f, ", ")); }
+ try!(write!(f, "{:?}", *e));
+ }
+
+ write!(f, "]")
+ }
+}
+
+#[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> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.len().hash(state);
+ for elt in self {
+ elt.hash(state);
+ }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use prelude::*;
+ use std::rand;
+ use std::hash::{self, SipHasher};
+ use std::thread;
+ use test::Bencher;
+ use test;
+
+ use super::{LinkedList, Node};
+
+ pub fn check_links<T>(list: &LinkedList<T>) {
+ let mut len = 0;
+ let mut last_ptr: Option<&Node<T>> = None;
+ let mut node_ptr: &Node<T>;
+ match list.list_head {
+ None => { assert_eq!(0, list.length); return }
+ Some(ref node) => node_ptr = &**node,
+ }
+ loop {
+ match (last_ptr, node_ptr.prev.resolve_immut()) {
+ (None , None ) => {}
+ (None , _ ) => panic!("prev link for list_head"),
+ (Some(p), Some(pptr)) => {
+ assert_eq!(p as *const Node<T>, pptr as *const Node<T>);
+ }
+ _ => panic!("prev link is none, not good"),
+ }
+ match node_ptr.next {
+ Some(ref next) => {
+ last_ptr = Some(node_ptr);
+ node_ptr = &**next;
+ len += 1;
+ }
+ None => {
+ len += 1;
+ break;
+ }
+ }
+ }
+ assert_eq!(len, list.length);
+ }
+
+ #[test]
+ fn test_basic() {
+ let mut m = LinkedList::new();
+ assert_eq!(m.pop_front(), None);
+ assert_eq!(m.pop_back(), None);
+ assert_eq!(m.pop_front(), None);
+ m.push_front(box 1);
+ assert_eq!(m.pop_front(), Some(box 1));
+ m.push_back(box 2);
+ m.push_back(box 3);
+ assert_eq!(m.len(), 2);
+ assert_eq!(m.pop_front(), Some(box 2));
+ assert_eq!(m.pop_front(), Some(box 3));
+ assert_eq!(m.len(), 0);
+ assert_eq!(m.pop_front(), None);
+ m.push_back(box 1);
+ m.push_back(box 3);
+ m.push_back(box 5);
+ m.push_back(box 7);
+ assert_eq!(m.pop_front(), Some(box 1));
+
+ let mut n = LinkedList::new();
+ n.push_front(2);
+ n.push_front(3);
+ {
+ assert_eq!(n.front().unwrap(), &3);
+ let x = n.front_mut().unwrap();
+ assert_eq!(*x, 3);
+ *x = 0;
+ }
+ {
+ assert_eq!(n.back().unwrap(), &2);
+ let y = n.back_mut().unwrap();
+ assert_eq!(*y, 2);
+ *y = 1;
+ }
+ assert_eq!(n.pop_front(), Some(0));
+ assert_eq!(n.pop_front(), Some(1));
+ }
+
+ #[cfg(test)]
+ fn generate_test() -> LinkedList<i32> {
+ list_from(&[0,1,2,3,4,5,6])
+ }
+
+ #[cfg(test)]
+ fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> {
+ v.iter().cloned().collect()
+ }
+
+ #[test]
+ fn test_append() {
+ // Empty to empty
+ {
+ let mut m = LinkedList::<i32>::new();
+ let mut n = LinkedList::new();
+ m.append(&mut n);
+ check_links(&m);
+ assert_eq!(m.len(), 0);
+ assert_eq!(n.len(), 0);
+ }
+ // Non-empty to empty
+ {
+ let mut m = LinkedList::new();
+ let mut n = LinkedList::new();
+ n.push_back(2);
+ m.append(&mut n);
+ check_links(&m);
+ assert_eq!(m.len(), 1);
+ assert_eq!(m.pop_back(), Some(2));
+ assert_eq!(n.len(), 0);
+ check_links(&m);
+ }
+ // Empty to non-empty
+ {
+ let mut m = LinkedList::new();
+ let mut n = LinkedList::new();
+ m.push_back(2);
+ m.append(&mut n);
+ check_links(&m);
+ assert_eq!(m.len(), 1);
+ assert_eq!(m.pop_back(), Some(2));
+ check_links(&m);
+ }
+
+ // Non-empty to non-empty
+ let v = vec![1,2,3,4,5];
+ let u = vec![9,8,1,2,3,4,5];
+ let mut m = list_from(&v);
+ let mut n = list_from(&u);
+ m.append(&mut n);
+ check_links(&m);
+ let mut sum = v;
+ sum.push_all(&u);
+ assert_eq!(sum.len(), m.len());
+ for elt in sum {
+ assert_eq!(m.pop_front(), Some(elt))
+ }
+ assert_eq!(n.len(), 0);
+ // let's make sure it's working properly, since we
+ // did some direct changes to private members
+ n.push_back(3);
+ assert_eq!(n.len(), 1);
+ assert_eq!(n.pop_front(), Some(3));
+ check_links(&n);
+ }
+
+ #[test]
+ fn test_split_off() {
+ // singleton
+ {
+ let mut m = LinkedList::new();
+ m.push_back(1);
+
+ let p = m.split_off(0);
+ assert_eq!(m.len(), 0);
+ assert_eq!(p.len(), 1);
+ assert_eq!(p.back(), Some(&1));
+ assert_eq!(p.front(), Some(&1));
+ }
+
+ // not singleton, forwards
+ {
+ let u = vec![1,2,3,4,5];
+ let mut m = list_from(&u);
+ let mut n = m.split_off(2);
+ assert_eq!(m.len(), 2);
+ assert_eq!(n.len(), 3);
+ for elt in 1..3 {
+ assert_eq!(m.pop_front(), Some(elt));
+ }
+ for elt in 3..6 {
+ assert_eq!(n.pop_front(), Some(elt));
+ }
+ }
+ // not singleton, backwards
+ {
+ let u = vec![1,2,3,4,5];
+ let mut m = list_from(&u);
+ let mut n = m.split_off(4);
+ assert_eq!(m.len(), 4);
+ assert_eq!(n.len(), 1);
+ for elt in 1..5 {
+ assert_eq!(m.pop_front(), Some(elt));
+ }
+ for elt in 5..6 {
+ assert_eq!(n.pop_front(), Some(elt));
+ }
+ }
+
+ // no-op on the last index
+ {
+ let mut m = LinkedList::new();
+ m.push_back(1);
+
+ let p = m.split_off(1);
+ assert_eq!(m.len(), 1);
+ assert_eq!(p.len(), 0);
+ assert_eq!(m.back(), Some(&1));
+ assert_eq!(m.front(), Some(&1));
+ }
+
+ }
+
+ #[test]
+ fn test_iterator() {
+ let m = generate_test();
+ for (i, elt) in m.iter().enumerate() {
+ assert_eq!(i as i32, *elt);
+ }
+ let mut n = LinkedList::new();
+ assert_eq!(n.iter().next(), None);
+ n.push_front(4);
+ let mut it = n.iter();
+ assert_eq!(it.size_hint(), (1, Some(1)));
+ assert_eq!(it.next().unwrap(), &4);
+ assert_eq!(it.size_hint(), (0, Some(0)));
+ assert_eq!(it.next(), None);
+ }
+
+ #[test]
+ fn test_iterator_clone() {
+ let mut n = LinkedList::new();
+ n.push_back(2);
+ n.push_back(3);
+ n.push_back(4);
+ let mut it = n.iter();
+ it.next();
+ let mut jt = it.clone();
+ assert_eq!(it.next(), jt.next());
+ assert_eq!(it.next_back(), jt.next_back());
+ assert_eq!(it.next(), jt.next());
+ }
+
+ #[test]
+ fn test_iterator_double_end() {
+ let mut n = LinkedList::new();
+ assert_eq!(n.iter().next(), None);
+ n.push_front(4);
+ n.push_front(5);
+ n.push_front(6);
+ let mut it = n.iter();
+ assert_eq!(it.size_hint(), (3, Some(3)));
+ assert_eq!(it.next().unwrap(), &6);
+ assert_eq!(it.size_hint(), (2, Some(2)));
+ assert_eq!(it.next_back().unwrap(), &4);
+ assert_eq!(it.size_hint(), (1, Some(1)));
+ assert_eq!(it.next_back().unwrap(), &5);
+ assert_eq!(it.next_back(), None);
+ assert_eq!(it.next(), None);
+ }
+
+ #[test]
+ fn test_rev_iter() {
+ let m = generate_test();
+ for (i, elt) in m.iter().rev().enumerate() {
+ assert_eq!((6 - i) as i32, *elt);
+ }
+ let mut n = LinkedList::new();
+ assert_eq!(n.iter().rev().next(), None);
+ n.push_front(4);
+ let mut it = n.iter().rev();
+ assert_eq!(it.size_hint(), (1, Some(1)));
+ assert_eq!(it.next().unwrap(), &4);
+ assert_eq!(it.size_hint(), (0, Some(0)));
+ assert_eq!(it.next(), None);
+ }
+
+ #[test]
+ fn test_mut_iter() {
+ let mut m = generate_test();
+ let mut len = m.len();
+ for (i, elt) in m.iter_mut().enumerate() {
+ assert_eq!(i as i32, *elt);
+ len -= 1;
+ }
+ assert_eq!(len, 0);
+ let mut n = LinkedList::new();
+ assert!(n.iter_mut().next().is_none());
+ n.push_front(4);
+ n.push_back(5);
+ let mut it = n.iter_mut();
+ assert_eq!(it.size_hint(), (2, Some(2)));
+ assert!(it.next().is_some());
+ assert!(it.next().is_some());
+ assert_eq!(it.size_hint(), (0, Some(0)));
+ assert!(it.next().is_none());
+ }
+
+ #[test]
+ fn test_iterator_mut_double_end() {
+ let mut n = LinkedList::new();
+ assert!(n.iter_mut().next_back().is_none());
+ n.push_front(4);
+ n.push_front(5);
+ n.push_front(6);
+ let mut it = n.iter_mut();
+ assert_eq!(it.size_hint(), (3, Some(3)));
+ assert_eq!(*it.next().unwrap(), 6);
+ assert_eq!(it.size_hint(), (2, Some(2)));
+ assert_eq!(*it.next_back().unwrap(), 4);
+ assert_eq!(it.size_hint(), (1, Some(1)));
+ assert_eq!(*it.next_back().unwrap(), 5);
+ assert!(it.next_back().is_none());
+ assert!(it.next().is_none());
+ }
+
+ #[test]
+ fn test_insert_prev() {
+ let mut m = list_from(&[0,2,4,6,8]);
+ let len = m.len();
+ {
+ let mut it = m.iter_mut();
+ it.insert_next(-2);
+ loop {
+ match it.next() {
+ None => break,
+ Some(elt) => {
+ it.insert_next(*elt + 1);
+ match it.peek_next() {
+ Some(x) => assert_eq!(*x, *elt + 2),
+ None => assert_eq!(8, *elt),
+ }
+ }
+ }
+ }
+ it.insert_next(0);
+ it.insert_next(1);
+ }
+ check_links(&m);
+ assert_eq!(m.len(), 3 + len * 2);
+ assert_eq!(m.into_iter().collect::<Vec<_>>(), vec![-2,0,1,2,3,4,5,6,7,8,9,0,1]);
+ }
+
+ #[test]
+ fn test_mut_rev_iter() {
+ let mut m = generate_test();
+ for (i, elt) in m.iter_mut().rev().enumerate() {
+ assert_eq!((6 - i) as i32, *elt);
+ }
+ let mut n = LinkedList::new();
+ assert!(n.iter_mut().rev().next().is_none());
+ n.push_front(4);
+ let mut it = n.iter_mut().rev();
+ assert!(it.next().is_some());
+ assert!(it.next().is_none());
+ }
+
+ #[test]
+ fn test_send() {
+ let n = list_from(&[1,2,3]);
+ thread::spawn(move || {
+ check_links(&n);
+ let a: &[_] = &[&1,&2,&3];
+ assert_eq!(a, n.iter().collect::<Vec<_>>());
+ }).join().ok().unwrap();
+ }
+
+ #[test]
+ fn test_eq() {
+ let mut n = list_from(&[]);
+ let mut m = list_from(&[]);
+ assert!(n == m);
+ n.push_front(1);
+ assert!(n != m);
+ m.push_back(1);
+ assert!(n == m);
+
+ let n = list_from(&[2,3,4]);
+ let m = list_from(&[1,2,3]);
+ assert!(n != m);
+ }
+
+ #[test]
+ fn test_hash() {
+ let mut x = LinkedList::new();
+ let mut y = LinkedList::new();
+
+ assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y));
+
+ x.push_back(1);
+ x.push_back(2);
+ x.push_back(3);
+
+ y.push_front(3);
+ y.push_front(2);
+ y.push_front(1);
+
+ assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y));
+ }
+
+ #[test]
+ fn test_ord() {
+ let n = list_from(&[]);
+ let m = list_from(&[1,2,3]);
+ assert!(n < m);
+ assert!(m > n);
+ assert!(n <= n);
+ assert!(n >= n);
+ }
+
+ #[test]
+ fn test_ord_nan() {
+ let nan = 0.0f64/0.0;
+ let n = list_from(&[nan]);
+ let m = list_from(&[nan]);
+ assert!(!(n < m));
+ assert!(!(n > m));
+ assert!(!(n <= m));
+ assert!(!(n >= m));
+
+ let n = list_from(&[nan]);
+ let one = list_from(&[1.0f64]);
+ assert!(!(n < one));
+ assert!(!(n > one));
+ assert!(!(n <= one));
+ assert!(!(n >= one));
+
+ let u = list_from(&[1.0f64,2.0,nan]);
+ let v = list_from(&[1.0f64,2.0,3.0]);
+ assert!(!(u < v));
+ assert!(!(u > v));
+ assert!(!(u <= v));
+ assert!(!(u >= v));
+
+ let s = list_from(&[1.0f64,2.0,4.0,2.0]);
+ let t = list_from(&[1.0f64,2.0,3.0,2.0]);
+ assert!(!(s < t));
+ assert!(s > one);
+ assert!(!(s <= one));
+ assert!(s >= one);
+ }
+
+ #[test]
+ fn test_fuzz() {
+ for _ in 0..25 {
+ fuzz_test(3);
+ fuzz_test(16);
+ fuzz_test(189);
+ }
+ }
+
+ #[test]
+ fn test_show() {
+ let list: LinkedList<_> = (0..10).collect();
+ assert_eq!(format!("{:?}", list), "LinkedList [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
+
+ let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect();
+ assert_eq!(format!("{:?}", list), "LinkedList [\"just\", \"one\", \"test\", \"more\"]");
+ }
+
+ #[cfg(test)]
+ fn fuzz_test(sz: i32) {
+ let mut m: LinkedList<_> = LinkedList::new();
+ let mut v = vec![];
+ for i in 0..sz {
+ check_links(&m);
+ let r: u8 = rand::random();
+ match r % 6 {
+ 0 => {
+ m.pop_back();
+ v.pop();
+ }
+ 1 => {
+ if !v.is_empty() {
+ m.pop_front();
+ v.remove(0);
+ }
+ }
+ 2 | 4 => {
+ m.push_front(-i);
+ v.insert(0, -i);
+ }
+ 3 | 5 | _ => {
+ m.push_back(i);
+ v.push(i);
+ }
+ }
+ }
+
+ check_links(&m);
+
+ let mut i = 0;
+ for (a, &b) in m.into_iter().zip(v.iter()) {
+ i += 1;
+ assert_eq!(a, b);
+ }
+ assert_eq!(i, v.len());
+ }
+
+ #[bench]
+ fn bench_collect_into(b: &mut test::Bencher) {
+ let v = &[0; 64];
+ b.iter(|| {
+ let _: LinkedList<_> = v.iter().cloned().collect();
+ })
+ }
+
+ #[bench]
+ fn bench_push_front(b: &mut test::Bencher) {
+ let mut m: LinkedList<_> = LinkedList::new();
+ b.iter(|| {
+ m.push_front(0);
+ })
+ }
+
+ #[bench]
+ fn bench_push_back(b: &mut test::Bencher) {
+ let mut m: LinkedList<_> = LinkedList::new();
+ b.iter(|| {
+ m.push_back(0);
+ })
+ }
+
+ #[bench]
+ fn bench_push_back_pop_back(b: &mut test::Bencher) {
+ let mut m: LinkedList<_> = LinkedList::new();
+ b.iter(|| {
+ m.push_back(0);
+ m.pop_back();
+ })
+ }
+
+ #[bench]
+ fn bench_push_front_pop_front(b: &mut test::Bencher) {
+ let mut m: LinkedList<_> = LinkedList::new();
+ b.iter(|| {
+ m.push_front(0);
+ m.pop_front();
+ })
+ }
+
+ #[bench]
+ fn bench_iter(b: &mut test::Bencher) {
+ let v = &[0; 128];
+ let m: LinkedList<_> = v.iter().cloned().collect();
+ b.iter(|| {
+ assert!(m.iter().count() == 128);
+ })
+ }
+ #[bench]
+ fn bench_iter_mut(b: &mut test::Bencher) {
+ let v = &[0; 128];
+ let mut m: LinkedList<_> = v.iter().cloned().collect();
+ b.iter(|| {
+ assert!(m.iter_mut().count() == 128);
+ })
+ }
+ #[bench]
+ fn bench_iter_rev(b: &mut test::Bencher) {
+ let v = &[0; 128];
+ let m: LinkedList<_> = v.iter().cloned().collect();
+ b.iter(|| {
+ assert!(m.iter().rev().count() == 128);
+ })
+ }
+ #[bench]
+ fn bench_iter_mut_rev(b: &mut test::Bencher) {
+ let v = &[0; 128];
+ let mut m: LinkedList<_> = v.iter().cloned().collect();
+ b.iter(|| {
+ assert!(m.iter_mut().rev().count() == 128);
+ })
+ }
+}
+++ /dev/null
-// Copyright 2012-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.
-
-//! RingBuf is a double-ended queue, which is implemented with the help of a
-//! growing circular buffer.
-//!
-//! This queue has `O(1)` amortized inserts and removals from both ends of the
-//! container. It also has `O(1)` indexing like a vector. The contained elements
-//! are not required to be copyable, and the queue will be sendable if the
-//! contained type is sendable.
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-use core::prelude::*;
-
-use core::cmp::Ordering;
-use core::default::Default;
-use core::fmt;
-use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator};
-use core::marker;
-use core::mem;
-use core::num::{Int, UnsignedInt};
-use core::ops::{Index, IndexMut};
-use core::ptr;
-use core::raw::Slice as RawSlice;
-
-use core::hash::{Writer, Hash, Hasher};
-use core::cmp;
-
-use alloc::heap;
-
-static INITIAL_CAPACITY: usize = 7; // 2^3 - 1
-static MINIMUM_CAPACITY: usize = 1; // 2 - 1
-
-/// `RingBuf` is a circular buffer, which can be used as a double-ended queue efficiently.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct RingBuf<T> {
- // tail and head are pointers into the buffer. Tail always points
- // to the first element that could be read, Head always points
- // to where data should be written.
- // If tail == head the buffer is empty. The length of the ringbuf
- // is defined as the distance between the two.
-
- tail: usize,
- head: usize,
- cap: usize,
- ptr: *mut T
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<T: Send> Send for RingBuf<T> {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<T: Sync> Sync for RingBuf<T> {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Clone> Clone for RingBuf<T> {
- fn clone(&self) -> RingBuf<T> {
- self.iter().cloned().collect()
- }
-}
-
-#[unsafe_destructor]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Drop for RingBuf<T> {
- fn drop(&mut self) {
- self.clear();
- unsafe {
- if mem::size_of::<T>() != 0 {
- heap::deallocate(self.ptr as *mut u8,
- self.cap * mem::size_of::<T>(),
- mem::min_align_of::<T>())
- }
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Default for RingBuf<T> {
- #[inline]
- fn default() -> RingBuf<T> { RingBuf::new() }
-}
-
-impl<T> RingBuf<T> {
- /// Turn ptr into a slice
- #[inline]
- unsafe fn buffer_as_slice(&self) -> &[T] {
- mem::transmute(RawSlice { data: self.ptr, len: self.cap })
- }
-
- /// Turn ptr into a mut slice
- #[inline]
- unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] {
- mem::transmute(RawSlice { data: self.ptr, len: self.cap })
- }
-
- /// Moves an element out of the buffer
- #[inline]
- unsafe fn buffer_read(&mut self, off: usize) -> T {
- ptr::read(self.ptr.offset(off as isize))
- }
-
- /// Writes an element into the buffer, moving it.
- #[inline]
- unsafe fn buffer_write(&mut self, off: usize, t: T) {
- ptr::write(self.ptr.offset(off as isize), t);
- }
-
- /// Returns true iff the buffer is at capacity
- #[inline]
- fn is_full(&self) -> bool { self.cap - self.len() == 1 }
-
- /// Returns the index in the underlying buffer for a given logical element
- /// index.
- #[inline]
- fn wrap_index(&self, idx: usize) -> usize { wrap_index(idx, self.cap) }
-
- /// Copies a contiguous block of memory len long from src to dst
- #[inline]
- unsafe fn copy(&self, dst: usize, src: usize, len: usize) {
- debug_assert!(dst + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
- self.cap);
- debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
- self.cap);
- ptr::copy_memory(
- self.ptr.offset(dst as isize),
- self.ptr.offset(src as isize),
- len);
- }
-
- /// Copies a contiguous block of memory len long from src to dst
- #[inline]
- unsafe fn copy_nonoverlapping(&self, dst: usize, src: usize, len: usize) {
- debug_assert!(dst + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
- self.cap);
- debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
- self.cap);
- ptr::copy_nonoverlapping_memory(
- self.ptr.offset(dst as isize),
- self.ptr.offset(src as isize),
- len);
- }
-}
-
-impl<T> RingBuf<T> {
- /// Creates an empty `RingBuf`.
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn new() -> RingBuf<T> {
- RingBuf::with_capacity(INITIAL_CAPACITY)
- }
-
- /// Creates an empty `RingBuf` with space for at least `n` elements.
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn with_capacity(n: usize) -> RingBuf<T> {
- // +1 since the ringbuffer always leaves one space empty
- let cap = cmp::max(n + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
- assert!(cap > n, "capacity overflow");
- let size = cap.checked_mul(mem::size_of::<T>())
- .expect("capacity overflow");
-
- let ptr = if mem::size_of::<T>() != 0 {
- unsafe {
- let ptr = heap::allocate(size, mem::min_align_of::<T>()) as *mut T;;
- if ptr.is_null() { ::alloc::oom() }
- ptr
- }
- } else {
- heap::EMPTY as *mut T
- };
-
- RingBuf {
- tail: 0,
- head: 0,
- cap: cap,
- ptr: ptr
- }
- }
-
- /// Retrieves an element in the `RingBuf` by index.
- ///
- /// # Examples
- ///
- /// ```rust
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::new();
- /// buf.push_back(3);
- /// buf.push_back(4);
- /// buf.push_back(5);
- /// assert_eq!(buf.get(1).unwrap(), &4);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn get(&self, i: usize) -> Option<&T> {
- if i < self.len() {
- let idx = self.wrap_index(self.tail + i);
- unsafe { Some(&*self.ptr.offset(idx as isize)) }
- } else {
- None
- }
- }
-
- /// Retrieves an element in the `RingBuf` mutably by index.
- ///
- /// # Examples
- ///
- /// ```rust
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::new();
- /// buf.push_back(3);
- /// buf.push_back(4);
- /// buf.push_back(5);
- /// match buf.get_mut(1) {
- /// None => {}
- /// Some(elem) => {
- /// *elem = 7;
- /// }
- /// }
- ///
- /// assert_eq!(buf[1], 7);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn get_mut(&mut self, i: usize) -> Option<&mut T> {
- if i < self.len() {
- let idx = self.wrap_index(self.tail + i);
- unsafe { Some(&mut *self.ptr.offset(idx as isize)) }
- } else {
- None
- }
- }
-
- /// Swaps elements at indices `i` and `j`.
- ///
- /// `i` and `j` may be equal.
- ///
- /// Fails if there is no element with either index.
- ///
- /// # Examples
- ///
- /// ```rust
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::new();
- /// buf.push_back(3);
- /// buf.push_back(4);
- /// buf.push_back(5);
- /// buf.swap(0, 2);
- /// assert_eq!(buf[0], 5);
- /// assert_eq!(buf[2], 3);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn swap(&mut self, i: usize, j: usize) {
- assert!(i < self.len());
- assert!(j < self.len());
- let ri = self.wrap_index(self.tail + i);
- let rj = self.wrap_index(self.tail + j);
- unsafe {
- ptr::swap(self.ptr.offset(ri as isize), self.ptr.offset(rj as isize))
- }
- }
-
- /// Returns the number of elements the `RingBuf` can hold without
- /// reallocating.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let buf: RingBuf<i32> = RingBuf::with_capacity(10);
- /// assert!(buf.capacity() >= 10);
- /// ```
- #[inline]
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn capacity(&self) -> usize { self.cap - 1 }
-
- /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
- /// given `RingBuf`. Does nothing if the capacity is already sufficient.
- ///
- /// Note that the allocator may give the collection more space than it requests. Therefore
- /// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future
- /// insertions are expected.
- ///
- /// # Panics
- ///
- /// Panics if the new capacity overflows `usize`.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut buf: RingBuf<i32> = vec![1].into_iter().collect();
- /// buf.reserve_exact(10);
- /// assert!(buf.capacity() >= 11);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn reserve_exact(&mut self, additional: usize) {
- self.reserve(additional);
- }
-
- /// Reserves capacity for at least `additional` more elements to be inserted in the given
- /// `Ringbuf`. The collection may reserve more space to avoid frequent reallocations.
- ///
- /// # Panics
- ///
- /// Panics if the new capacity overflows `usize`.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut buf: RingBuf<i32> = vec![1].into_iter().collect();
- /// buf.reserve(10);
- /// assert!(buf.capacity() >= 11);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn reserve(&mut self, additional: usize) {
- let new_len = self.len() + additional;
- assert!(new_len + 1 > self.len(), "capacity overflow");
- if new_len > self.capacity() {
- let count = (new_len + 1).next_power_of_two();
- assert!(count >= new_len + 1);
-
- if mem::size_of::<T>() != 0 {
- let old = self.cap * mem::size_of::<T>();
- let new = count.checked_mul(mem::size_of::<T>())
- .expect("capacity overflow");
- unsafe {
- self.ptr = heap::reallocate(self.ptr as *mut u8,
- old,
- new,
- mem::min_align_of::<T>()) as *mut T;
- if self.ptr.is_null() { ::alloc::oom() }
- }
- }
-
- // Move the shortest contiguous section of the ring buffer
- // T H
- // [o o o o o o o . ]
- // T H
- // A [o o o o o o o . . . . . . . . . ]
- // H T
- // [o o . o o o o o ]
- // T H
- // B [. . . o o o o o o o . . . . . . ]
- // H T
- // [o o o o o . o o ]
- // H T
- // C [o o o o o . . . . . . . . . o o ]
-
- let oldcap = self.cap;
- self.cap = count;
-
- if self.tail <= self.head { // A
- // Nop
- } else if self.head < oldcap - self.tail { // B
- unsafe {
- self.copy_nonoverlapping(oldcap, 0, self.head);
- }
- self.head += oldcap;
- debug_assert!(self.head > self.tail);
- } else { // C
- let new_tail = count - (oldcap - self.tail);
- unsafe {
- self.copy_nonoverlapping(new_tail, self.tail, oldcap - self.tail);
- }
- self.tail = new_tail;
- debug_assert!(self.head < self.tail);
- }
- debug_assert!(self.head < self.cap);
- debug_assert!(self.tail < self.cap);
- debug_assert!(self.cap.count_ones() == 1);
- }
- }
-
- /// Shrinks the capacity of the ringbuf as much as possible.
- ///
- /// It will drop down as close as possible to the length but the allocator may still inform the
- /// ringbuf that there is space for a few more elements.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::with_capacity(15);
- /// buf.extend(0..4);
- /// assert_eq!(buf.capacity(), 15);
- /// buf.shrink_to_fit();
- /// assert!(buf.capacity() >= 4);
- /// ```
- pub fn shrink_to_fit(&mut self) {
- // +1 since the ringbuffer always leaves one space empty
- // len + 1 can't overflow for an existing, well-formed ringbuf.
- let target_cap = cmp::max(self.len() + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
- if target_cap < self.cap {
- // There are three cases of interest:
- // All elements are out of desired bounds
- // Elements are contiguous, and head is out of desired bounds
- // Elements are discontiguous, and tail is out of desired bounds
- //
- // At all other times, element positions are unaffected.
- //
- // Indicates that elements at the head should be moved.
- let head_outside = self.head == 0 || self.head >= target_cap;
- // Move elements from out of desired bounds (positions after target_cap)
- if self.tail >= target_cap && head_outside {
- // T H
- // [. . . . . . . . o o o o o o o . ]
- // T H
- // [o o o o o o o . ]
- unsafe {
- self.copy_nonoverlapping(0, self.tail, self.len());
- }
- self.head = self.len();
- self.tail = 0;
- } else if self.tail != 0 && self.tail < target_cap && head_outside {
- // T H
- // [. . . o o o o o o o . . . . . . ]
- // H T
- // [o o . o o o o o ]
- let len = self.wrap_index(self.head - target_cap);
- unsafe {
- self.copy_nonoverlapping(0, target_cap, len);
- }
- self.head = len;
- debug_assert!(self.head < self.tail);
- } else if self.tail >= target_cap {
- // H T
- // [o o o o o . . . . . . . . . o o ]
- // H T
- // [o o o o o . o o ]
- debug_assert!(self.wrap_index(self.head - 1) < target_cap);
- let len = self.cap - self.tail;
- let new_tail = target_cap - len;
- unsafe {
- self.copy_nonoverlapping(new_tail, self.tail, len);
- }
- self.tail = new_tail;
- debug_assert!(self.head < self.tail);
- }
-
- if mem::size_of::<T>() != 0 {
- let old = self.cap * mem::size_of::<T>();
- let new_size = target_cap * mem::size_of::<T>();
- unsafe {
- self.ptr = heap::reallocate(self.ptr as *mut u8,
- old,
- new_size,
- mem::min_align_of::<T>()) as *mut T;
- if self.ptr.is_null() { ::alloc::oom() }
- }
- }
- self.cap = target_cap;
- debug_assert!(self.head < self.cap);
- debug_assert!(self.tail < self.cap);
- debug_assert!(self.cap.count_ones() == 1);
- }
- }
-
- /// Shorten a ringbuf, dropping excess elements from the back.
- ///
- /// If `len` is greater than the ringbuf's current length, this has no
- /// effect.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::new();
- /// buf.push_back(5);
- /// buf.push_back(10);
- /// buf.push_back(15);
- /// buf.truncate(1);
- /// assert_eq!(buf.len(), 1);
- /// assert_eq!(Some(&5), buf.get(0));
- /// ```
- #[unstable(feature = "collections",
- reason = "matches collection reform specification; waiting on panic semantics")]
- pub fn truncate(&mut self, len: usize) {
- for _ in len..self.len() {
- self.pop_back();
- }
- }
-
- /// Returns a front-to-back iterator.
- ///
- /// # Examples
- ///
- /// ```rust
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::new();
- /// buf.push_back(5);
- /// buf.push_back(3);
- /// buf.push_back(4);
- /// let b: &[_] = &[&5, &3, &4];
- /// assert_eq!(buf.iter().collect::<Vec<&i32>>().as_slice(), b);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn iter(&self) -> Iter<T> {
- Iter {
- tail: self.tail,
- head: self.head,
- ring: unsafe { self.buffer_as_slice() }
- }
- }
-
- /// Returns a front-to-back iterator that returns mutable references.
- ///
- /// # Examples
- ///
- /// ```rust
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::new();
- /// buf.push_back(5);
- /// buf.push_back(3);
- /// buf.push_back(4);
- /// for num in buf.iter_mut() {
- /// *num = *num - 2;
- /// }
- /// let b: &[_] = &[&mut 3, &mut 1, &mut 2];
- /// assert_eq!(&buf.iter_mut().collect::<Vec<&mut i32>>()[], b);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn iter_mut(&mut self) -> IterMut<T> {
- IterMut {
- tail: self.tail,
- head: self.head,
- cap: self.cap,
- ptr: self.ptr,
- marker: marker::ContravariantLifetime,
- }
- }
-
- /// Consumes the list into an iterator yielding elements by value.
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn into_iter(self) -> IntoIter<T> {
- IntoIter {
- inner: self,
- }
- }
-
- /// Returns a pair of slices which contain, in order, the contents of the
- /// `RingBuf`.
- #[inline]
- #[unstable(feature = "collections",
- reason = "matches collection reform specification, waiting for dust to settle")]
- pub fn as_slices(&self) -> (&[T], &[T]) {
- unsafe {
- let contiguous = self.is_contiguous();
- let buf = self.buffer_as_slice();
- if contiguous {
- let (empty, buf) = buf.split_at(0);
- (&buf[self.tail..self.head], empty)
- } else {
- let (mid, right) = buf.split_at(self.tail);
- let (left, _) = mid.split_at(self.head);
- (right, left)
- }
- }
- }
-
- /// Returns a pair of slices which contain, in order, the contents of the
- /// `RingBuf`.
- #[inline]
- #[unstable(feature = "collections",
- reason = "matches collection reform specification, waiting for dust to settle")]
- pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
- unsafe {
- let contiguous = self.is_contiguous();
- let head = self.head;
- let tail = self.tail;
- let buf = self.buffer_as_mut_slice();
-
- if contiguous {
- let (empty, buf) = buf.split_at_mut(0);
- (&mut buf[tail .. head], empty)
- } else {
- let (mid, right) = buf.split_at_mut(tail);
- let (left, _) = mid.split_at_mut(head);
-
- (right, left)
- }
- }
- }
-
- /// Returns the number of elements in the `RingBuf`.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut v = RingBuf::new();
- /// assert_eq!(v.len(), 0);
- /// v.push_back(1);
- /// assert_eq!(v.len(), 1);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn len(&self) -> usize { count(self.tail, self.head, self.cap) }
-
- /// Returns true if the buffer contains no elements
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut v = RingBuf::new();
- /// assert!(v.is_empty());
- /// v.push_front(1);
- /// assert!(!v.is_empty());
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn is_empty(&self) -> bool { self.len() == 0 }
-
- /// Creates a draining iterator that clears the `RingBuf` and iterates over
- /// the removed items from start to end.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut v = RingBuf::new();
- /// v.push_back(1);
- /// assert_eq!(v.drain().next(), Some(1));
- /// assert!(v.is_empty());
- /// ```
- #[inline]
- #[unstable(feature = "collections",
- reason = "matches collection reform specification, waiting for dust to settle")]
- pub fn drain(&mut self) -> Drain<T> {
- Drain {
- inner: self,
- }
- }
-
- /// Clears the buffer, removing all values.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut v = RingBuf::new();
- /// v.push_back(1);
- /// v.clear();
- /// assert!(v.is_empty());
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- #[inline]
- pub fn clear(&mut self) {
- self.drain();
- }
-
- /// Provides a reference to the front element, or `None` if the sequence is
- /// empty.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut d = RingBuf::new();
- /// assert_eq!(d.front(), None);
- ///
- /// d.push_back(1);
- /// d.push_back(2);
- /// assert_eq!(d.front(), Some(&1));
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn front(&self) -> Option<&T> {
- if !self.is_empty() { Some(&self[0]) } else { None }
- }
-
- /// Provides a mutable reference to the front element, or `None` if the
- /// sequence is empty.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut d = RingBuf::new();
- /// assert_eq!(d.front_mut(), None);
- ///
- /// d.push_back(1);
- /// d.push_back(2);
- /// match d.front_mut() {
- /// Some(x) => *x = 9,
- /// None => (),
- /// }
- /// assert_eq!(d.front(), Some(&9));
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn front_mut(&mut self) -> Option<&mut T> {
- if !self.is_empty() { Some(&mut self[0]) } else { None }
- }
-
- /// Provides a reference to the back element, or `None` if the sequence is
- /// empty.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut d = RingBuf::new();
- /// assert_eq!(d.back(), None);
- ///
- /// d.push_back(1);
- /// d.push_back(2);
- /// assert_eq!(d.back(), Some(&2));
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn back(&self) -> Option<&T> {
- if !self.is_empty() { Some(&self[self.len() - 1]) } else { None }
- }
-
- /// Provides a mutable reference to the back element, or `None` if the
- /// sequence is empty.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut d = RingBuf::new();
- /// assert_eq!(d.back(), None);
- ///
- /// d.push_back(1);
- /// d.push_back(2);
- /// match d.back_mut() {
- /// Some(x) => *x = 9,
- /// None => (),
- /// }
- /// assert_eq!(d.back(), Some(&9));
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn back_mut(&mut self) -> Option<&mut T> {
- let len = self.len();
- if !self.is_empty() { Some(&mut self[len - 1]) } else { None }
- }
-
- /// Removes the first element and returns it, or `None` if the sequence is
- /// empty.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut d = RingBuf::new();
- /// d.push_back(1);
- /// d.push_back(2);
- ///
- /// assert_eq!(d.pop_front(), Some(1));
- /// assert_eq!(d.pop_front(), Some(2));
- /// assert_eq!(d.pop_front(), None);
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn pop_front(&mut self) -> Option<T> {
- if self.is_empty() {
- None
- } else {
- let tail = self.tail;
- self.tail = self.wrap_index(self.tail + 1);
- unsafe { Some(self.buffer_read(tail)) }
- }
- }
-
- /// Inserts an element first in the sequence.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut d = RingBuf::new();
- /// d.push_front(1);
- /// d.push_front(2);
- /// assert_eq!(d.front(), Some(&2));
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn push_front(&mut self, t: T) {
- if self.is_full() {
- self.reserve(1);
- debug_assert!(!self.is_full());
- }
-
- self.tail = self.wrap_index(self.tail - 1);
- let tail = self.tail;
- unsafe { self.buffer_write(tail, t); }
- }
-
- /// Appends an element to the back of a buffer
- ///
- /// # Examples
- ///
- /// ```rust
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::new();
- /// buf.push_back(1);
- /// buf.push_back(3);
- /// assert_eq!(3, *buf.back().unwrap());
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn push_back(&mut self, t: T) {
- if self.is_full() {
- self.reserve(1);
- debug_assert!(!self.is_full());
- }
-
- let head = self.head;
- self.head = self.wrap_index(self.head + 1);
- unsafe { self.buffer_write(head, t) }
- }
-
- /// Removes the last element from a buffer and returns it, or `None` if
- /// it is empty.
- ///
- /// # Examples
- ///
- /// ```rust
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::new();
- /// assert_eq!(buf.pop_back(), None);
- /// buf.push_back(1);
- /// buf.push_back(3);
- /// assert_eq!(buf.pop_back(), Some(3));
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn pop_back(&mut self) -> Option<T> {
- if self.is_empty() {
- None
- } else {
- self.head = self.wrap_index(self.head - 1);
- let head = self.head;
- unsafe { Some(self.buffer_read(head)) }
- }
- }
-
- #[inline]
- fn is_contiguous(&self) -> bool {
- self.tail <= self.head
- }
-
- /// Removes an element from anywhere in the ringbuf and returns it, replacing it with the last
- /// element.
- ///
- /// This does not preserve ordering, but is O(1).
- ///
- /// Returns `None` if `index` is out of bounds.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::new();
- /// assert_eq!(buf.swap_back_remove(0), None);
- /// buf.push_back(5);
- /// buf.push_back(99);
- /// buf.push_back(15);
- /// buf.push_back(20);
- /// buf.push_back(10);
- /// assert_eq!(buf.swap_back_remove(1), Some(99));
- /// ```
- #[unstable(feature = "collections",
- reason = "the naming of this function may be altered")]
- pub fn swap_back_remove(&mut self, index: usize) -> Option<T> {
- let length = self.len();
- if length > 0 && index < length - 1 {
- self.swap(index, length - 1);
- } else if index >= length {
- return None;
- }
- self.pop_back()
- }
-
- /// Removes an element from anywhere in the ringbuf and returns it, replacing it with the first
- /// element.
- ///
- /// This does not preserve ordering, but is O(1).
- ///
- /// Returns `None` if `index` is out of bounds.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::new();
- /// assert_eq!(buf.swap_front_remove(0), None);
- /// buf.push_back(15);
- /// buf.push_back(5);
- /// buf.push_back(10);
- /// buf.push_back(99);
- /// buf.push_back(20);
- /// assert_eq!(buf.swap_front_remove(3), Some(99));
- /// ```
- #[unstable(feature = "collections",
- reason = "the naming of this function may be altered")]
- pub fn swap_front_remove(&mut self, index: usize) -> Option<T> {
- let length = self.len();
- if length > 0 && index < length && index != 0 {
- self.swap(index, 0);
- } else if index >= length {
- return None;
- }
- self.pop_front()
- }
-
- /// Inserts an element at position `i` within the ringbuf. Whichever
- /// end is closer to the insertion point will be moved to make room,
- /// and all the affected elements will be moved to new positions.
- ///
- /// # Panics
- ///
- /// Panics if `i` is greater than ringbuf's length
- ///
- /// # Examples
- /// ```rust
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::new();
- /// buf.push_back(10);
- /// buf.push_back(12);
- /// buf.insert(1,11);
- /// assert_eq!(Some(&11), buf.get(1));
- /// ```
- pub fn insert(&mut self, i: usize, t: T) {
- assert!(i <= self.len(), "index out of bounds");
- if self.is_full() {
- self.reserve(1);
- debug_assert!(!self.is_full());
- }
-
- // Move the least number of elements in the ring buffer and insert
- // the given object
- //
- // At most len/2 - 1 elements will be moved. O(min(n, n-i))
- //
- // There are three main cases:
- // Elements are contiguous
- // - special case when tail is 0
- // Elements are discontiguous and the insert is in the tail section
- // Elements are discontiguous and the insert is in the head section
- //
- // For each of those there are two more cases:
- // Insert is closer to tail
- // Insert is closer to head
- //
- // Key: H - self.head
- // T - self.tail
- // o - Valid element
- // I - Insertion element
- // A - The element that should be after the insertion point
- // M - Indicates element was moved
-
- let idx = self.wrap_index(self.tail + i);
-
- let distance_to_tail = i;
- let distance_to_head = self.len() - i;
-
- let contiguous = self.is_contiguous();
-
- match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
- (true, true, _) if i == 0 => {
- // push_front
- //
- // T
- // I H
- // [A o o o o o o . . . . . . . . .]
- //
- // H T
- // [A o o o o o o o . . . . . I]
- //
-
- self.tail = self.wrap_index(self.tail - 1);
- },
- (true, true, _) => unsafe {
- // contiguous, insert closer to tail:
- //
- // T I H
- // [. . . o o A o o o o . . . . . .]
- //
- // T H
- // [. . o o I A o o o o . . . . . .]
- // M M
- //
- // contiguous, insert closer to tail and tail is 0:
- //
- //
- // T I H
- // [o o A o o o o . . . . . . . . .]
- //
- // H T
- // [o I A o o o o o . . . . . . . o]
- // M M
-
- let new_tail = self.wrap_index(self.tail - 1);
-
- self.copy(new_tail, self.tail, 1);
- // Already moved the tail, so we only copy `i - 1` elements.
- self.copy(self.tail, self.tail + 1, i - 1);
-
- self.tail = new_tail;
- },
- (true, false, _) => unsafe {
- // contiguous, insert closer to head:
- //
- // T I H
- // [. . . o o o o A o o . . . . . .]
- //
- // T H
- // [. . . o o o o I A o o . . . . .]
- // M M M
-
- self.copy(idx + 1, idx, self.head - idx);
- self.head = self.wrap_index(self.head + 1);
- },
- (false, true, true) => unsafe {
- // discontiguous, insert closer to tail, tail section:
- //
- // H T I
- // [o o o o o o . . . . . o o A o o]
- //
- // H T
- // [o o o o o o . . . . o o I A o o]
- // M M
-
- self.copy(self.tail - 1, self.tail, i);
- self.tail -= 1;
- },
- (false, false, true) => unsafe {
- // discontiguous, insert closer to head, tail section:
- //
- // H T I
- // [o o . . . . . . . o o o o o A o]
- //
- // H T
- // [o o o . . . . . . o o o o o I A]
- // M M M M
-
- // copy elements up to new head
- self.copy(1, 0, self.head);
-
- // copy last element into empty spot at bottom of buffer
- self.copy(0, self.cap - 1, 1);
-
- // move elements from idx to end forward not including ^ element
- self.copy(idx + 1, idx, self.cap - 1 - idx);
-
- self.head += 1;
- },
- (false, true, false) if idx == 0 => unsafe {
- // discontiguous, insert is closer to tail, head section,
- // and is at index zero in the internal buffer:
- //
- // I H T
- // [A o o o o o o o o o . . . o o o]
- //
- // H T
- // [A o o o o o o o o o . . o o o I]
- // M M M
-
- // copy elements up to new tail
- self.copy(self.tail - 1, self.tail, self.cap - self.tail);
-
- // copy last element into empty spot at bottom of buffer
- self.copy(self.cap - 1, 0, 1);
-
- self.tail -= 1;
- },
- (false, true, false) => unsafe {
- // discontiguous, insert closer to tail, head section:
- //
- // I H T
- // [o o o A o o o o o o . . . o o o]
- //
- // H T
- // [o o I A o o o o o o . . o o o o]
- // M M M M M M
-
- // copy elements up to new tail
- self.copy(self.tail - 1, self.tail, self.cap - self.tail);
-
- // copy last element into empty spot at bottom of buffer
- self.copy(self.cap - 1, 0, 1);
-
- // move elements from idx-1 to end forward not including ^ element
- self.copy(0, 1, idx - 1);
-
- self.tail -= 1;
- },
- (false, false, false) => unsafe {
- // discontiguous, insert closer to head, head section:
- //
- // I H T
- // [o o o o A o o . . . . . . o o o]
- //
- // H T
- // [o o o o I A o o . . . . . o o o]
- // M M M
-
- self.copy(idx + 1, idx, self.head - idx);
- self.head += 1;
- }
- }
-
- // tail might've been changed so we need to recalculate
- let new_idx = self.wrap_index(self.tail + i);
- unsafe {
- self.buffer_write(new_idx, t);
- }
- }
-
- /// Removes and returns the element at position `i` from the ringbuf.
- /// Whichever end is closer to the removal point will be moved to make
- /// room, and all the affected elements will be moved to new positions.
- /// Returns `None` if `i` is out of bounds.
- ///
- /// # Examples
- /// ```rust
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::new();
- /// buf.push_back(5);
- /// buf.push_back(10);
- /// buf.push_back(12);
- /// buf.push_back(15);
- /// buf.remove(2);
- /// assert_eq!(Some(&15), buf.get(2));
- /// ```
- #[stable(feature = "rust1", since = "1.0.0")]
- pub fn remove(&mut self, i: usize) -> Option<T> {
- if self.is_empty() || self.len() <= i {
- return None;
- }
-
- // There are three main cases:
- // Elements are contiguous
- // Elements are discontiguous and the removal is in the tail section
- // Elements are discontiguous and the removal is in the head section
- // - special case when elements are technically contiguous,
- // but self.head = 0
- //
- // For each of those there are two more cases:
- // Insert is closer to tail
- // Insert is closer to head
- //
- // Key: H - self.head
- // T - self.tail
- // o - Valid element
- // x - Element marked for removal
- // R - Indicates element that is being removed
- // M - Indicates element was moved
-
- let idx = self.wrap_index(self.tail + i);
-
- let elem = unsafe {
- Some(self.buffer_read(idx))
- };
-
- let distance_to_tail = i;
- let distance_to_head = self.len() - i;
-
- let contiguous = self.is_contiguous();
-
- match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
- (true, true, _) => unsafe {
- // contiguous, remove closer to tail:
- //
- // T R H
- // [. . . o o x o o o o . . . . . .]
- //
- // T H
- // [. . . . o o o o o o . . . . . .]
- // M M
-
- self.copy(self.tail + 1, self.tail, i);
- self.tail += 1;
- },
- (true, false, _) => unsafe {
- // contiguous, remove closer to head:
- //
- // T R H
- // [. . . o o o o x o o . . . . . .]
- //
- // T H
- // [. . . o o o o o o . . . . . . .]
- // M M
-
- self.copy(idx, idx + 1, self.head - idx - 1);
- self.head -= 1;
- },
- (false, true, true) => unsafe {
- // discontiguous, remove closer to tail, tail section:
- //
- // H T R
- // [o o o o o o . . . . . o o x o o]
- //
- // H T
- // [o o o o o o . . . . . . o o o o]
- // M M
-
- self.copy(self.tail + 1, self.tail, i);
- self.tail = self.wrap_index(self.tail + 1);
- },
- (false, false, false) => unsafe {
- // discontiguous, remove closer to head, head section:
- //
- // R H T
- // [o o o o x o o . . . . . . o o o]
- //
- // H T
- // [o o o o o o . . . . . . . o o o]
- // M M
-
- self.copy(idx, idx + 1, self.head - idx - 1);
- self.head -= 1;
- },
- (false, false, true) => unsafe {
- // discontiguous, remove closer to head, tail section:
- //
- // H T R
- // [o o o . . . . . . o o o o o x o]
- //
- // H T
- // [o o . . . . . . . o o o o o o o]
- // M M M M
- //
- // or quasi-discontiguous, remove next to head, tail section:
- //
- // H T R
- // [. . . . . . . . . o o o o o x o]
- //
- // T H
- // [. . . . . . . . . o o o o o o .]
- // M
-
- // draw in elements in the tail section
- self.copy(idx, idx + 1, self.cap - idx - 1);
-
- // Prevents underflow.
- if self.head != 0 {
- // copy first element into empty spot
- self.copy(self.cap - 1, 0, 1);
-
- // move elements in the head section backwards
- self.copy(0, 1, self.head - 1);
- }
-
- self.head = self.wrap_index(self.head - 1);
- },
- (false, true, false) => unsafe {
- // discontiguous, remove closer to tail, head section:
- //
- // R H T
- // [o o x o o o o o o o . . . o o o]
- //
- // H T
- // [o o o o o o o o o o . . . . o o]
- // M M M M M
-
- // draw in elements up to idx
- self.copy(1, 0, idx);
-
- // copy last element into empty spot
- self.copy(0, self.cap - 1, 1);
-
- // move elements from tail to end forward, excluding the last one
- self.copy(self.tail + 1, self.tail, self.cap - self.tail - 1);
-
- self.tail = self.wrap_index(self.tail + 1);
- }
- }
-
- return elem;
- }
-
- /// Splits the collection into two at the given index.
- ///
- /// Returns a newly allocated `Self`. `self` contains elements `[0, at)`,
- /// and the returned `Self` contains elements `[at, len)`.
- ///
- /// Note that the capacity of `self` does not change.
- ///
- /// # Panics
- ///
- /// Panics if `at > len`
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut buf: RingBuf<_> = vec![1,2,3].into_iter().collect();
- /// let buf2 = buf.split_off(1);
- /// // buf = [1], buf2 = [2, 3]
- /// assert_eq!(buf.len(), 1);
- /// assert_eq!(buf2.len(), 2);
- /// ```
- #[inline]
- #[unstable(feature = "collections",
- reason = "new API, waiting for dust to settle")]
- pub fn split_off(&mut self, at: usize) -> Self {
- let len = self.len();
- assert!(at <= len, "`at` out of bounds");
-
- let other_len = len - at;
- let mut other = RingBuf::with_capacity(other_len);
-
- unsafe {
- let (first_half, second_half) = self.as_slices();
-
- let first_len = first_half.len();
- let second_len = second_half.len();
- if at < first_len {
- // `at` lies in the first half.
- let amount_in_first = first_len - at;
-
- ptr::copy_nonoverlapping_memory(other.ptr,
- first_half.as_ptr().offset(at as isize),
- amount_in_first);
-
- // just take all of the second half.
- ptr::copy_nonoverlapping_memory(other.ptr.offset(amount_in_first as isize),
- second_half.as_ptr(),
- second_len);
- } else {
- // `at` lies in the second half, need to factor in the elements we skipped
- // in the first half.
- let offset = at - first_len;
- let amount_in_second = second_len - offset;
- ptr::copy_nonoverlapping_memory(other.ptr,
- second_half.as_ptr().offset(offset as isize),
- amount_in_second);
- }
- }
-
- // Cleanup where the ends of the buffers are
- self.head = self.wrap_index(self.head - other_len);
- other.head = other.wrap_index(other_len);
-
- other
- }
-
- /// Moves all the elements of `other` into `Self`, leaving `other` empty.
- ///
- /// # Panics
- ///
- /// Panics if the new number of elements in self overflows a `usize`.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut buf: RingBuf<_> = vec![1, 2, 3].into_iter().collect();
- /// let mut buf2: RingBuf<_> = vec![4, 5, 6].into_iter().collect();
- /// buf.append(&mut buf2);
- /// assert_eq!(buf.len(), 6);
- /// assert_eq!(buf2.len(), 0);
- /// ```
- #[inline]
- #[unstable(feature = "collections",
- reason = "new API, waiting for dust to settle")]
- pub fn append(&mut self, other: &mut Self) {
- // naive impl
- self.extend(other.drain());
- }
-}
-
-impl<T: Clone> RingBuf<T> {
- /// Modifies the ringbuf in-place so that `len()` is equal to new_len,
- /// either by removing excess elements or by appending copies of a value to the back.
- ///
- /// # Examples
- ///
- /// ```
- /// use std::collections::RingBuf;
- ///
- /// let mut buf = RingBuf::new();
- /// buf.push_back(5);
- /// buf.push_back(10);
- /// buf.push_back(15);
- /// buf.resize(2, 0);
- /// buf.resize(6, 20);
- /// for (a, b) in [5, 10, 20, 20, 20, 20].iter().zip(buf.iter()) {
- /// assert_eq!(a, b);
- /// }
- /// ```
- #[unstable(feature = "collections",
- reason = "matches collection reform specification; waiting on panic semantics")]
- pub fn resize(&mut self, new_len: usize, value: T) {
- let len = self.len();
-
- if new_len > len {
- self.extend(repeat(value).take(new_len - len))
- } else {
- self.truncate(new_len);
- }
- }
-}
-
-/// Returns the index in the underlying buffer for a given logical element index.
-#[inline]
-fn wrap_index(index: usize, size: usize) -> usize {
- // size is always a power of 2
- index & (size - 1)
-}
-
-/// Calculate the number of elements left to be read in the buffer
-#[inline]
-fn count(tail: usize, head: usize, size: usize) -> usize {
- // size is always a power of 2
- (head - tail) & (size - 1)
-}
-
-/// `RingBuf` iterator.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Iter<'a, T:'a> {
- ring: &'a [T],
- tail: usize,
- head: usize
-}
-
-// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
-impl<'a, T> Clone for Iter<'a, T> {
- fn clone(&self) -> Iter<'a, T> {
- Iter {
- ring: self.ring,
- tail: self.tail,
- head: self.head
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Iterator for Iter<'a, T> {
- type Item = &'a T;
-
- #[inline]
- fn next(&mut self) -> Option<&'a T> {
- if self.tail == self.head {
- return None;
- }
- let tail = self.tail;
- self.tail = wrap_index(self.tail + 1, self.ring.len());
- unsafe { Some(self.ring.get_unchecked(tail)) }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- let len = count(self.tail, self.head, self.ring.len());
- (len, Some(len))
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
- #[inline]
- fn next_back(&mut self) -> Option<&'a T> {
- if self.tail == self.head {
- return None;
- }
- self.head = wrap_index(self.head - 1, self.ring.len());
- unsafe { Some(self.ring.get_unchecked(self.head)) }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> RandomAccessIterator for Iter<'a, T> {
- #[inline]
- fn indexable(&self) -> usize {
- let (len, _) = self.size_hint();
- len
- }
-
- #[inline]
- fn idx(&mut self, j: usize) -> Option<&'a T> {
- if j >= self.indexable() {
- None
- } else {
- let idx = wrap_index(self.tail + j, self.ring.len());
- unsafe { Some(self.ring.get_unchecked(idx)) }
- }
- }
-}
-
-// FIXME This was implemented differently from Iter because of a problem
-// with returning the mutable reference. I couldn't find a way to
-// make the lifetime checker happy so, but there should be a way.
-/// `RingBuf` mutable iterator.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct IterMut<'a, T:'a> {
- ptr: *mut T,
- tail: usize,
- head: usize,
- cap: usize,
- marker: marker::ContravariantLifetime<'a>,
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> Iterator for IterMut<'a, T> {
- type Item = &'a mut T;
-
- #[inline]
- fn next(&mut self) -> Option<&'a mut T> {
- if self.tail == self.head {
- return None;
- }
- let tail = self.tail;
- self.tail = wrap_index(self.tail + 1, self.cap);
-
- unsafe {
- Some(&mut *self.ptr.offset(tail as isize))
- }
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- let len = count(self.tail, self.head, self.cap);
- (len, Some(len))
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
- #[inline]
- fn next_back(&mut self) -> Option<&'a mut T> {
- if self.tail == self.head {
- return None;
- }
- self.head = wrap_index(self.head - 1, self.cap);
-
- unsafe {
- Some(&mut *self.ptr.offset(self.head as isize))
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
-
-/// A by-value RingBuf iterator
-#[stable(feature = "rust1", since = "1.0.0")]
-pub struct IntoIter<T> {
- inner: RingBuf<T>,
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Iterator for IntoIter<T> {
- type Item = T;
-
- #[inline]
- fn next(&mut self) -> Option<T> {
- self.inner.pop_front()
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- let len = self.inner.len();
- (len, Some(len))
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> DoubleEndedIterator for IntoIter<T> {
- #[inline]
- fn next_back(&mut self) -> Option<T> {
- self.inner.pop_back()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> ExactSizeIterator for IntoIter<T> {}
-
-/// A draining RingBuf iterator
-#[unstable(feature = "collections",
- reason = "matches collection reform specification, waiting for dust to settle")]
-pub struct Drain<'a, T: 'a> {
- inner: &'a mut RingBuf<T>,
-}
-
-#[unsafe_destructor]
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: 'a> Drop for Drain<'a, T> {
- fn drop(&mut self) {
- for _ in self.by_ref() {}
- self.inner.head = 0;
- self.inner.tail = 0;
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: 'a> Iterator for Drain<'a, T> {
- type Item = T;
-
- #[inline]
- fn next(&mut self) -> Option<T> {
- self.inner.pop_front()
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- let len = self.inner.len();
- (len, Some(len))
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
- #[inline]
- fn next_back(&mut self) -> Option<T> {
- self.inner.pop_back()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A: PartialEq> PartialEq for RingBuf<A> {
- fn eq(&self, other: &RingBuf<A>) -> bool {
- self.len() == other.len() &&
- self.iter().zip(other.iter()).all(|(a, b)| a.eq(b))
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Eq> Eq for RingBuf<A> {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A: PartialOrd> PartialOrd for RingBuf<A> {
- fn partial_cmp(&self, other: &RingBuf<A>) -> Option<Ordering> {
- iter::order::partial_cmp(self.iter(), other.iter())
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A: Ord> Ord for RingBuf<A> {
- #[inline]
- fn cmp(&self, other: &RingBuf<A>) -> Ordering {
- iter::order::cmp(self.iter(), other.iter())
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for RingBuf<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")]
-impl<A> Index<usize> for RingBuf<A> {
- type Output = A;
-
- #[inline]
- fn index(&self, i: &usize) -> &A {
- self.get(*i).expect("Out of bounds access")
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A> IndexMut<usize> for RingBuf<A> {
- #[inline]
- fn index_mut(&mut self, i: &usize) -> &mut A {
- self.get_mut(*i).expect("Out of bounds access")
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A> FromIterator<A> for RingBuf<A> {
- fn from_iter<T: Iterator<Item=A>>(iterator: T) -> RingBuf<A> {
- let (lower, _) = iterator.size_hint();
- let mut deq = RingBuf::with_capacity(lower);
- deq.extend(iterator);
- deq
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T> IntoIterator for RingBuf<T> {
- type Item = T;
- type IntoIter = IntoIter<T>;
-
- fn into_iter(self) -> IntoIter<T> {
- self.into_iter()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> IntoIterator for &'a RingBuf<T> {
- type Item = &'a T;
- type IntoIter = Iter<'a, T>;
-
- fn into_iter(self) -> Iter<'a, T> {
- self.iter()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> IntoIterator for &'a mut RingBuf<T> {
- type Item = &'a mut T;
- type IntoIter = IterMut<'a, T>;
-
- fn into_iter(mut self) -> IterMut<'a, T> {
- self.iter_mut()
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<A> Extend<A> for RingBuf<A> {
- fn extend<T: Iterator<Item=A>>(&mut self, iterator: T) {
- for elt in iterator {
- self.push_back(elt);
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: fmt::Debug> fmt::Debug for RingBuf<T> {
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- try!(write!(f, "RingBuf ["));
-
- for (i, e) in self.iter().enumerate() {
- if i != 0 { try!(write!(f, ", ")); }
- try!(write!(f, "{:?}", *e));
- }
-
- write!(f, "]")
- }
-}
-
-#[cfg(test)]
-mod tests {
- use self::Taggy::*;
- use self::Taggypar::*;
- use prelude::*;
- use core::iter;
- use std::fmt::Debug;
- use std::hash::{self, SipHasher};
- use test::Bencher;
- use test;
-
- use super::RingBuf;
-
- #[test]
- #[allow(deprecated)]
- fn test_simple() {
- let mut d = RingBuf::new();
- assert_eq!(d.len(), 0);
- d.push_front(17);
- d.push_front(42);
- d.push_back(137);
- assert_eq!(d.len(), 3);
- d.push_back(137);
- assert_eq!(d.len(), 4);
- assert_eq!(*d.front().unwrap(), 42);
- assert_eq!(*d.back().unwrap(), 137);
- let mut i = d.pop_front();
- assert_eq!(i, Some(42));
- i = d.pop_back();
- assert_eq!(i, Some(137));
- i = d.pop_back();
- assert_eq!(i, Some(137));
- i = d.pop_back();
- assert_eq!(i, Some(17));
- assert_eq!(d.len(), 0);
- d.push_back(3);
- assert_eq!(d.len(), 1);
- d.push_front(2);
- assert_eq!(d.len(), 2);
- d.push_back(4);
- assert_eq!(d.len(), 3);
- d.push_front(1);
- assert_eq!(d.len(), 4);
- debug!("{}", d[0]);
- debug!("{}", d[1]);
- debug!("{}", d[2]);
- debug!("{}", d[3]);
- assert_eq!(d[0], 1);
- assert_eq!(d[1], 2);
- assert_eq!(d[2], 3);
- assert_eq!(d[3], 4);
- }
-
- #[cfg(test)]
- fn test_parameterized<T:Clone + PartialEq + Debug>(a: T, b: T, c: T, d: T) {
- let mut deq = RingBuf::new();
- assert_eq!(deq.len(), 0);
- deq.push_front(a.clone());
- deq.push_front(b.clone());
- deq.push_back(c.clone());
- assert_eq!(deq.len(), 3);
- deq.push_back(d.clone());
- assert_eq!(deq.len(), 4);
- assert_eq!((*deq.front().unwrap()).clone(), b.clone());
- assert_eq!((*deq.back().unwrap()).clone(), d.clone());
- assert_eq!(deq.pop_front().unwrap(), b.clone());
- assert_eq!(deq.pop_back().unwrap(), d.clone());
- assert_eq!(deq.pop_back().unwrap(), c.clone());
- assert_eq!(deq.pop_back().unwrap(), a.clone());
- assert_eq!(deq.len(), 0);
- deq.push_back(c.clone());
- assert_eq!(deq.len(), 1);
- deq.push_front(b.clone());
- assert_eq!(deq.len(), 2);
- deq.push_back(d.clone());
- assert_eq!(deq.len(), 3);
- deq.push_front(a.clone());
- assert_eq!(deq.len(), 4);
- assert_eq!(deq[0].clone(), a.clone());
- assert_eq!(deq[1].clone(), b.clone());
- assert_eq!(deq[2].clone(), c.clone());
- assert_eq!(deq[3].clone(), d.clone());
- }
-
- #[test]
- fn test_push_front_grow() {
- let mut deq = RingBuf::new();
- for i in 0..66 {
- deq.push_front(i);
- }
- assert_eq!(deq.len(), 66);
-
- for i in 0..66 {
- assert_eq!(deq[i], 65 - i);
- }
-
- let mut deq = RingBuf::new();
- for i in 0..66 {
- deq.push_back(i);
- }
-
- for i in 0..66 {
- assert_eq!(deq[i], i);
- }
- }
-
- #[test]
- fn test_index() {
- let mut deq = RingBuf::new();
- for i in 1..4 {
- deq.push_front(i);
- }
- assert_eq!(deq[1], 2);
- }
-
- #[test]
- #[should_fail]
- fn test_index_out_of_bounds() {
- let mut deq = RingBuf::new();
- for i in 1..4 {
- deq.push_front(i);
- }
- deq[3];
- }
-
- #[bench]
- fn bench_new(b: &mut test::Bencher) {
- b.iter(|| {
- let ring: RingBuf<i32> = RingBuf::new();
- test::black_box(ring);
- })
- }
-
- #[bench]
- fn bench_push_back_100(b: &mut test::Bencher) {
- let mut deq = RingBuf::with_capacity(101);
- b.iter(|| {
- for i in 0..100 {
- deq.push_back(i);
- }
- deq.head = 0;
- deq.tail = 0;
- })
- }
-
- #[bench]
- fn bench_push_front_100(b: &mut test::Bencher) {
- let mut deq = RingBuf::with_capacity(101);
- b.iter(|| {
- for i in 0..100 {
- deq.push_front(i);
- }
- deq.head = 0;
- deq.tail = 0;
- })
- }
-
- #[bench]
- fn bench_pop_back_100(b: &mut test::Bencher) {
- let mut deq= RingBuf::<i32>::with_capacity(101);
-
- b.iter(|| {
- deq.head = 100;
- deq.tail = 0;
- while !deq.is_empty() {
- test::black_box(deq.pop_back());
- }
- })
- }
-
- #[bench]
- fn bench_pop_front_100(b: &mut test::Bencher) {
- let mut deq = RingBuf::<i32>::with_capacity(101);
-
- b.iter(|| {
- deq.head = 100;
- deq.tail = 0;
- while !deq.is_empty() {
- test::black_box(deq.pop_front());
- }
- })
- }
-
- #[bench]
- fn bench_grow_1025(b: &mut test::Bencher) {
- b.iter(|| {
- let mut deq = RingBuf::new();
- for i in 0..1025 {
- deq.push_front(i);
- }
- test::black_box(deq);
- })
- }
-
- #[bench]
- fn bench_iter_1000(b: &mut test::Bencher) {
- let ring: RingBuf<_> = (0..1000).collect();
-
- b.iter(|| {
- let mut sum = 0;
- for &i in &ring {
- sum += i;
- }
- test::black_box(sum);
- })
- }
-
- #[bench]
- fn bench_mut_iter_1000(b: &mut test::Bencher) {
- let mut ring: RingBuf<_> = (0..1000).collect();
-
- b.iter(|| {
- let mut sum = 0;
- for i in &mut ring {
- sum += *i;
- }
- test::black_box(sum);
- })
- }
-
- #[derive(Clone, PartialEq, Debug)]
- enum Taggy {
- One(i32),
- Two(i32, i32),
- Three(i32, i32, i32),
- }
-
- #[derive(Clone, PartialEq, Debug)]
- enum Taggypar<T> {
- Onepar(i32),
- Twopar(i32, i32),
- Threepar(i32, i32, i32),
- }
-
- #[derive(Clone, PartialEq, Debug)]
- struct RecCy {
- x: i32,
- y: i32,
- t: Taggy
- }
-
- #[test]
- fn test_param_int() {
- test_parameterized::<i32>(5, 72, 64, 175);
- }
-
- #[test]
- fn test_param_taggy() {
- test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42));
- }
-
- #[test]
- fn test_param_taggypar() {
- test_parameterized::<Taggypar<i32>>(Onepar::<i32>(1),
- Twopar::<i32>(1, 2),
- Threepar::<i32>(1, 2, 3),
- Twopar::<i32>(17, 42));
- }
-
- #[test]
- fn test_param_reccy() {
- let reccy1 = RecCy { x: 1, y: 2, t: One(1) };
- let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) };
- let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) };
- let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) };
- test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4);
- }
-
- #[test]
- fn test_with_capacity() {
- let mut d = RingBuf::with_capacity(0);
- d.push_back(1);
- assert_eq!(d.len(), 1);
- let mut d = RingBuf::with_capacity(50);
- d.push_back(1);
- assert_eq!(d.len(), 1);
- }
-
- #[test]
- fn test_with_capacity_non_power_two() {
- let mut d3 = RingBuf::with_capacity(3);
- d3.push_back(1);
-
- // X = None, | = lo
- // [|1, X, X]
- assert_eq!(d3.pop_front(), Some(1));
- // [X, |X, X]
- assert_eq!(d3.front(), None);
-
- // [X, |3, X]
- d3.push_back(3);
- // [X, |3, 6]
- d3.push_back(6);
- // [X, X, |6]
- assert_eq!(d3.pop_front(), Some(3));
-
- // Pushing the lo past half way point to trigger
- // the 'B' scenario for growth
- // [9, X, |6]
- d3.push_back(9);
- // [9, 12, |6]
- d3.push_back(12);
-
- d3.push_back(15);
- // There used to be a bug here about how the
- // RingBuf made growth assumptions about the
- // underlying Vec which didn't hold and lead
- // to corruption.
- // (Vec grows to next power of two)
- //good- [9, 12, 15, X, X, X, X, |6]
- //bug- [15, 12, X, X, X, |6, X, X]
- assert_eq!(d3.pop_front(), Some(6));
-
- // Which leads us to the following state which
- // would be a failure case.
- //bug- [15, 12, X, X, X, X, |X, X]
- assert_eq!(d3.front(), Some(&9));
- }
-
- #[test]
- fn test_reserve_exact() {
- let mut d = RingBuf::new();
- d.push_back(0);
- d.reserve_exact(50);
- assert!(d.capacity() >= 51);
- }
-
- #[test]
- fn test_reserve() {
- let mut d = RingBuf::new();
- d.push_back(0);
- d.reserve(50);
- assert!(d.capacity() >= 51);
- }
-
- #[test]
- fn test_swap() {
- let mut d: RingBuf<_> = (0..5).collect();
- d.pop_front();
- d.swap(0, 3);
- assert_eq!(d.iter().cloned().collect::<Vec<_>>(), vec!(4, 2, 3, 1));
- }
-
- #[test]
- fn test_iter() {
- let mut d = RingBuf::new();
- assert_eq!(d.iter().next(), None);
- assert_eq!(d.iter().size_hint(), (0, Some(0)));
-
- for i in 0..5 {
- d.push_back(i);
- }
- {
- let b: &[_] = &[&0,&1,&2,&3,&4];
- assert_eq!(d.iter().collect::<Vec<_>>(), b);
- }
-
- for i in 6..9 {
- d.push_front(i);
- }
- {
- let b: &[_] = &[&8,&7,&6,&0,&1,&2,&3,&4];
- assert_eq!(d.iter().collect::<Vec<_>>(), b);
- }
-
- let mut it = d.iter();
- let mut len = d.len();
- loop {
- match it.next() {
- None => break,
- _ => { len -= 1; assert_eq!(it.size_hint(), (len, Some(len))) }
- }
- }
- }
-
- #[test]
- fn test_rev_iter() {
- let mut d = RingBuf::new();
- assert_eq!(d.iter().rev().next(), None);
-
- for i in 0..5 {
- d.push_back(i);
- }
- {
- let b: &[_] = &[&4,&3,&2,&1,&0];
- assert_eq!(d.iter().rev().collect::<Vec<_>>(), b);
- }
-
- for i in 6..9 {
- d.push_front(i);
- }
- let b: &[_] = &[&4,&3,&2,&1,&0,&6,&7,&8];
- assert_eq!(d.iter().rev().collect::<Vec<_>>(), b);
- }
-
- #[test]
- fn test_mut_rev_iter_wrap() {
- let mut d = RingBuf::with_capacity(3);
- assert!(d.iter_mut().rev().next().is_none());
-
- d.push_back(1);
- d.push_back(2);
- d.push_back(3);
- assert_eq!(d.pop_front(), Some(1));
- d.push_back(4);
-
- assert_eq!(d.iter_mut().rev().cloned().collect::<Vec<_>>(),
- vec![4, 3, 2]);
- }
-
- #[test]
- fn test_mut_iter() {
- let mut d = RingBuf::new();
- assert!(d.iter_mut().next().is_none());
-
- for i in 0..3 {
- d.push_front(i);
- }
-
- for (i, elt) in d.iter_mut().enumerate() {
- assert_eq!(*elt, 2 - i);
- *elt = i;
- }
-
- {
- let mut it = d.iter_mut();
- assert_eq!(*it.next().unwrap(), 0);
- assert_eq!(*it.next().unwrap(), 1);
- assert_eq!(*it.next().unwrap(), 2);
- assert!(it.next().is_none());
- }
- }
-
- #[test]
- fn test_mut_rev_iter() {
- let mut d = RingBuf::new();
- assert!(d.iter_mut().rev().next().is_none());
-
- for i in 0..3 {
- d.push_front(i);
- }
-
- for (i, elt) in d.iter_mut().rev().enumerate() {
- assert_eq!(*elt, i);
- *elt = i;
- }
-
- {
- let mut it = d.iter_mut().rev();
- assert_eq!(*it.next().unwrap(), 0);
- assert_eq!(*it.next().unwrap(), 1);
- assert_eq!(*it.next().unwrap(), 2);
- assert!(it.next().is_none());
- }
- }
-
- #[test]
- fn test_into_iter() {
-
- // Empty iter
- {
- let d: RingBuf<i32> = RingBuf::new();
- let mut iter = d.into_iter();
-
- assert_eq!(iter.size_hint(), (0, Some(0)));
- assert_eq!(iter.next(), None);
- assert_eq!(iter.size_hint(), (0, Some(0)));
- }
-
- // simple iter
- {
- let mut d = RingBuf::new();
- for i in 0..5 {
- d.push_back(i);
- }
-
- let b = vec![0,1,2,3,4];
- assert_eq!(d.into_iter().collect::<Vec<_>>(), b);
- }
-
- // wrapped iter
- {
- let mut d = RingBuf::new();
- for i in 0..5 {
- d.push_back(i);
- }
- for i in 6..9 {
- d.push_front(i);
- }
-
- let b = vec![8,7,6,0,1,2,3,4];
- assert_eq!(d.into_iter().collect::<Vec<_>>(), b);
- }
-
- // partially used
- {
- let mut d = RingBuf::new();
- for i in 0..5 {
- d.push_back(i);
- }
- for i in 6..9 {
- d.push_front(i);
- }
-
- let mut it = d.into_iter();
- assert_eq!(it.size_hint(), (8, Some(8)));
- assert_eq!(it.next(), Some(8));
- assert_eq!(it.size_hint(), (7, Some(7)));
- assert_eq!(it.next_back(), Some(4));
- assert_eq!(it.size_hint(), (6, Some(6)));
- assert_eq!(it.next(), Some(7));
- assert_eq!(it.size_hint(), (5, Some(5)));
- }
- }
-
- #[test]
- fn test_drain() {
-
- // Empty iter
- {
- let mut d: RingBuf<i32> = RingBuf::new();
-
- {
- let mut iter = d.drain();
-
- assert_eq!(iter.size_hint(), (0, Some(0)));
- assert_eq!(iter.next(), None);
- assert_eq!(iter.size_hint(), (0, Some(0)));
- }
-
- assert!(d.is_empty());
- }
-
- // simple iter
- {
- let mut d = RingBuf::new();
- for i in 0..5 {
- d.push_back(i);
- }
-
- assert_eq!(d.drain().collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
- assert!(d.is_empty());
- }
-
- // wrapped iter
- {
- let mut d = RingBuf::new();
- for i in 0..5 {
- d.push_back(i);
- }
- for i in 6..9 {
- d.push_front(i);
- }
-
- assert_eq!(d.drain().collect::<Vec<_>>(), [8,7,6,0,1,2,3,4]);
- assert!(d.is_empty());
- }
-
- // partially used
- {
- let mut d: RingBuf<_> = RingBuf::new();
- for i in 0..5 {
- d.push_back(i);
- }
- for i in 6..9 {
- d.push_front(i);
- }
-
- {
- let mut it = d.drain();
- assert_eq!(it.size_hint(), (8, Some(8)));
- assert_eq!(it.next(), Some(8));
- assert_eq!(it.size_hint(), (7, Some(7)));
- assert_eq!(it.next_back(), Some(4));
- assert_eq!(it.size_hint(), (6, Some(6)));
- assert_eq!(it.next(), Some(7));
- assert_eq!(it.size_hint(), (5, Some(5)));
- }
- assert!(d.is_empty());
- }
- }
-
- #[test]
- fn test_from_iter() {
- use core::iter;
- let v = vec!(1,2,3,4,5,6,7);
- let deq: RingBuf<_> = v.iter().cloned().collect();
- let u: Vec<_> = deq.iter().cloned().collect();
- assert_eq!(u, v);
-
- let seq = iter::count(0, 2).take(256);
- let deq: RingBuf<_> = seq.collect();
- for (i, &x) in deq.iter().enumerate() {
- assert_eq!(2*i, x);
- }
- assert_eq!(deq.len(), 256);
- }
-
- #[test]
- fn test_clone() {
- let mut d = RingBuf::new();
- d.push_front(17);
- d.push_front(42);
- d.push_back(137);
- d.push_back(137);
- assert_eq!(d.len(), 4);
- let mut e = d.clone();
- assert_eq!(e.len(), 4);
- while !d.is_empty() {
- assert_eq!(d.pop_back(), e.pop_back());
- }
- assert_eq!(d.len(), 0);
- assert_eq!(e.len(), 0);
- }
-
- #[test]
- fn test_eq() {
- let mut d = RingBuf::new();
- assert!(d == RingBuf::with_capacity(0));
- d.push_front(137);
- d.push_front(17);
- d.push_front(42);
- d.push_back(137);
- let mut e = RingBuf::with_capacity(0);
- e.push_back(42);
- e.push_back(17);
- e.push_back(137);
- e.push_back(137);
- assert!(&e == &d);
- e.pop_back();
- e.push_back(0);
- assert!(e != d);
- e.clear();
- assert!(e == RingBuf::new());
- }
-
- #[test]
- fn test_hash() {
- let mut x = RingBuf::new();
- let mut y = RingBuf::new();
-
- x.push_back(1);
- x.push_back(2);
- x.push_back(3);
-
- y.push_back(0);
- y.push_back(1);
- y.pop_front();
- y.push_back(2);
- y.push_back(3);
-
- assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y));
- }
-
- #[test]
- fn test_ord() {
- let x = RingBuf::new();
- let mut y = RingBuf::new();
- y.push_back(1);
- y.push_back(2);
- y.push_back(3);
- assert!(x < y);
- assert!(y > x);
- assert!(x <= x);
- assert!(x >= x);
- }
-
- #[test]
- fn test_show() {
- let ringbuf: RingBuf<_> = (0..10).collect();
- assert_eq!(format!("{:?}", ringbuf), "RingBuf [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
-
- let ringbuf: RingBuf<_> = vec!["just", "one", "test", "more"].iter()
- .cloned()
- .collect();
- assert_eq!(format!("{:?}", ringbuf), "RingBuf [\"just\", \"one\", \"test\", \"more\"]");
- }
-
- #[test]
- fn test_drop() {
- static mut drops: i32 = 0;
- struct Elem;
- impl Drop for Elem {
- fn drop(&mut self) {
- unsafe { drops += 1; }
- }
- }
-
- let mut ring = RingBuf::new();
- ring.push_back(Elem);
- ring.push_front(Elem);
- ring.push_back(Elem);
- ring.push_front(Elem);
- drop(ring);
-
- assert_eq!(unsafe {drops}, 4);
- }
-
- #[test]
- fn test_drop_with_pop() {
- static mut drops: i32 = 0;
- struct Elem;
- impl Drop for Elem {
- fn drop(&mut self) {
- unsafe { drops += 1; }
- }
- }
-
- let mut ring = RingBuf::new();
- ring.push_back(Elem);
- ring.push_front(Elem);
- ring.push_back(Elem);
- ring.push_front(Elem);
-
- drop(ring.pop_back());
- drop(ring.pop_front());
- assert_eq!(unsafe {drops}, 2);
-
- drop(ring);
- assert_eq!(unsafe {drops}, 4);
- }
-
- #[test]
- fn test_drop_clear() {
- static mut drops: i32 = 0;
- struct Elem;
- impl Drop for Elem {
- fn drop(&mut self) {
- unsafe { drops += 1; }
- }
- }
-
- let mut ring = RingBuf::new();
- ring.push_back(Elem);
- ring.push_front(Elem);
- ring.push_back(Elem);
- ring.push_front(Elem);
- ring.clear();
- assert_eq!(unsafe {drops}, 4);
-
- drop(ring);
- assert_eq!(unsafe {drops}, 4);
- }
-
- #[test]
- fn test_reserve_grow() {
- // test growth path A
- // [T o o H] -> [T o o H . . . . ]
- let mut ring = RingBuf::with_capacity(4);
- for i in 0..3 {
- ring.push_back(i);
- }
- ring.reserve(7);
- for i in 0..3 {
- assert_eq!(ring.pop_front(), Some(i));
- }
-
- // test growth path B
- // [H T o o] -> [. T o o H . . . ]
- let mut ring = RingBuf::with_capacity(4);
- for i in 0..1 {
- ring.push_back(i);
- assert_eq!(ring.pop_front(), Some(i));
- }
- for i in 0..3 {
- ring.push_back(i);
- }
- ring.reserve(7);
- for i in 0..3 {
- assert_eq!(ring.pop_front(), Some(i));
- }
-
- // test growth path C
- // [o o H T] -> [o o H . . . . T ]
- let mut ring = RingBuf::with_capacity(4);
- for i in 0..3 {
- ring.push_back(i);
- assert_eq!(ring.pop_front(), Some(i));
- }
- for i in 0..3 {
- ring.push_back(i);
- }
- ring.reserve(7);
- for i in 0..3 {
- assert_eq!(ring.pop_front(), Some(i));
- }
- }
-
- #[test]
- fn test_get() {
- let mut ring = RingBuf::new();
- ring.push_back(0);
- assert_eq!(ring.get(0), Some(&0));
- assert_eq!(ring.get(1), None);
-
- ring.push_back(1);
- assert_eq!(ring.get(0), Some(&0));
- assert_eq!(ring.get(1), Some(&1));
- assert_eq!(ring.get(2), None);
-
- ring.push_back(2);
- assert_eq!(ring.get(0), Some(&0));
- assert_eq!(ring.get(1), Some(&1));
- assert_eq!(ring.get(2), Some(&2));
- assert_eq!(ring.get(3), None);
-
- assert_eq!(ring.pop_front(), Some(0));
- assert_eq!(ring.get(0), Some(&1));
- assert_eq!(ring.get(1), Some(&2));
- assert_eq!(ring.get(2), None);
-
- assert_eq!(ring.pop_front(), Some(1));
- assert_eq!(ring.get(0), Some(&2));
- assert_eq!(ring.get(1), None);
-
- assert_eq!(ring.pop_front(), Some(2));
- assert_eq!(ring.get(0), None);
- assert_eq!(ring.get(1), None);
- }
-
- #[test]
- fn test_get_mut() {
- let mut ring = RingBuf::new();
- for i in 0..3 {
- ring.push_back(i);
- }
-
- match ring.get_mut(1) {
- Some(x) => *x = -1,
- None => ()
- };
-
- assert_eq!(ring.get_mut(0), Some(&mut 0));
- assert_eq!(ring.get_mut(1), Some(&mut -1));
- assert_eq!(ring.get_mut(2), Some(&mut 2));
- assert_eq!(ring.get_mut(3), None);
-
- assert_eq!(ring.pop_front(), Some(0));
- assert_eq!(ring.get_mut(0), Some(&mut -1));
- assert_eq!(ring.get_mut(1), Some(&mut 2));
- assert_eq!(ring.get_mut(2), None);
- }
-
- #[test]
- fn test_swap_front_back_remove() {
- fn test(back: bool) {
- // This test checks that every single combination of tail position and length is tested.
- // Capacity 15 should be large enough to cover every case.
- let mut tester = RingBuf::with_capacity(15);
- let usable_cap = tester.capacity();
- let final_len = usable_cap / 2;
-
- for len in 0..final_len {
- let expected = if back {
- (0..len).collect()
- } else {
- (0..len).rev().collect()
- };
- for tail_pos in 0..usable_cap {
- tester.tail = tail_pos;
- tester.head = tail_pos;
- if back {
- for i in 0..len * 2 {
- tester.push_front(i);
- }
- for i in 0..len {
- assert_eq!(tester.swap_back_remove(i), Some(len * 2 - 1 - i));
- }
- } else {
- for i in 0..len * 2 {
- tester.push_back(i);
- }
- for i in 0..len {
- let idx = tester.len() - 1 - i;
- assert_eq!(tester.swap_front_remove(idx), Some(len * 2 - 1 - i));
- }
- }
- assert!(tester.tail < tester.cap);
- assert!(tester.head < tester.cap);
- assert_eq!(tester, expected);
- }
- }
- }
- test(true);
- test(false);
- }
-
- #[test]
- fn test_insert() {
- // This test checks that every single combination of tail position, length, and
- // insertion position is tested. Capacity 15 should be large enough to cover every case.
-
- let mut tester = RingBuf::with_capacity(15);
- // can't guarantee we got 15, so have to get what we got.
- // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
- // this test isn't covering what it wants to
- let cap = tester.capacity();
-
-
- // len is the length *after* insertion
- for len in 1..cap {
- // 0, 1, 2, .., len - 1
- let expected = iter::count(0, 1).take(len).collect();
- for tail_pos in 0..cap {
- for to_insert in 0..len {
- tester.tail = tail_pos;
- tester.head = tail_pos;
- for i in 0..len {
- if i != to_insert {
- tester.push_back(i);
- }
- }
- tester.insert(to_insert, to_insert);
- assert!(tester.tail < tester.cap);
- assert!(tester.head < tester.cap);
- assert_eq!(tester, expected);
- }
- }
- }
- }
-
- #[test]
- fn test_remove() {
- // This test checks that every single combination of tail position, length, and
- // removal position is tested. Capacity 15 should be large enough to cover every case.
-
- let mut tester = RingBuf::with_capacity(15);
- // can't guarantee we got 15, so have to get what we got.
- // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
- // this test isn't covering what it wants to
- let cap = tester.capacity();
-
- // len is the length *after* removal
- for len in 0..cap - 1 {
- // 0, 1, 2, .., len - 1
- let expected = iter::count(0, 1).take(len).collect();
- for tail_pos in 0..cap {
- for to_remove in 0..len + 1 {
- tester.tail = tail_pos;
- tester.head = tail_pos;
- for i in 0..len {
- if i == to_remove {
- tester.push_back(1234);
- }
- tester.push_back(i);
- }
- if to_remove == len {
- tester.push_back(1234);
- }
- tester.remove(to_remove);
- assert!(tester.tail < tester.cap);
- assert!(tester.head < tester.cap);
- assert_eq!(tester, expected);
- }
- }
- }
- }
-
- #[test]
- fn test_shrink_to_fit() {
- // This test checks that every single combination of head and tail position,
- // is tested. Capacity 15 should be large enough to cover every case.
-
- let mut tester = RingBuf::with_capacity(15);
- // can't guarantee we got 15, so have to get what we got.
- // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
- // this test isn't covering what it wants to
- let cap = tester.capacity();
- tester.reserve(63);
- let max_cap = tester.capacity();
-
- for len in 0..cap + 1 {
- // 0, 1, 2, .., len - 1
- let expected = iter::count(0, 1).take(len).collect();
- for tail_pos in 0..max_cap + 1 {
- tester.tail = tail_pos;
- tester.head = tail_pos;
- tester.reserve(63);
- for i in 0..len {
- tester.push_back(i);
- }
- tester.shrink_to_fit();
- assert!(tester.capacity() <= cap);
- assert!(tester.tail < tester.cap);
- assert!(tester.head < tester.cap);
- assert_eq!(tester, expected);
- }
- }
- }
-
- #[test]
- fn test_front() {
- let mut ring = RingBuf::new();
- ring.push_back(10);
- ring.push_back(20);
- assert_eq!(ring.front(), Some(&10));
- ring.pop_front();
- assert_eq!(ring.front(), Some(&20));
- ring.pop_front();
- assert_eq!(ring.front(), None);
- }
-
- #[test]
- fn test_as_slices() {
- let mut ring: RingBuf<i32> = RingBuf::with_capacity(127);
- let cap = ring.capacity() as i32;
- let first = cap/2;
- let last = cap - first;
- for i in 0..first {
- ring.push_back(i);
-
- let (left, right) = ring.as_slices();
- let expected: Vec<_> = (0..i+1).collect();
- assert_eq!(left, expected);
- assert_eq!(right, []);
- }
-
- for j in -last..0 {
- ring.push_front(j);
- let (left, right) = ring.as_slices();
- let expected_left: Vec<_> = (-last..j+1).rev().collect();
- let expected_right: Vec<_> = (0..first).collect();
- assert_eq!(left, expected_left);
- assert_eq!(right, expected_right);
- }
-
- assert_eq!(ring.len() as i32, cap);
- assert_eq!(ring.capacity() as i32, cap);
- }
-
- #[test]
- fn test_as_mut_slices() {
- let mut ring: RingBuf<i32> = RingBuf::with_capacity(127);
- let cap = ring.capacity() as i32;
- let first = cap/2;
- let last = cap - first;
- for i in 0..first {
- ring.push_back(i);
-
- let (left, right) = ring.as_mut_slices();
- let expected: Vec<_> = (0..i+1).collect();
- assert_eq!(left, expected);
- assert_eq!(right, []);
- }
-
- for j in -last..0 {
- ring.push_front(j);
- let (left, right) = ring.as_mut_slices();
- let expected_left: Vec<_> = (-last..j+1).rev().collect();
- let expected_right: Vec<_> = (0..first).collect();
- assert_eq!(left, expected_left);
- assert_eq!(right, expected_right);
- }
-
- assert_eq!(ring.len() as i32, cap);
- assert_eq!(ring.capacity() as i32, cap);
- }
-
- #[test]
- fn test_split_off() {
- // This test checks that every single combination of tail position, length, and
- // split position is tested. Capacity 15 should be large enough to cover every case.
-
- let mut tester = RingBuf::with_capacity(15);
- // can't guarantee we got 15, so have to get what we got.
- // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
- // this test isn't covering what it wants to
- let cap = tester.capacity();
-
- // len is the length *before* splitting
- for len in 0..cap {
- // index to split at
- for at in 0..len + 1 {
- // 0, 1, 2, .., at - 1 (may be empty)
- let expected_self = iter::count(0, 1).take(at).collect();
- // at, at + 1, .., len - 1 (may be empty)
- let expected_other = iter::count(at, 1).take(len - at).collect();
-
- for tail_pos in 0..cap {
- tester.tail = tail_pos;
- tester.head = tail_pos;
- for i in 0..len {
- tester.push_back(i);
- }
- let result = tester.split_off(at);
- assert!(tester.tail < tester.cap);
- assert!(tester.head < tester.cap);
- assert!(result.tail < result.cap);
- assert!(result.head < result.cap);
- assert_eq!(tester, expected_self);
- assert_eq!(result, expected_other);
- }
- }
- }
- }
-
- #[test]
- fn test_append() {
- let mut a: RingBuf<_> = vec![1, 2, 3].into_iter().collect();
- let mut b: RingBuf<_> = vec![4, 5, 6].into_iter().collect();
-
- // normal append
- a.append(&mut b);
- assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
- assert_eq!(b.iter().cloned().collect(), vec![]);
-
- // append nothing to something
- a.append(&mut b);
- assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
- assert_eq!(b.iter().cloned().collect(), vec![]);
-
- // append something to nothing
- b.append(&mut a);
- assert_eq!(b.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
- assert_eq!(a.iter().cloned().collect(), vec![]);
- }
-}
#![stable(feature = "rust1", since = "1.0.0")]
use alloc::boxed::Box;
-use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned};
use core::clone::Clone;
use core::cmp::Ordering::{self, Greater, Less};
use core::cmp::{self, Ord, PartialEq};
use core::slice as core_slice;
use self::Direction::*;
+use borrow::{Borrow, BorrowMut, ToOwned};
use vec::Vec;
pub use core::slice::{Chunks, AsSlice, Windows};
// Standard trait implementations for slices
////////////////////////////////////////////////////////////////////////////////
-#[unstable(feature = "collections", reason = "trait is unstable")]
-impl<T> BorrowFrom<Vec<T>> for [T] {
- fn borrow_from(owned: &Vec<T>) -> &[T] { &owned[] }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> Borrow<[T]> for Vec<T> {
+ fn borrow(&self) -> &[T] { &self[..] }
}
-#[unstable(feature = "collections", reason = "trait is unstable")]
-impl<T> BorrowFromMut<Vec<T>> for [T] {
- fn borrow_from_mut(owned: &mut Vec<T>) -> &mut [T] { &mut owned[] }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> BorrowMut<[T]> for Vec<T> {
+ fn borrow_mut(&mut self) -> &mut [T] { &mut self[..] }
}
-#[unstable(feature = "collections", reason = "trait is unstable")]
-impl<T: Clone> ToOwned<Vec<T>> for [T] {
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Clone> ToOwned for [T] {
+ type Owned = Vec<T>;
fn to_owned(&self) -> Vec<T> { self.to_vec() }
}
#[test]
fn test_slice_from() {
let vec: &[_] = &[1, 2, 3, 4];
- assert_eq!(&vec[], vec);
+ assert_eq!(&vec[..], vec);
let b: &[_] = &[3, 4];
assert_eq!(&vec[2..], b);
let b: &[_] = &[];
#[test]
fn test_total_ord() {
let c = &[1, 2, 3];
- [1, 2, 3, 4][].cmp(c) == Greater;
+ [1, 2, 3, 4][..].cmp(c) == Greater;
let c = &[1, 2, 3, 4];
- [1, 2, 3][].cmp(c) == Less;
+ [1, 2, 3][..].cmp(c) == Less;
let c = &[1, 2, 3, 6];
- [1, 2, 3, 4][].cmp(c) == Equal;
+ [1, 2, 3, 4][..].cmp(c) == Equal;
let c = &[1, 2, 3, 4, 5, 6];
- [1, 2, 3, 4, 5, 5, 5, 5][].cmp(c) == Less;
+ [1, 2, 3, 4, 5, 5, 5, 5][..].cmp(c) == Less;
let c = &[1, 2, 3, 4];
- [2, 2][].cmp(c) == Greater;
+ [2, 2][..].cmp(c) == Greater;
}
#[test]
use self::RecompositionState::*;
use self::DecompositionType::*;
-use core::borrow::{BorrowFrom, ToOwned};
use core::char::CharExt;
use core::clone::Clone;
use core::iter::AdditiveIterator;
use core::str as core_str;
use unicode::str::{UnicodeStr, Utf16Encoder};
-use ring_buf::RingBuf;
+use vec_deque::VecDeque;
+use borrow::{Borrow, ToOwned};
use slice::SliceExt;
use string::String;
use unicode;
pub struct Recompositions<'a> {
iter: Decompositions<'a>,
state: RecompositionState,
- buffer: RingBuf<char>,
+ buffer: VecDeque<char>,
composee: Option<char>,
last_ccc: Option<u8>
}
($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63u8) as u32)
}
-#[unstable(feature = "collections", reason = "trait is unstable")]
-impl BorrowFrom<String> for str {
- fn borrow_from(owned: &String) -> &str { &owned[] }
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Borrow<str> for String {
+ fn borrow(&self) -> &str { &self[..] }
}
-#[unstable(feature = "collections", reason = "trait is unstable")]
-impl ToOwned<String> for str {
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ToOwned for str {
+ type Owned = String;
fn to_owned(&self) -> String {
unsafe {
String::from_utf8_unchecked(self.as_bytes().to_owned())
reason = "this functionality may be moved to libunicode")]
fn nfd_chars(&self) -> Decompositions {
Decompositions {
- iter: self[].chars(),
+ iter: self[..].chars(),
buffer: Vec::new(),
sorted: false,
kind: Canonical
reason = "this functionality may be moved to libunicode")]
fn nfkd_chars(&self) -> Decompositions {
Decompositions {
- iter: self[].chars(),
+ iter: self[..].chars(),
buffer: Vec::new(),
sorted: false,
kind: Compatible
Recompositions {
iter: self.nfd_chars(),
state: Composing,
- buffer: RingBuf::new(),
+ buffer: VecDeque::new(),
composee: None,
last_ccc: None
}
Recompositions {
iter: self.nfkd_chars(),
state: Composing,
- buffer: RingBuf::new(),
+ buffer: VecDeque::new(),
composee: None,
last_ccc: None
}
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn contains(&self, pat: &str) -> bool {
- core_str::StrExt::contains(&self[], pat)
+ core_str::StrExt::contains(&self[..], pat)
}
/// Returns true if a string contains a char pattern.
#[unstable(feature = "collections",
reason = "might get removed in favour of a more generic contains()")]
fn contains_char<P: CharEq>(&self, pat: P) -> bool {
- core_str::StrExt::contains_char(&self[], pat)
+ core_str::StrExt::contains_char(&self[..], pat)
}
/// An iterator over the characters of `self`. Note, this iterates
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn chars(&self) -> Chars {
- core_str::StrExt::chars(&self[])
+ core_str::StrExt::chars(&self[..])
}
/// An iterator over the bytes of `self`
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn bytes(&self) -> Bytes {
- core_str::StrExt::bytes(&self[])
+ core_str::StrExt::bytes(&self[..])
}
/// An iterator over the characters of `self` and their byte offsets.
#[stable(feature = "rust1", since = "1.0.0")]
fn char_indices(&self) -> CharIndices {
- core_str::StrExt::char_indices(&self[])
+ core_str::StrExt::char_indices(&self[..])
}
/// An iterator over substrings of `self`, separated by characters
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn split<P: CharEq>(&self, pat: P) -> Split<P> {
- core_str::StrExt::split(&self[], pat)
+ core_str::StrExt::split(&self[..], pat)
}
/// An iterator over substrings of `self`, separated by characters
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn splitn<P: CharEq>(&self, count: usize, pat: P) -> SplitN<P> {
- core_str::StrExt::splitn(&self[], count, pat)
+ core_str::StrExt::splitn(&self[..], count, pat)
}
/// An iterator over substrings of `self`, separated by characters
/// ```
#[unstable(feature = "collections", reason = "might get removed")]
fn split_terminator<P: CharEq>(&self, pat: P) -> SplitTerminator<P> {
- core_str::StrExt::split_terminator(&self[], pat)
+ core_str::StrExt::split_terminator(&self[..], pat)
}
/// An iterator over substrings of `self`, separated by characters
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn rsplitn<P: CharEq>(&self, count: usize, pat: P) -> RSplitN<P> {
- core_str::StrExt::rsplitn(&self[], count, pat)
+ core_str::StrExt::rsplitn(&self[..], count, pat)
}
/// An iterator over the start and end indices of the disjoint
#[unstable(feature = "collections",
reason = "might have its iterator type changed")]
fn match_indices<'a>(&'a self, pat: &'a str) -> MatchIndices<'a> {
- core_str::StrExt::match_indices(&self[], pat)
+ core_str::StrExt::match_indices(&self[..], pat)
}
/// An iterator over the substrings of `self` separated by the pattern `sep`.
#[unstable(feature = "collections",
reason = "might get removed in the future in favor of a more generic split()")]
fn split_str<'a>(&'a self, pat: &'a str) -> SplitStr<'a> {
- core_str::StrExt::split_str(&self[], pat)
+ core_str::StrExt::split_str(&self[..], pat)
}
/// An iterator over the lines of a string (subsequences separated
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn lines(&self) -> Lines {
- core_str::StrExt::lines(&self[])
+ core_str::StrExt::lines(&self[..])
}
/// An iterator over the lines of a string, separated by either
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn lines_any(&self) -> LinesAny {
- core_str::StrExt::lines_any(&self[])
+ core_str::StrExt::lines_any(&self[..])
}
/// Deprecated: use `s[a .. b]` instead.
#[unstable(feature = "collections",
reason = "may have yet to prove its worth")]
fn slice_chars(&self, begin: usize, end: usize) -> &str {
- core_str::StrExt::slice_chars(&self[], begin, end)
+ core_str::StrExt::slice_chars(&self[..], begin, end)
}
/// Takes a bytewise (not UTF-8) slice from a string.
/// the entire slice as well.
#[stable(feature = "rust1", since = "1.0.0")]
unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
- core_str::StrExt::slice_unchecked(&self[], begin, end)
+ core_str::StrExt::slice_unchecked(&self[..], begin, end)
}
/// Returns true if the pattern `pat` is a prefix of the string.
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn starts_with(&self, pat: &str) -> bool {
- core_str::StrExt::starts_with(&self[], pat)
+ core_str::StrExt::starts_with(&self[..], pat)
}
/// Returns true if the pattern `pat` is a suffix of the string.
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn ends_with(&self, pat: &str) -> bool {
- core_str::StrExt::ends_with(&self[], pat)
+ core_str::StrExt::ends_with(&self[..], pat)
}
/// Returns a string with all pre- and suffixes that match
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn trim_matches<P: CharEq>(&self, pat: P) -> &str {
- core_str::StrExt::trim_matches(&self[], pat)
+ core_str::StrExt::trim_matches(&self[..], pat)
}
/// Returns a string with all prefixes that match
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn trim_left_matches<P: CharEq>(&self, pat: P) -> &str {
- core_str::StrExt::trim_left_matches(&self[], pat)
+ core_str::StrExt::trim_left_matches(&self[..], pat)
}
/// Returns a string with all suffixes that match
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn trim_right_matches<P: CharEq>(&self, pat: P) -> &str {
- core_str::StrExt::trim_right_matches(&self[], pat)
+ core_str::StrExt::trim_right_matches(&self[..], pat)
}
/// Check that `index`-th byte lies at the start and/or end of a
#[unstable(feature = "collections",
reason = "naming is uncertain with container conventions")]
fn is_char_boundary(&self, index: usize) -> bool {
- core_str::StrExt::is_char_boundary(&self[], index)
+ core_str::StrExt::is_char_boundary(&self[..], index)
}
/// Pluck a character out of a string and return the index of the next
#[unstable(feature = "collections",
reason = "naming is uncertain with container conventions")]
fn char_range_at(&self, start: usize) -> CharRange {
- core_str::StrExt::char_range_at(&self[], start)
+ core_str::StrExt::char_range_at(&self[..], start)
}
/// Given a byte position and a str, return the previous char and its position.
#[unstable(feature = "collections",
reason = "naming is uncertain with container conventions")]
fn char_range_at_reverse(&self, start: usize) -> CharRange {
- core_str::StrExt::char_range_at_reverse(&self[], start)
+ core_str::StrExt::char_range_at_reverse(&self[..], start)
}
/// Plucks the character starting at the `i`th byte of a string.
#[unstable(feature = "collections",
reason = "naming is uncertain with container conventions")]
fn char_at(&self, i: usize) -> char {
- core_str::StrExt::char_at(&self[], i)
+ core_str::StrExt::char_at(&self[..], i)
}
/// Plucks the character ending at the `i`th byte of a string.
#[unstable(feature = "collections",
reason = "naming is uncertain with container conventions")]
fn char_at_reverse(&self, i: usize) -> char {
- core_str::StrExt::char_at_reverse(&self[], i)
+ core_str::StrExt::char_at_reverse(&self[..], i)
}
/// Work with the byte buffer of a string as a byte slice.
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn as_bytes(&self) -> &[u8] {
- core_str::StrExt::as_bytes(&self[])
+ core_str::StrExt::as_bytes(&self[..])
}
/// Returns the byte index of the first character of `self` that
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn find<P: CharEq>(&self, pat: P) -> Option<usize> {
- core_str::StrExt::find(&self[], pat)
+ core_str::StrExt::find(&self[..], pat)
}
/// Returns the byte index of the last character of `self` that
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn rfind<P: CharEq>(&self, pat: P) -> Option<usize> {
- core_str::StrExt::rfind(&self[], pat)
+ core_str::StrExt::rfind(&self[..], pat)
}
/// Returns the byte index of the first matching substring
#[unstable(feature = "collections",
reason = "might get removed in favor of a more generic find in the future")]
fn find_str(&self, needle: &str) -> Option<usize> {
- core_str::StrExt::find_str(&self[], needle)
+ core_str::StrExt::find_str(&self[..], needle)
}
/// Retrieves the first character from a string slice and returns
#[unstable(feature = "collections",
reason = "awaiting conventions about shifting and slices")]
fn slice_shift_char(&self) -> Option<(char, &str)> {
- core_str::StrExt::slice_shift_char(&self[])
+ core_str::StrExt::slice_shift_char(&self[..])
}
/// Returns the byte offset of an inner slice relative to an enclosing outer slice.
#[unstable(feature = "collections",
reason = "awaiting convention about comparability of arbitrary slices")]
fn subslice_offset(&self, inner: &str) -> usize {
- core_str::StrExt::subslice_offset(&self[], inner)
+ core_str::StrExt::subslice_offset(&self[..], inner)
}
/// Return an unsafe pointer to the strings buffer.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
fn as_ptr(&self) -> *const u8 {
- core_str::StrExt::as_ptr(&self[])
+ core_str::StrExt::as_ptr(&self[..])
}
/// Return an iterator of `u16` over the string encoded as UTF-16.
#[unstable(feature = "collections",
reason = "this functionality may only be provided by libunicode")]
fn utf16_units(&self) -> Utf16Units {
- Utf16Units { encoder: Utf16Encoder::new(self[].chars()) }
+ Utf16Units { encoder: Utf16Encoder::new(self[..].chars()) }
}
/// Return the number of bytes in this string
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
fn len(&self) -> usize {
- core_str::StrExt::len(&self[])
+ core_str::StrExt::len(&self[..])
}
/// Returns true if this slice contains no bytes
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn is_empty(&self) -> bool {
- core_str::StrExt::is_empty(&self[])
+ core_str::StrExt::is_empty(&self[..])
}
/// Parse this string into the specified type.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
- core_str::StrExt::parse(&self[])
+ core_str::StrExt::parse(&self[..])
}
/// Returns an iterator over the
#[unstable(feature = "collections",
reason = "this functionality may only be provided by libunicode")]
fn graphemes(&self, is_extended: bool) -> Graphemes {
- UnicodeStr::graphemes(&self[], is_extended)
+ UnicodeStr::graphemes(&self[..], is_extended)
}
/// Returns an iterator over the grapheme clusters of self and their byte offsets.
#[unstable(feature = "collections",
reason = "this functionality may only be provided by libunicode")]
fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices {
- UnicodeStr::grapheme_indices(&self[], is_extended)
+ UnicodeStr::grapheme_indices(&self[..], is_extended)
}
/// An iterator over the words of a string (subsequences separated
#[unstable(feature = "str_words",
reason = "the precise algorithm to use is unclear")]
fn words(&self) -> Words {
- UnicodeStr::words(&self[])
+ UnicodeStr::words(&self[..])
}
/// Returns a string's displayed width in columns, treating control
#[unstable(feature = "collections",
reason = "this functionality may only be provided by libunicode")]
fn width(&self, is_cjk: bool) -> usize {
- UnicodeStr::width(&self[], is_cjk)
+ UnicodeStr::width(&self[..], is_cjk)
}
/// Returns a string with leading and trailing whitespace removed.
#[stable(feature = "rust1", since = "1.0.0")]
fn trim(&self) -> &str {
- UnicodeStr::trim(&self[])
+ UnicodeStr::trim(&self[..])
}
/// Returns a string with leading whitespace removed.
#[stable(feature = "rust1", since = "1.0.0")]
fn trim_left(&self) -> &str {
- UnicodeStr::trim_left(&self[])
+ UnicodeStr::trim_left(&self[..])
}
/// Returns a string with trailing whitespace removed.
#[stable(feature = "rust1", since = "1.0.0")]
fn trim_right(&self) -> &str {
- UnicodeStr::trim_right(&self[])
+ UnicodeStr::trim_right(&self[..])
}
}
&["\u{378}\u{308}\u{903}"], &["\u{378}\u{308}", "\u{903}"]),
];
- for &(s, g) in &test_same[] {
+ for &(s, g) in &test_same[..] {
// test forward iterator
assert!(order::equals(s.graphemes(true), g.iter().cloned()));
assert!(order::equals(s.graphemes(false), g.iter().cloned()));
use core::prelude::*;
-use core::borrow::{Cow, IntoCow};
use core::default::Default;
use core::error::Error;
use core::fmt;
use core::hash;
-use core::iter::FromIterator;
+use core::iter::{IntoIterator, FromIterator};
use core::mem;
use core::ops::{self, Deref, Add, Index};
use core::ptr;
use unicode::str as unicode_str;
use unicode::str::Utf16Item;
+use borrow::{Cow, IntoCow};
use str::{self, CharRange, FromStr, Utf8Error};
use vec::{DerefVec, Vec, as_vec};
/// assert_eq!(output.as_slice(), "Hello \u{FFFD}World");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> CowString<'a> {
+ pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> Cow<'a, str> {
let mut i = 0;
match str::from_utf8(v) {
Ok(s) => return Cow::Borrowed(s),
#[stable(feature = "rust1", since = "1.0.0")]
impl FromIterator<char> for String {
- fn from_iter<I:Iterator<Item=char>>(iterator: I) -> String {
+ fn from_iter<I: IntoIterator<Item=char>>(iter: I) -> String {
let mut buf = String::new();
- buf.extend(iterator);
+ buf.extend(iter);
buf
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> FromIterator<&'a str> for String {
- fn from_iter<I:Iterator<Item=&'a str>>(iterator: I) -> String {
+ fn from_iter<I: IntoIterator<Item=&'a str>>(iter: I) -> String {
let mut buf = String::new();
- buf.extend(iterator);
+ buf.extend(iter);
buf
}
}
#[unstable(feature = "collections",
reason = "waiting on Extend stabilization")]
impl Extend<char> for String {
- fn extend<I:Iterator<Item=char>>(&mut self, iterator: I) {
+ fn extend<I: IntoIterator<Item=char>>(&mut self, iterable: I) {
+ let iterator = iterable.into_iter();
let (lower_bound, _) = iterator.size_hint();
self.reserve(lower_bound);
for ch in iterator {
#[unstable(feature = "collections",
reason = "waiting on Extend stabilization")]
impl<'a> Extend<&'a str> for String {
- fn extend<I: Iterator<Item=&'a str>>(&mut self, iterator: I) {
+ fn extend<I: IntoIterator<Item=&'a str>>(&mut self, iterable: I) {
+ let iterator = iterable.into_iter();
// A guess that at least one byte per iterator element will be needed.
let (lower_bound, _) = iterator.size_hint();
self.reserve(lower_bound);
}
impl_eq! { String, &'a str }
-impl_eq! { CowString<'a>, String }
+impl_eq! { Cow<'a, str>, String }
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b> PartialEq<&'b str> for CowString<'a> {
+impl<'a, 'b> PartialEq<&'b str> for Cow<'a, str> {
#[inline]
fn eq(&self, other: &&'b str) -> bool { PartialEq::eq(&**self, &**other) }
#[inline]
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b> PartialEq<CowString<'a>> for &'b str {
+impl<'a, 'b> PartialEq<Cow<'a, str>> for &'b str {
#[inline]
- fn eq(&self, other: &CowString<'a>) -> bool { PartialEq::eq(&**self, &**other) }
+ fn eq(&self, other: &Cow<'a, str>) -> bool { PartialEq::eq(&**self, &**other) }
#[inline]
- fn ne(&self, other: &CowString<'a>) -> bool { PartialEq::ne(&**self, &**other) }
+ fn ne(&self, other: &Cow<'a, str>) -> bool { PartialEq::ne(&**self, &**other) }
}
#[unstable(feature = "collections", reason = "waiting on Str stabilization")]
}
#[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")]
+#[cfg(not(stage0))]
+impl hash::Hash for String {
+ #[inline]
+ fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
+ (**self).hash(hasher)
+ }
+}
#[unstable(feature = "collections",
reason = "recent addition, needs more experience")]
type Output = str;
#[inline]
fn index(&self, index: &ops::Range<usize>) -> &str {
- &self[][*index]
+ &self[..][*index]
}
}
#[stable(feature = "rust1", since = "1.0.0")]
type Output = str;
#[inline]
fn index(&self, index: &ops::RangeTo<usize>) -> &str {
- &self[][*index]
+ &self[..][*index]
}
}
#[stable(feature = "rust1", since = "1.0.0")]
type Output = str;
#[inline]
fn index(&self, index: &ops::RangeFrom<usize>) -> &str {
- &self[][*index]
+ &self[..][*index]
}
}
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
fn deref(&self) -> &str {
- unsafe { mem::transmute(&self.vec[]) }
+ unsafe { mem::transmute(&self.vec[..]) }
}
}
}
}
-impl IntoCow<'static, String, str> for String {
+#[stable(feature = "rust1", since = "1.0.0")]
+impl IntoCow<'static, str> for String {
#[inline]
- fn into_cow(self) -> CowString<'static> {
+ fn into_cow(self) -> Cow<'static, str> {
Cow::Owned(self)
}
}
-impl<'a> IntoCow<'a, String, str> for &'a str {
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a> IntoCow<'a, str> for &'a str {
#[inline]
- fn into_cow(self) -> CowString<'a> {
+ fn into_cow(self) -> Cow<'a, str> {
Cow::Borrowed(self)
}
}
-/// A clone-on-write string
-#[stable(feature = "rust1", since = "1.0.0")]
-pub type CowString<'a> = Cow<'a, String, str>;
-
-impl<'a> Str for CowString<'a> {
+impl<'a> Str for Cow<'a, str> {
#[inline]
fn as_slice<'b>(&'b self) -> &'b str {
&**self
}
}
+/// A clone-on-write string
+#[deprecated(since = "1.0.0", reason = "use Cow<'a, str> instead")]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub type CowString<'a> = Cow<'a, str>;
+
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Write for String {
#[inline]
#[test]
fn test_slicing() {
let s = "foobar".to_string();
- assert_eq!("foobar", &s[]);
+ assert_eq!("foobar", &s[..]);
assert_eq!("foo", &s[..3]);
assert_eq!("bar", &s[3..]);
assert_eq!("oob", &s[1..4]);
use alloc::boxed::Box;
use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
-use core::borrow::{Cow, IntoCow};
use core::cmp::max;
use core::cmp::{Ordering};
use core::default::Default;
use core::fmt;
use core::hash::{self, Hash};
+use core::intrinsics::assume;
use core::iter::{repeat, FromIterator, IntoIterator};
-use core::marker::{self, ContravariantLifetime, InvariantType};
+use core::marker::PhantomData;
use core::mem;
-use core::nonzero::NonZero;
use core::num::{Int, UnsignedInt};
use core::ops::{Index, IndexMut, Deref, Add};
use core::ops;
use core::ptr;
+use core::ptr::Unique;
use core::raw::Slice as RawSlice;
use core::slice;
use core::usize;
+use borrow::{Cow, IntoCow};
+
/// A growable list type, written `Vec<T>` but pronounced 'vector.'
///
/// # Examples
#[unsafe_no_drop_flag]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Vec<T> {
- ptr: NonZero<*mut T>,
+ ptr: Unique<T>,
len: usize,
cap: usize,
- _own: marker::PhantomData<T>,
}
unsafe impl<T: Send> Send for Vec<T> { }
pub unsafe fn from_raw_parts(ptr: *mut T, length: usize,
capacity: usize) -> Vec<T> {
Vec {
- ptr: NonZero::new(ptr),
+ ptr: Unique::new(ptr),
len: length,
cap: capacity,
- _own: marker::PhantomData,
}
}
self.len * mem::size_of::<T>(),
mem::min_align_of::<T>()) as *mut T;
if ptr.is_null() { ::alloc::oom() }
- self.ptr = NonZero::new(ptr);
+ self.ptr = Unique::new(ptr);
}
self.cap = self.len;
}
unsafe {
let ptr = alloc_or_realloc(*self.ptr, old_size, size);
if ptr.is_null() { ::alloc::oom() }
- self.ptr = NonZero::new(ptr);
+ self.ptr = Unique::new(ptr);
}
self.cap = max(self.cap, 2) * 2;
}
Drain {
ptr: begin,
end: end,
- marker: ContravariantLifetime,
+ marker: PhantomData,
}
}
}
end_t: unsafe { start.offset(offset) },
start_u: start as *mut U,
end_u: start as *mut U,
+
+ _marker: PhantomData,
};
// start_t
// start_u
let mut pv = PartialVecZeroSized::<T,U> {
num_t: vec.len(),
num_u: 0,
- marker_t: InvariantType,
- marker_u: InvariantType,
+ marker: PhantomData,
};
unsafe { mem::forget(vec); }
unsafe {
let ptr = alloc_or_realloc(*self.ptr, self.cap * mem::size_of::<T>(), size);
if ptr.is_null() { ::alloc::oom() }
- self.ptr = NonZero::new(ptr);
+ self.ptr = Unique::new(ptr);
}
self.cap = capacity;
}
}
}
+#[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")]
+#[cfg(not(stage0))]
+impl<T: Hash> Hash for Vec<T> {
+ #[inline]
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ Hash::hash(&**self, state)
+ }
+}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Index<usize> for Vec<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> FromIterator<T> for Vec<T> {
#[inline]
- fn from_iter<I:Iterator<Item=T>>(mut iterator: I) -> Vec<T> {
+ fn from_iter<I: IntoIterator<Item=T>>(iterable: I) -> Vec<T> {
+ let mut iterator = iterable.into_iter();
let (lower, _) = iterator.size_hint();
let mut vector = Vec::with_capacity(lower);
#[unstable(feature = "collections", reason = "waiting on Extend stability")]
impl<T> Extend<T> for Vec<T> {
#[inline]
- fn extend<I: Iterator<Item=T>>(&mut self, iterator: I) {
+ fn extend<I: IntoIterator<Item=T>>(&mut self, iterable: I) {
+ let iterator = iterable.into_iter();
let (lower, _) = iterator.size_hint();
self.reserve(lower);
for element in iterator {
impl_eq! { Vec<A>, &'b [B] }
impl_eq! { Vec<A>, &'b mut [B] }
-impl<'a, A, B> PartialEq<Vec<B>> for CowVec<'a, A> where A: PartialEq<B> + Clone {
+impl<'a, A, B> PartialEq<Vec<B>> for Cow<'a, [A]> where A: PartialEq<B> + Clone {
#[inline]
fn eq(&self, other: &Vec<B>) -> bool { PartialEq::eq(&**self, &**other) }
#[inline]
fn ne(&self, other: &Vec<B>) -> bool { PartialEq::ne(&**self, &**other) }
}
-impl<'a, A, B> PartialEq<CowVec<'a, A>> for Vec<B> where A: Clone, B: PartialEq<A> {
+impl<'a, A, B> PartialEq<Cow<'a, [A]>> for Vec<B> where A: Clone, B: PartialEq<A> {
#[inline]
- fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) }
+ fn eq(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::eq(&**self, &**other) }
#[inline]
- fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) }
+ fn ne(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::ne(&**self, &**other) }
}
macro_rules! impl_eq_for_cowvec {
($rhs:ty) => {
- impl<'a, 'b, A, B> PartialEq<$rhs> for CowVec<'a, A> where A: PartialEq<B> + Clone {
+ impl<'a, 'b, A, B> PartialEq<$rhs> for Cow<'a, [A]> where A: PartialEq<B> + Clone {
#[inline]
fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
#[inline]
fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
}
- impl<'a, 'b, A, B> PartialEq<CowVec<'a, A>> for $rhs where A: Clone, B: PartialEq<A> {
+ impl<'a, 'b, A, B> PartialEq<Cow<'a, [A]>> for $rhs where A: Clone, B: PartialEq<A> {
#[inline]
- fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) }
+ fn eq(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::eq(&**self, &**other) }
#[inline]
- fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) }
+ fn ne(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::ne(&**self, &**other) }
}
}
}
impl_eq_for_cowvec! { &'b [B] }
impl_eq_for_cowvec! { &'b mut [B] }
-#[unstable(feature = "collections",
- reason = "waiting on PartialOrd stability")]
+#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PartialOrd> PartialOrd for Vec<T> {
#[inline]
fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
}
}
-#[unstable(feature = "collections", reason = "waiting on Eq stability")]
+#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Eq> Eq for Vec<T> {}
-#[unstable(feature = "collections", reason = "waiting on Ord stability")]
+#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Ord> Ord for Vec<T> {
#[inline]
fn cmp(&self, other: &Vec<T>) -> Ordering {
#[stable(feature = "rust1", since = "1.0.0")]
fn as_slice(&self) -> &[T] {
unsafe {
+ let p = *self.ptr;
+ if cfg!(not(stage0)) { // NOTE remove cfg after next snapshot
+ assume(p != 0 as *mut T);
+ }
mem::transmute(RawSlice {
- data: *self.ptr,
+ data: p,
len: self.len
})
}
// Clone-on-write
////////////////////////////////////////////////////////////////////////////////
-#[unstable(feature = "collections",
- reason = "unclear how valuable this alias is")]
/// A clone-on-write vector
-pub type CowVec<'a, T> = Cow<'a, Vec<T>, [T]>;
+#[deprecated(since = "1.0.0", reason = "use Cow<'a, [T]> instead")]
+#[unstable(feature = "collections")]
+pub type CowVec<'a, T> = Cow<'a, [T]>;
#[unstable(feature = "collections")]
-impl<'a, T> FromIterator<T> for CowVec<'a, T> where T: Clone {
- fn from_iter<I: Iterator<Item=T>>(it: I) -> CowVec<'a, T> {
+impl<'a, T> FromIterator<T> for Cow<'a, [T]> where T: Clone {
+ fn from_iter<I: IntoIterator<Item=T>>(it: I) -> Cow<'a, [T]> {
Cow::Owned(FromIterator::from_iter(it))
}
}
-impl<'a, T: 'a> IntoCow<'a, Vec<T>, [T]> for Vec<T> where T: Clone {
- fn into_cow(self) -> CowVec<'a, T> {
+impl<'a, T: 'a> IntoCow<'a, [T]> for Vec<T> where T: Clone {
+ fn into_cow(self) -> Cow<'a, [T]> {
Cow::Owned(self)
}
}
-impl<'a, T> IntoCow<'a, Vec<T>, [T]> for &'a [T] where T: Clone {
- fn into_cow(self) -> CowVec<'a, T> {
+impl<'a, T> IntoCow<'a, [T]> for &'a [T] where T: Clone {
+ fn into_cow(self) -> Cow<'a, [T]> {
Cow::Borrowed(self)
}
}
#[unsafe_no_drop_flag]
#[unstable(feature = "collections",
reason = "recently added as part of collections reform 2")]
-pub struct Drain<'a, T> {
+pub struct Drain<'a, T:'a> {
ptr: *const T,
end: *const T,
- marker: ContravariantLifetime<'a>,
+ marker: PhantomData<&'a T>,
}
#[stable(feature = "rust1", since = "1.0.0")]
/// Wrapper type providing a `&Vec<T>` reference via `Deref`.
#[unstable(feature = "collections")]
-pub struct DerefVec<'a, T> {
+pub struct DerefVec<'a, T:'a> {
x: Vec<T>,
- l: ContravariantLifetime<'a>
+ l: PhantomData<&'a T>,
}
#[unstable(feature = "collections")]
unsafe {
DerefVec {
x: Vec::from_raw_parts(x.as_ptr() as *mut T, x.len(), x.len()),
- l: ContravariantLifetime::<'a>
+ l: PhantomData,
}
}
}
end_u: *mut U,
start_t: *mut T,
end_t: *mut T,
+
+ _marker: PhantomData<U>,
}
/// An owned, partially type-converted vector of zero-sized elements.
struct PartialVecZeroSized<T,U> {
num_t: usize,
num_u: usize,
- marker_t: InvariantType<T>,
- marker_u: InvariantType<U>,
+ marker: PhantomData<::core::cell::Cell<(T,U)>>,
}
#[unsafe_destructor]
b.bytes = src_len as u64;
b.iter(|| {
- let dst = src.clone()[].to_vec();
+ let dst = src.clone()[..].to_vec();
assert_eq!(dst.len(), src_len);
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
});
--- /dev/null
+// Copyright 2012-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.
+
+//! VecDeque is a double-ended queue, which is implemented with the help of a
+//! growing ring buffer.
+//!
+//! This queue has `O(1)` amortized inserts and removals from both ends of the
+//! container. It also has `O(1)` indexing like a vector. The contained elements
+//! are not required to be copyable, and the queue will be sendable if the
+//! contained type is sendable.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use core::prelude::*;
+
+use core::cmp::Ordering;
+use core::default::Default;
+use core::fmt;
+use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator};
+use core::marker;
+use core::mem;
+use core::num::{Int, UnsignedInt};
+use core::ops::{Index, IndexMut};
+use core::ptr::{self, Unique};
+use core::raw::Slice as RawSlice;
+
+use core::hash::{Hash, Hasher};
+#[cfg(stage0)] use core::hash::Writer;
+use core::cmp;
+
+use alloc::heap;
+
+#[deprecated(since = "1.0.0", reason = "renamed to VecDeque")]
+#[unstable(feature = "collections")]
+pub use VecDeque as RingBuf;
+
+static INITIAL_CAPACITY: usize = 7; // 2^3 - 1
+static MINIMUM_CAPACITY: usize = 1; // 2 - 1
+
+/// `VecDeque` is a growable ring buffer, which can be used as a
+/// double-ended queue efficiently.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct VecDeque<T> {
+ // tail and head are pointers into the buffer. Tail always points
+ // to the first element that could be read, Head always points
+ // to where data should be written.
+ // If tail == head the buffer is empty. The length of the ringbuf
+ // is defined as the distance between the two.
+
+ tail: usize,
+ head: usize,
+ cap: usize,
+ ptr: Unique<T>,
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+unsafe impl<T: Send> Send for VecDeque<T> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+unsafe impl<T: Sync> Sync for VecDeque<T> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: Clone> Clone for VecDeque<T> {
+ fn clone(&self) -> VecDeque<T> {
+ self.iter().cloned().collect()
+ }
+}
+
+#[unsafe_destructor]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> Drop for VecDeque<T> {
+ fn drop(&mut self) {
+ self.clear();
+ unsafe {
+ if mem::size_of::<T>() != 0 {
+ heap::deallocate(*self.ptr as *mut u8,
+ self.cap * mem::size_of::<T>(),
+ mem::min_align_of::<T>())
+ }
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> Default for VecDeque<T> {
+ #[inline]
+ fn default() -> VecDeque<T> { VecDeque::new() }
+}
+
+impl<T> VecDeque<T> {
+ /// Turn ptr into a slice
+ #[inline]
+ unsafe fn buffer_as_slice(&self) -> &[T] {
+ mem::transmute(RawSlice { data: *self.ptr as *const T, len: self.cap })
+ }
+
+ /// Turn ptr into a mut slice
+ #[inline]
+ unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] {
+ mem::transmute(RawSlice { data: *self.ptr as *const T, len: self.cap })
+ }
+
+ /// Moves an element out of the buffer
+ #[inline]
+ unsafe fn buffer_read(&mut self, off: usize) -> T {
+ ptr::read(self.ptr.offset(off as isize))
+ }
+
+ /// Writes an element into the buffer, moving it.
+ #[inline]
+ unsafe fn buffer_write(&mut self, off: usize, t: T) {
+ ptr::write(self.ptr.offset(off as isize), t);
+ }
+
+ /// Returns true iff the buffer is at capacity
+ #[inline]
+ fn is_full(&self) -> bool { self.cap - self.len() == 1 }
+
+ /// Returns the index in the underlying buffer for a given logical element
+ /// index.
+ #[inline]
+ fn wrap_index(&self, idx: usize) -> usize { wrap_index(idx, self.cap) }
+
+ /// Copies a contiguous block of memory len long from src to dst
+ #[inline]
+ unsafe fn copy(&self, dst: usize, src: usize, len: usize) {
+ debug_assert!(dst + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
+ self.cap);
+ debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
+ self.cap);
+ ptr::copy_memory(
+ self.ptr.offset(dst as isize),
+ self.ptr.offset(src as isize),
+ len);
+ }
+
+ /// Copies a contiguous block of memory len long from src to dst
+ #[inline]
+ unsafe fn copy_nonoverlapping(&self, dst: usize, src: usize, len: usize) {
+ debug_assert!(dst + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
+ self.cap);
+ debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
+ self.cap);
+ ptr::copy_nonoverlapping_memory(
+ self.ptr.offset(dst as isize),
+ self.ptr.offset(src as isize),
+ len);
+ }
+}
+
+impl<T> VecDeque<T> {
+ /// Creates an empty `VecDeque`.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn new() -> VecDeque<T> {
+ VecDeque::with_capacity(INITIAL_CAPACITY)
+ }
+
+ /// Creates an empty `VecDeque` with space for at least `n` elements.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn with_capacity(n: usize) -> VecDeque<T> {
+ // +1 since the ringbuffer always leaves one space empty
+ let cap = cmp::max(n + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
+ assert!(cap > n, "capacity overflow");
+ let size = cap.checked_mul(mem::size_of::<T>())
+ .expect("capacity overflow");
+
+ let ptr = unsafe {
+ if mem::size_of::<T>() != 0 {
+ let ptr = heap::allocate(size, mem::min_align_of::<T>()) as *mut T;;
+ if ptr.is_null() { ::alloc::oom() }
+ Unique::new(ptr)
+ } else {
+ Unique::new(heap::EMPTY as *mut T)
+ }
+ };
+
+ VecDeque {
+ tail: 0,
+ head: 0,
+ cap: cap,
+ ptr: ptr,
+ }
+ }
+
+ /// Retrieves an element in the `VecDeque` by index.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// buf.push_back(3);
+ /// buf.push_back(4);
+ /// buf.push_back(5);
+ /// assert_eq!(buf.get(1).unwrap(), &4);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn get(&self, i: usize) -> Option<&T> {
+ if i < self.len() {
+ let idx = self.wrap_index(self.tail + i);
+ unsafe { Some(&*self.ptr.offset(idx as isize)) }
+ } else {
+ None
+ }
+ }
+
+ /// Retrieves an element in the `VecDeque` mutably by index.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// buf.push_back(3);
+ /// buf.push_back(4);
+ /// buf.push_back(5);
+ /// match buf.get_mut(1) {
+ /// None => {}
+ /// Some(elem) => {
+ /// *elem = 7;
+ /// }
+ /// }
+ ///
+ /// assert_eq!(buf[1], 7);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn get_mut(&mut self, i: usize) -> Option<&mut T> {
+ if i < self.len() {
+ let idx = self.wrap_index(self.tail + i);
+ unsafe { Some(&mut *self.ptr.offset(idx as isize)) }
+ } else {
+ None
+ }
+ }
+
+ /// Swaps elements at indices `i` and `j`.
+ ///
+ /// `i` and `j` may be equal.
+ ///
+ /// Fails if there is no element with either index.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// buf.push_back(3);
+ /// buf.push_back(4);
+ /// buf.push_back(5);
+ /// buf.swap(0, 2);
+ /// assert_eq!(buf[0], 5);
+ /// assert_eq!(buf[2], 3);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn swap(&mut self, i: usize, j: usize) {
+ assert!(i < self.len());
+ assert!(j < self.len());
+ let ri = self.wrap_index(self.tail + i);
+ let rj = self.wrap_index(self.tail + j);
+ unsafe {
+ ptr::swap(self.ptr.offset(ri as isize), self.ptr.offset(rj as isize))
+ }
+ }
+
+ /// Returns the number of elements the `VecDeque` can hold without
+ /// reallocating.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let buf: VecDeque<i32> = VecDeque::with_capacity(10);
+ /// assert!(buf.capacity() >= 10);
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn capacity(&self) -> usize { self.cap - 1 }
+
+ /// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
+ /// given `VecDeque`. Does nothing if the capacity is already sufficient.
+ ///
+ /// Note that the allocator may give the collection more space than it requests. Therefore
+ /// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future
+ /// insertions are expected.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the new capacity overflows `usize`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf: VecDeque<i32> = vec![1].into_iter().collect();
+ /// buf.reserve_exact(10);
+ /// assert!(buf.capacity() >= 11);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn reserve_exact(&mut self, additional: usize) {
+ self.reserve(additional);
+ }
+
+ /// Reserves capacity for at least `additional` more elements to be inserted in the given
+ /// `Ringbuf`. The collection may reserve more space to avoid frequent reallocations.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the new capacity overflows `usize`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf: VecDeque<i32> = vec![1].into_iter().collect();
+ /// buf.reserve(10);
+ /// assert!(buf.capacity() >= 11);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn reserve(&mut self, additional: usize) {
+ let new_len = self.len() + additional;
+ assert!(new_len + 1 > self.len(), "capacity overflow");
+ if new_len > self.capacity() {
+ let count = (new_len + 1).next_power_of_two();
+ assert!(count >= new_len + 1);
+
+ if mem::size_of::<T>() != 0 {
+ let old = self.cap * mem::size_of::<T>();
+ let new = count.checked_mul(mem::size_of::<T>())
+ .expect("capacity overflow");
+ unsafe {
+ let ptr = heap::reallocate(*self.ptr as *mut u8,
+ old,
+ new,
+ mem::min_align_of::<T>()) as *mut T;
+ if ptr.is_null() { ::alloc::oom() }
+ self.ptr = Unique::new(ptr);
+ }
+ }
+
+ // Move the shortest contiguous section of the ring buffer
+ // T H
+ // [o o o o o o o . ]
+ // T H
+ // A [o o o o o o o . . . . . . . . . ]
+ // H T
+ // [o o . o o o o o ]
+ // T H
+ // B [. . . o o o o o o o . . . . . . ]
+ // H T
+ // [o o o o o . o o ]
+ // H T
+ // C [o o o o o . . . . . . . . . o o ]
+
+ let oldcap = self.cap;
+ self.cap = count;
+
+ if self.tail <= self.head { // A
+ // Nop
+ } else if self.head < oldcap - self.tail { // B
+ unsafe {
+ self.copy_nonoverlapping(oldcap, 0, self.head);
+ }
+ self.head += oldcap;
+ debug_assert!(self.head > self.tail);
+ } else { // C
+ let new_tail = count - (oldcap - self.tail);
+ unsafe {
+ self.copy_nonoverlapping(new_tail, self.tail, oldcap - self.tail);
+ }
+ self.tail = new_tail;
+ debug_assert!(self.head < self.tail);
+ }
+ debug_assert!(self.head < self.cap);
+ debug_assert!(self.tail < self.cap);
+ debug_assert!(self.cap.count_ones() == 1);
+ }
+ }
+
+ /// Shrinks the capacity of the ringbuf as much as possible.
+ ///
+ /// It will drop down as close as possible to the length but the allocator may still inform the
+ /// ringbuf that there is space for a few more elements.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::with_capacity(15);
+ /// buf.extend(0..4);
+ /// assert_eq!(buf.capacity(), 15);
+ /// buf.shrink_to_fit();
+ /// assert!(buf.capacity() >= 4);
+ /// ```
+ pub fn shrink_to_fit(&mut self) {
+ // +1 since the ringbuffer always leaves one space empty
+ // len + 1 can't overflow for an existing, well-formed ringbuf.
+ let target_cap = cmp::max(self.len() + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
+ if target_cap < self.cap {
+ // There are three cases of interest:
+ // All elements are out of desired bounds
+ // Elements are contiguous, and head is out of desired bounds
+ // Elements are discontiguous, and tail is out of desired bounds
+ //
+ // At all other times, element positions are unaffected.
+ //
+ // Indicates that elements at the head should be moved.
+ let head_outside = self.head == 0 || self.head >= target_cap;
+ // Move elements from out of desired bounds (positions after target_cap)
+ if self.tail >= target_cap && head_outside {
+ // T H
+ // [. . . . . . . . o o o o o o o . ]
+ // T H
+ // [o o o o o o o . ]
+ unsafe {
+ self.copy_nonoverlapping(0, self.tail, self.len());
+ }
+ self.head = self.len();
+ self.tail = 0;
+ } else if self.tail != 0 && self.tail < target_cap && head_outside {
+ // T H
+ // [. . . o o o o o o o . . . . . . ]
+ // H T
+ // [o o . o o o o o ]
+ let len = self.wrap_index(self.head - target_cap);
+ unsafe {
+ self.copy_nonoverlapping(0, target_cap, len);
+ }
+ self.head = len;
+ debug_assert!(self.head < self.tail);
+ } else if self.tail >= target_cap {
+ // H T
+ // [o o o o o . . . . . . . . . o o ]
+ // H T
+ // [o o o o o . o o ]
+ debug_assert!(self.wrap_index(self.head - 1) < target_cap);
+ let len = self.cap - self.tail;
+ let new_tail = target_cap - len;
+ unsafe {
+ self.copy_nonoverlapping(new_tail, self.tail, len);
+ }
+ self.tail = new_tail;
+ debug_assert!(self.head < self.tail);
+ }
+
+ if mem::size_of::<T>() != 0 {
+ let old = self.cap * mem::size_of::<T>();
+ let new_size = target_cap * mem::size_of::<T>();
+ unsafe {
+ let ptr = heap::reallocate(*self.ptr as *mut u8,
+ old,
+ new_size,
+ mem::min_align_of::<T>()) as *mut T;
+ if ptr.is_null() { ::alloc::oom() }
+ self.ptr = Unique::new(ptr);
+ }
+ }
+ self.cap = target_cap;
+ debug_assert!(self.head < self.cap);
+ debug_assert!(self.tail < self.cap);
+ debug_assert!(self.cap.count_ones() == 1);
+ }
+ }
+
+ /// Shorten a ringbuf, dropping excess elements from the back.
+ ///
+ /// If `len` is greater than the ringbuf's current length, this has no
+ /// effect.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// buf.push_back(5);
+ /// buf.push_back(10);
+ /// buf.push_back(15);
+ /// buf.truncate(1);
+ /// assert_eq!(buf.len(), 1);
+ /// assert_eq!(Some(&5), buf.get(0));
+ /// ```
+ #[unstable(feature = "collections",
+ reason = "matches collection reform specification; waiting on panic semantics")]
+ pub fn truncate(&mut self, len: usize) {
+ for _ in len..self.len() {
+ self.pop_back();
+ }
+ }
+
+ /// Returns a front-to-back iterator.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// buf.push_back(5);
+ /// buf.push_back(3);
+ /// buf.push_back(4);
+ /// let b: &[_] = &[&5, &3, &4];
+ /// assert_eq!(buf.iter().collect::<Vec<&i32>>().as_slice(), b);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn iter(&self) -> Iter<T> {
+ Iter {
+ tail: self.tail,
+ head: self.head,
+ ring: unsafe { self.buffer_as_slice() }
+ }
+ }
+
+ /// Returns a front-to-back iterator that returns mutable references.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// buf.push_back(5);
+ /// buf.push_back(3);
+ /// buf.push_back(4);
+ /// for num in buf.iter_mut() {
+ /// *num = *num - 2;
+ /// }
+ /// let b: &[_] = &[&mut 3, &mut 1, &mut 2];
+ /// assert_eq!(&buf.iter_mut().collect::<Vec<&mut i32>>()[], b);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn iter_mut(&mut self) -> IterMut<T> {
+ IterMut {
+ tail: self.tail,
+ head: self.head,
+ cap: self.cap,
+ ptr: *self.ptr,
+ marker: marker::PhantomData,
+ }
+ }
+
+ /// Consumes the list into an iterator yielding elements by value.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn into_iter(self) -> IntoIter<T> {
+ IntoIter {
+ inner: self,
+ }
+ }
+
+ /// Returns a pair of slices which contain, in order, the contents of the
+ /// `VecDeque`.
+ #[inline]
+ #[unstable(feature = "collections",
+ reason = "matches collection reform specification, waiting for dust to settle")]
+ pub fn as_slices(&self) -> (&[T], &[T]) {
+ unsafe {
+ let contiguous = self.is_contiguous();
+ let buf = self.buffer_as_slice();
+ if contiguous {
+ let (empty, buf) = buf.split_at(0);
+ (&buf[self.tail..self.head], empty)
+ } else {
+ let (mid, right) = buf.split_at(self.tail);
+ let (left, _) = mid.split_at(self.head);
+ (right, left)
+ }
+ }
+ }
+
+ /// Returns a pair of slices which contain, in order, the contents of the
+ /// `VecDeque`.
+ #[inline]
+ #[unstable(feature = "collections",
+ reason = "matches collection reform specification, waiting for dust to settle")]
+ pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
+ unsafe {
+ let contiguous = self.is_contiguous();
+ let head = self.head;
+ let tail = self.tail;
+ let buf = self.buffer_as_mut_slice();
+
+ if contiguous {
+ let (empty, buf) = buf.split_at_mut(0);
+ (&mut buf[tail .. head], empty)
+ } else {
+ let (mid, right) = buf.split_at_mut(tail);
+ let (left, _) = mid.split_at_mut(head);
+
+ (right, left)
+ }
+ }
+ }
+
+ /// Returns the number of elements in the `VecDeque`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut v = VecDeque::new();
+ /// assert_eq!(v.len(), 0);
+ /// v.push_back(1);
+ /// assert_eq!(v.len(), 1);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn len(&self) -> usize { count(self.tail, self.head, self.cap) }
+
+ /// Returns true if the buffer contains no elements
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut v = VecDeque::new();
+ /// assert!(v.is_empty());
+ /// v.push_front(1);
+ /// assert!(!v.is_empty());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn is_empty(&self) -> bool { self.len() == 0 }
+
+ /// Creates a draining iterator that clears the `VecDeque` and iterates over
+ /// the removed items from start to end.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut v = VecDeque::new();
+ /// v.push_back(1);
+ /// assert_eq!(v.drain().next(), Some(1));
+ /// assert!(v.is_empty());
+ /// ```
+ #[inline]
+ #[unstable(feature = "collections",
+ reason = "matches collection reform specification, waiting for dust to settle")]
+ pub fn drain(&mut self) -> Drain<T> {
+ Drain {
+ inner: self,
+ }
+ }
+
+ /// Clears the buffer, removing all values.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut v = VecDeque::new();
+ /// v.push_back(1);
+ /// v.clear();
+ /// assert!(v.is_empty());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
+ pub fn clear(&mut self) {
+ self.drain();
+ }
+
+ /// Provides a reference to the front element, or `None` if the sequence is
+ /// empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut d = VecDeque::new();
+ /// assert_eq!(d.front(), None);
+ ///
+ /// d.push_back(1);
+ /// d.push_back(2);
+ /// assert_eq!(d.front(), Some(&1));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn front(&self) -> Option<&T> {
+ if !self.is_empty() { Some(&self[0]) } else { None }
+ }
+
+ /// Provides a mutable reference to the front element, or `None` if the
+ /// sequence is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut d = VecDeque::new();
+ /// assert_eq!(d.front_mut(), None);
+ ///
+ /// d.push_back(1);
+ /// d.push_back(2);
+ /// match d.front_mut() {
+ /// Some(x) => *x = 9,
+ /// None => (),
+ /// }
+ /// assert_eq!(d.front(), Some(&9));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn front_mut(&mut self) -> Option<&mut T> {
+ if !self.is_empty() { Some(&mut self[0]) } else { None }
+ }
+
+ /// Provides a reference to the back element, or `None` if the sequence is
+ /// empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut d = VecDeque::new();
+ /// assert_eq!(d.back(), None);
+ ///
+ /// d.push_back(1);
+ /// d.push_back(2);
+ /// assert_eq!(d.back(), Some(&2));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn back(&self) -> Option<&T> {
+ if !self.is_empty() { Some(&self[self.len() - 1]) } else { None }
+ }
+
+ /// Provides a mutable reference to the back element, or `None` if the
+ /// sequence is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut d = VecDeque::new();
+ /// assert_eq!(d.back(), None);
+ ///
+ /// d.push_back(1);
+ /// d.push_back(2);
+ /// match d.back_mut() {
+ /// Some(x) => *x = 9,
+ /// None => (),
+ /// }
+ /// assert_eq!(d.back(), Some(&9));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn back_mut(&mut self) -> Option<&mut T> {
+ let len = self.len();
+ if !self.is_empty() { Some(&mut self[len - 1]) } else { None }
+ }
+
+ /// Removes the first element and returns it, or `None` if the sequence is
+ /// empty.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut d = VecDeque::new();
+ /// d.push_back(1);
+ /// d.push_back(2);
+ ///
+ /// assert_eq!(d.pop_front(), Some(1));
+ /// assert_eq!(d.pop_front(), Some(2));
+ /// assert_eq!(d.pop_front(), None);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn pop_front(&mut self) -> Option<T> {
+ if self.is_empty() {
+ None
+ } else {
+ let tail = self.tail;
+ self.tail = self.wrap_index(self.tail + 1);
+ unsafe { Some(self.buffer_read(tail)) }
+ }
+ }
+
+ /// Inserts an element first in the sequence.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut d = VecDeque::new();
+ /// d.push_front(1);
+ /// d.push_front(2);
+ /// assert_eq!(d.front(), Some(&2));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn push_front(&mut self, t: T) {
+ if self.is_full() {
+ self.reserve(1);
+ debug_assert!(!self.is_full());
+ }
+
+ self.tail = self.wrap_index(self.tail - 1);
+ let tail = self.tail;
+ unsafe { self.buffer_write(tail, t); }
+ }
+
+ /// Appends an element to the back of a buffer
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// buf.push_back(1);
+ /// buf.push_back(3);
+ /// assert_eq!(3, *buf.back().unwrap());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn push_back(&mut self, t: T) {
+ if self.is_full() {
+ self.reserve(1);
+ debug_assert!(!self.is_full());
+ }
+
+ let head = self.head;
+ self.head = self.wrap_index(self.head + 1);
+ unsafe { self.buffer_write(head, t) }
+ }
+
+ /// Removes the last element from a buffer and returns it, or `None` if
+ /// it is empty.
+ ///
+ /// # Examples
+ ///
+ /// ```rust
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// assert_eq!(buf.pop_back(), None);
+ /// buf.push_back(1);
+ /// buf.push_back(3);
+ /// assert_eq!(buf.pop_back(), Some(3));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn pop_back(&mut self) -> Option<T> {
+ if self.is_empty() {
+ None
+ } else {
+ self.head = self.wrap_index(self.head - 1);
+ let head = self.head;
+ unsafe { Some(self.buffer_read(head)) }
+ }
+ }
+
+ #[inline]
+ fn is_contiguous(&self) -> bool {
+ self.tail <= self.head
+ }
+
+ /// Removes an element from anywhere in the ringbuf and returns it, replacing it with the last
+ /// element.
+ ///
+ /// This does not preserve ordering, but is O(1).
+ ///
+ /// Returns `None` if `index` is out of bounds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// assert_eq!(buf.swap_back_remove(0), None);
+ /// buf.push_back(5);
+ /// buf.push_back(99);
+ /// buf.push_back(15);
+ /// buf.push_back(20);
+ /// buf.push_back(10);
+ /// assert_eq!(buf.swap_back_remove(1), Some(99));
+ /// ```
+ #[unstable(feature = "collections",
+ reason = "the naming of this function may be altered")]
+ pub fn swap_back_remove(&mut self, index: usize) -> Option<T> {
+ let length = self.len();
+ if length > 0 && index < length - 1 {
+ self.swap(index, length - 1);
+ } else if index >= length {
+ return None;
+ }
+ self.pop_back()
+ }
+
+ /// Removes an element from anywhere in the ringbuf and returns it, replacing it with the first
+ /// element.
+ ///
+ /// This does not preserve ordering, but is O(1).
+ ///
+ /// Returns `None` if `index` is out of bounds.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// assert_eq!(buf.swap_front_remove(0), None);
+ /// buf.push_back(15);
+ /// buf.push_back(5);
+ /// buf.push_back(10);
+ /// buf.push_back(99);
+ /// buf.push_back(20);
+ /// assert_eq!(buf.swap_front_remove(3), Some(99));
+ /// ```
+ #[unstable(feature = "collections",
+ reason = "the naming of this function may be altered")]
+ pub fn swap_front_remove(&mut self, index: usize) -> Option<T> {
+ let length = self.len();
+ if length > 0 && index < length && index != 0 {
+ self.swap(index, 0);
+ } else if index >= length {
+ return None;
+ }
+ self.pop_front()
+ }
+
+ /// Inserts an element at position `i` within the ringbuf. Whichever
+ /// end is closer to the insertion point will be moved to make room,
+ /// and all the affected elements will be moved to new positions.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `i` is greater than ringbuf's length
+ ///
+ /// # Examples
+ /// ```rust
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// buf.push_back(10);
+ /// buf.push_back(12);
+ /// buf.insert(1,11);
+ /// assert_eq!(Some(&11), buf.get(1));
+ /// ```
+ pub fn insert(&mut self, i: usize, t: T) {
+ assert!(i <= self.len(), "index out of bounds");
+ if self.is_full() {
+ self.reserve(1);
+ debug_assert!(!self.is_full());
+ }
+
+ // Move the least number of elements in the ring buffer and insert
+ // the given object
+ //
+ // At most len/2 - 1 elements will be moved. O(min(n, n-i))
+ //
+ // There are three main cases:
+ // Elements are contiguous
+ // - special case when tail is 0
+ // Elements are discontiguous and the insert is in the tail section
+ // Elements are discontiguous and the insert is in the head section
+ //
+ // For each of those there are two more cases:
+ // Insert is closer to tail
+ // Insert is closer to head
+ //
+ // Key: H - self.head
+ // T - self.tail
+ // o - Valid element
+ // I - Insertion element
+ // A - The element that should be after the insertion point
+ // M - Indicates element was moved
+
+ let idx = self.wrap_index(self.tail + i);
+
+ let distance_to_tail = i;
+ let distance_to_head = self.len() - i;
+
+ let contiguous = self.is_contiguous();
+
+ match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
+ (true, true, _) if i == 0 => {
+ // push_front
+ //
+ // T
+ // I H
+ // [A o o o o o o . . . . . . . . .]
+ //
+ // H T
+ // [A o o o o o o o . . . . . I]
+ //
+
+ self.tail = self.wrap_index(self.tail - 1);
+ },
+ (true, true, _) => unsafe {
+ // contiguous, insert closer to tail:
+ //
+ // T I H
+ // [. . . o o A o o o o . . . . . .]
+ //
+ // T H
+ // [. . o o I A o o o o . . . . . .]
+ // M M
+ //
+ // contiguous, insert closer to tail and tail is 0:
+ //
+ //
+ // T I H
+ // [o o A o o o o . . . . . . . . .]
+ //
+ // H T
+ // [o I A o o o o o . . . . . . . o]
+ // M M
+
+ let new_tail = self.wrap_index(self.tail - 1);
+
+ self.copy(new_tail, self.tail, 1);
+ // Already moved the tail, so we only copy `i - 1` elements.
+ self.copy(self.tail, self.tail + 1, i - 1);
+
+ self.tail = new_tail;
+ },
+ (true, false, _) => unsafe {
+ // contiguous, insert closer to head:
+ //
+ // T I H
+ // [. . . o o o o A o o . . . . . .]
+ //
+ // T H
+ // [. . . o o o o I A o o . . . . .]
+ // M M M
+
+ self.copy(idx + 1, idx, self.head - idx);
+ self.head = self.wrap_index(self.head + 1);
+ },
+ (false, true, true) => unsafe {
+ // discontiguous, insert closer to tail, tail section:
+ //
+ // H T I
+ // [o o o o o o . . . . . o o A o o]
+ //
+ // H T
+ // [o o o o o o . . . . o o I A o o]
+ // M M
+
+ self.copy(self.tail - 1, self.tail, i);
+ self.tail -= 1;
+ },
+ (false, false, true) => unsafe {
+ // discontiguous, insert closer to head, tail section:
+ //
+ // H T I
+ // [o o . . . . . . . o o o o o A o]
+ //
+ // H T
+ // [o o o . . . . . . o o o o o I A]
+ // M M M M
+
+ // copy elements up to new head
+ self.copy(1, 0, self.head);
+
+ // copy last element into empty spot at bottom of buffer
+ self.copy(0, self.cap - 1, 1);
+
+ // move elements from idx to end forward not including ^ element
+ self.copy(idx + 1, idx, self.cap - 1 - idx);
+
+ self.head += 1;
+ },
+ (false, true, false) if idx == 0 => unsafe {
+ // discontiguous, insert is closer to tail, head section,
+ // and is at index zero in the internal buffer:
+ //
+ // I H T
+ // [A o o o o o o o o o . . . o o o]
+ //
+ // H T
+ // [A o o o o o o o o o . . o o o I]
+ // M M M
+
+ // copy elements up to new tail
+ self.copy(self.tail - 1, self.tail, self.cap - self.tail);
+
+ // copy last element into empty spot at bottom of buffer
+ self.copy(self.cap - 1, 0, 1);
+
+ self.tail -= 1;
+ },
+ (false, true, false) => unsafe {
+ // discontiguous, insert closer to tail, head section:
+ //
+ // I H T
+ // [o o o A o o o o o o . . . o o o]
+ //
+ // H T
+ // [o o I A o o o o o o . . o o o o]
+ // M M M M M M
+
+ // copy elements up to new tail
+ self.copy(self.tail - 1, self.tail, self.cap - self.tail);
+
+ // copy last element into empty spot at bottom of buffer
+ self.copy(self.cap - 1, 0, 1);
+
+ // move elements from idx-1 to end forward not including ^ element
+ self.copy(0, 1, idx - 1);
+
+ self.tail -= 1;
+ },
+ (false, false, false) => unsafe {
+ // discontiguous, insert closer to head, head section:
+ //
+ // I H T
+ // [o o o o A o o . . . . . . o o o]
+ //
+ // H T
+ // [o o o o I A o o . . . . . o o o]
+ // M M M
+
+ self.copy(idx + 1, idx, self.head - idx);
+ self.head += 1;
+ }
+ }
+
+ // tail might've been changed so we need to recalculate
+ let new_idx = self.wrap_index(self.tail + i);
+ unsafe {
+ self.buffer_write(new_idx, t);
+ }
+ }
+
+ /// Removes and returns the element at position `i` from the ringbuf.
+ /// Whichever end is closer to the removal point will be moved to make
+ /// room, and all the affected elements will be moved to new positions.
+ /// Returns `None` if `i` is out of bounds.
+ ///
+ /// # Examples
+ /// ```rust
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// buf.push_back(5);
+ /// buf.push_back(10);
+ /// buf.push_back(12);
+ /// buf.push_back(15);
+ /// buf.remove(2);
+ /// assert_eq!(Some(&15), buf.get(2));
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn remove(&mut self, i: usize) -> Option<T> {
+ if self.is_empty() || self.len() <= i {
+ return None;
+ }
+
+ // There are three main cases:
+ // Elements are contiguous
+ // Elements are discontiguous and the removal is in the tail section
+ // Elements are discontiguous and the removal is in the head section
+ // - special case when elements are technically contiguous,
+ // but self.head = 0
+ //
+ // For each of those there are two more cases:
+ // Insert is closer to tail
+ // Insert is closer to head
+ //
+ // Key: H - self.head
+ // T - self.tail
+ // o - Valid element
+ // x - Element marked for removal
+ // R - Indicates element that is being removed
+ // M - Indicates element was moved
+
+ let idx = self.wrap_index(self.tail + i);
+
+ let elem = unsafe {
+ Some(self.buffer_read(idx))
+ };
+
+ let distance_to_tail = i;
+ let distance_to_head = self.len() - i;
+
+ let contiguous = self.is_contiguous();
+
+ match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
+ (true, true, _) => unsafe {
+ // contiguous, remove closer to tail:
+ //
+ // T R H
+ // [. . . o o x o o o o . . . . . .]
+ //
+ // T H
+ // [. . . . o o o o o o . . . . . .]
+ // M M
+
+ self.copy(self.tail + 1, self.tail, i);
+ self.tail += 1;
+ },
+ (true, false, _) => unsafe {
+ // contiguous, remove closer to head:
+ //
+ // T R H
+ // [. . . o o o o x o o . . . . . .]
+ //
+ // T H
+ // [. . . o o o o o o . . . . . . .]
+ // M M
+
+ self.copy(idx, idx + 1, self.head - idx - 1);
+ self.head -= 1;
+ },
+ (false, true, true) => unsafe {
+ // discontiguous, remove closer to tail, tail section:
+ //
+ // H T R
+ // [o o o o o o . . . . . o o x o o]
+ //
+ // H T
+ // [o o o o o o . . . . . . o o o o]
+ // M M
+
+ self.copy(self.tail + 1, self.tail, i);
+ self.tail = self.wrap_index(self.tail + 1);
+ },
+ (false, false, false) => unsafe {
+ // discontiguous, remove closer to head, head section:
+ //
+ // R H T
+ // [o o o o x o o . . . . . . o o o]
+ //
+ // H T
+ // [o o o o o o . . . . . . . o o o]
+ // M M
+
+ self.copy(idx, idx + 1, self.head - idx - 1);
+ self.head -= 1;
+ },
+ (false, false, true) => unsafe {
+ // discontiguous, remove closer to head, tail section:
+ //
+ // H T R
+ // [o o o . . . . . . o o o o o x o]
+ //
+ // H T
+ // [o o . . . . . . . o o o o o o o]
+ // M M M M
+ //
+ // or quasi-discontiguous, remove next to head, tail section:
+ //
+ // H T R
+ // [. . . . . . . . . o o o o o x o]
+ //
+ // T H
+ // [. . . . . . . . . o o o o o o .]
+ // M
+
+ // draw in elements in the tail section
+ self.copy(idx, idx + 1, self.cap - idx - 1);
+
+ // Prevents underflow.
+ if self.head != 0 {
+ // copy first element into empty spot
+ self.copy(self.cap - 1, 0, 1);
+
+ // move elements in the head section backwards
+ self.copy(0, 1, self.head - 1);
+ }
+
+ self.head = self.wrap_index(self.head - 1);
+ },
+ (false, true, false) => unsafe {
+ // discontiguous, remove closer to tail, head section:
+ //
+ // R H T
+ // [o o x o o o o o o o . . . o o o]
+ //
+ // H T
+ // [o o o o o o o o o o . . . . o o]
+ // M M M M M
+
+ // draw in elements up to idx
+ self.copy(1, 0, idx);
+
+ // copy last element into empty spot
+ self.copy(0, self.cap - 1, 1);
+
+ // move elements from tail to end forward, excluding the last one
+ self.copy(self.tail + 1, self.tail, self.cap - self.tail - 1);
+
+ self.tail = self.wrap_index(self.tail + 1);
+ }
+ }
+
+ return elem;
+ }
+
+ /// Splits the collection into two at the given index.
+ ///
+ /// Returns a newly allocated `Self`. `self` contains elements `[0, at)`,
+ /// and the returned `Self` contains elements `[at, len)`.
+ ///
+ /// Note that the capacity of `self` does not change.
+ ///
+ /// # Panics
+ ///
+ /// Panics if `at > len`
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf: VecDeque<_> = vec![1,2,3].into_iter().collect();
+ /// let buf2 = buf.split_off(1);
+ /// // buf = [1], buf2 = [2, 3]
+ /// assert_eq!(buf.len(), 1);
+ /// assert_eq!(buf2.len(), 2);
+ /// ```
+ #[inline]
+ #[unstable(feature = "collections",
+ reason = "new API, waiting for dust to settle")]
+ pub fn split_off(&mut self, at: usize) -> Self {
+ let len = self.len();
+ assert!(at <= len, "`at` out of bounds");
+
+ let other_len = len - at;
+ let mut other = VecDeque::with_capacity(other_len);
+
+ unsafe {
+ let (first_half, second_half) = self.as_slices();
+
+ let first_len = first_half.len();
+ let second_len = second_half.len();
+ if at < first_len {
+ // `at` lies in the first half.
+ let amount_in_first = first_len - at;
+
+ ptr::copy_nonoverlapping_memory(*other.ptr,
+ first_half.as_ptr().offset(at as isize),
+ amount_in_first);
+
+ // just take all of the second half.
+ ptr::copy_nonoverlapping_memory(other.ptr.offset(amount_in_first as isize),
+ second_half.as_ptr(),
+ second_len);
+ } else {
+ // `at` lies in the second half, need to factor in the elements we skipped
+ // in the first half.
+ let offset = at - first_len;
+ let amount_in_second = second_len - offset;
+ ptr::copy_nonoverlapping_memory(*other.ptr,
+ second_half.as_ptr().offset(offset as isize),
+ amount_in_second);
+ }
+ }
+
+ // Cleanup where the ends of the buffers are
+ self.head = self.wrap_index(self.head - other_len);
+ other.head = other.wrap_index(other_len);
+
+ other
+ }
+
+ /// Moves all the elements of `other` into `Self`, leaving `other` empty.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the new number of elements in self overflows a `usize`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
+ /// let mut buf2: VecDeque<_> = vec![4, 5, 6].into_iter().collect();
+ /// buf.append(&mut buf2);
+ /// assert_eq!(buf.len(), 6);
+ /// assert_eq!(buf2.len(), 0);
+ /// ```
+ #[inline]
+ #[unstable(feature = "collections",
+ reason = "new API, waiting for dust to settle")]
+ pub fn append(&mut self, other: &mut Self) {
+ // naive impl
+ self.extend(other.drain());
+ }
+}
+
+impl<T: Clone> VecDeque<T> {
+ /// Modifies the ringbuf in-place so that `len()` is equal to new_len,
+ /// either by removing excess elements or by appending copies of a value to the back.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::VecDeque;
+ ///
+ /// let mut buf = VecDeque::new();
+ /// buf.push_back(5);
+ /// buf.push_back(10);
+ /// buf.push_back(15);
+ /// buf.resize(2, 0);
+ /// buf.resize(6, 20);
+ /// for (a, b) in [5, 10, 20, 20, 20, 20].iter().zip(buf.iter()) {
+ /// assert_eq!(a, b);
+ /// }
+ /// ```
+ #[unstable(feature = "collections",
+ reason = "matches collection reform specification; waiting on panic semantics")]
+ pub fn resize(&mut self, new_len: usize, value: T) {
+ let len = self.len();
+
+ if new_len > len {
+ self.extend(repeat(value).take(new_len - len))
+ } else {
+ self.truncate(new_len);
+ }
+ }
+}
+
+/// Returns the index in the underlying buffer for a given logical element index.
+#[inline]
+fn wrap_index(index: usize, size: usize) -> usize {
+ // size is always a power of 2
+ index & (size - 1)
+}
+
+/// Calculate the number of elements left to be read in the buffer
+#[inline]
+fn count(tail: usize, head: usize, size: usize) -> usize {
+ // size is always a power of 2
+ (head - tail) & (size - 1)
+}
+
+/// `VecDeque` iterator.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Iter<'a, T:'a> {
+ ring: &'a [T],
+ tail: usize,
+ head: usize
+}
+
+// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
+impl<'a, T> Clone for Iter<'a, T> {
+ fn clone(&self) -> Iter<'a, T> {
+ Iter {
+ ring: self.ring,
+ tail: self.tail,
+ head: self.head
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> Iterator for Iter<'a, T> {
+ type Item = &'a T;
+
+ #[inline]
+ fn next(&mut self) -> Option<&'a T> {
+ if self.tail == self.head {
+ return None;
+ }
+ let tail = self.tail;
+ self.tail = wrap_index(self.tail + 1, self.ring.len());
+ unsafe { Some(self.ring.get_unchecked(tail)) }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let len = count(self.tail, self.head, self.ring.len());
+ (len, Some(len))
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> DoubleEndedIterator for Iter<'a, T> {
+ #[inline]
+ fn next_back(&mut self) -> Option<&'a T> {
+ if self.tail == self.head {
+ return None;
+ }
+ self.head = wrap_index(self.head - 1, self.ring.len());
+ unsafe { Some(self.ring.get_unchecked(self.head)) }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> RandomAccessIterator for Iter<'a, T> {
+ #[inline]
+ fn indexable(&self) -> usize {
+ let (len, _) = self.size_hint();
+ len
+ }
+
+ #[inline]
+ fn idx(&mut self, j: usize) -> Option<&'a T> {
+ if j >= self.indexable() {
+ None
+ } else {
+ let idx = wrap_index(self.tail + j, self.ring.len());
+ unsafe { Some(self.ring.get_unchecked(idx)) }
+ }
+ }
+}
+
+// FIXME This was implemented differently from Iter because of a problem
+// with returning the mutable reference. I couldn't find a way to
+// make the lifetime checker happy so, but there should be a way.
+/// `VecDeque` mutable iterator.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct IterMut<'a, T:'a> {
+ ptr: *mut T,
+ tail: usize,
+ head: usize,
+ cap: usize,
+ marker: marker::PhantomData<&'a mut T>,
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> Iterator for IterMut<'a, T> {
+ type Item = &'a mut T;
+
+ #[inline]
+ fn next(&mut self) -> Option<&'a mut T> {
+ if self.tail == self.head {
+ return None;
+ }
+ let tail = self.tail;
+ self.tail = wrap_index(self.tail + 1, self.cap);
+
+ unsafe {
+ Some(&mut *self.ptr.offset(tail as isize))
+ }
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let len = count(self.tail, self.head, self.cap);
+ (len, Some(len))
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> DoubleEndedIterator for IterMut<'a, T> {
+ #[inline]
+ fn next_back(&mut self) -> Option<&'a mut T> {
+ if self.tail == self.head {
+ return None;
+ }
+ self.head = wrap_index(self.head - 1, self.cap);
+
+ unsafe {
+ Some(&mut *self.ptr.offset(self.head as isize))
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> ExactSizeIterator for IterMut<'a, T> {}
+
+/// A by-value VecDeque iterator
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct IntoIter<T> {
+ inner: VecDeque<T>,
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> Iterator for IntoIter<T> {
+ type Item = T;
+
+ #[inline]
+ fn next(&mut self) -> Option<T> {
+ self.inner.pop_front()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let len = self.inner.len();
+ (len, Some(len))
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> DoubleEndedIterator for IntoIter<T> {
+ #[inline]
+ fn next_back(&mut self) -> Option<T> {
+ self.inner.pop_back()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> ExactSizeIterator for IntoIter<T> {}
+
+/// A draining VecDeque iterator
+#[unstable(feature = "collections",
+ reason = "matches collection reform specification, waiting for dust to settle")]
+pub struct Drain<'a, T: 'a> {
+ inner: &'a mut VecDeque<T>,
+}
+
+#[unsafe_destructor]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T: 'a> Drop for Drain<'a, T> {
+ fn drop(&mut self) {
+ for _ in self.by_ref() {}
+ self.inner.head = 0;
+ self.inner.tail = 0;
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T: 'a> Iterator for Drain<'a, T> {
+ type Item = T;
+
+ #[inline]
+ fn next(&mut self) -> Option<T> {
+ self.inner.pop_front()
+ }
+
+ #[inline]
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let len = self.inner.len();
+ (len, Some(len))
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T: 'a> DoubleEndedIterator for Drain<'a, T> {
+ #[inline]
+ fn next_back(&mut self) -> Option<T> {
+ self.inner.pop_back()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A: PartialEq> PartialEq for VecDeque<A> {
+ fn eq(&self, other: &VecDeque<A>) -> bool {
+ self.len() == other.len() &&
+ self.iter().zip(other.iter()).all(|(a, b)| a.eq(b))
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A: Eq> Eq for VecDeque<A> {}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A: PartialOrd> PartialOrd for VecDeque<A> {
+ fn partial_cmp(&self, other: &VecDeque<A>) -> Option<Ordering> {
+ iter::order::partial_cmp(self.iter(), other.iter())
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A: Ord> Ord for VecDeque<A> {
+ #[inline]
+ fn cmp(&self, other: &VecDeque<A>) -> Ordering {
+ iter::order::cmp(self.iter(), other.iter())
+ }
+}
+
+#[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> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.len().hash(state);
+ for elt in self {
+ elt.hash(state);
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A> Index<usize> for VecDeque<A> {
+ type Output = A;
+
+ #[inline]
+ fn index(&self, i: &usize) -> &A {
+ self.get(*i).expect("Out of bounds access")
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A> IndexMut<usize> for VecDeque<A> {
+ #[inline]
+ fn index_mut(&mut self, i: &usize) -> &mut A {
+ self.get_mut(*i).expect("Out of bounds access")
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A> FromIterator<A> for VecDeque<A> {
+ fn from_iter<T: IntoIterator<Item=A>>(iterable: T) -> VecDeque<A> {
+ let iterator = iterable.into_iter();
+ let (lower, _) = iterator.size_hint();
+ let mut deq = VecDeque::with_capacity(lower);
+ deq.extend(iterator);
+ deq
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T> IntoIterator for VecDeque<T> {
+ type Item = T;
+ type IntoIter = IntoIter<T>;
+
+ fn into_iter(self) -> IntoIter<T> {
+ self.into_iter()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> IntoIterator for &'a VecDeque<T> {
+ type Item = &'a T;
+ type IntoIter = Iter<'a, T>;
+
+ fn into_iter(self) -> Iter<'a, T> {
+ self.iter()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> IntoIterator for &'a mut VecDeque<T> {
+ type Item = &'a mut T;
+ type IntoIter = IterMut<'a, T>;
+
+ fn into_iter(mut self) -> IterMut<'a, T> {
+ self.iter_mut()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<A> Extend<A> for VecDeque<A> {
+ fn extend<T: IntoIterator<Item=A>>(&mut self, iter: T) {
+ for elt in iter {
+ self.push_back(elt);
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: fmt::Debug> fmt::Debug for VecDeque<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ try!(write!(f, "VecDeque ["));
+
+ for (i, e) in self.iter().enumerate() {
+ if i != 0 { try!(write!(f, ", ")); }
+ try!(write!(f, "{:?}", *e));
+ }
+
+ write!(f, "]")
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use self::Taggy::*;
+ use self::Taggypar::*;
+ use prelude::*;
+ use core::iter;
+ use std::fmt::Debug;
+ use std::hash::{self, SipHasher};
+ use test::Bencher;
+ use test;
+
+ use super::VecDeque;
+
+ #[test]
+ #[allow(deprecated)]
+ fn test_simple() {
+ let mut d = VecDeque::new();
+ assert_eq!(d.len(), 0);
+ d.push_front(17);
+ d.push_front(42);
+ d.push_back(137);
+ assert_eq!(d.len(), 3);
+ d.push_back(137);
+ assert_eq!(d.len(), 4);
+ assert_eq!(*d.front().unwrap(), 42);
+ assert_eq!(*d.back().unwrap(), 137);
+ let mut i = d.pop_front();
+ assert_eq!(i, Some(42));
+ i = d.pop_back();
+ assert_eq!(i, Some(137));
+ i = d.pop_back();
+ assert_eq!(i, Some(137));
+ i = d.pop_back();
+ assert_eq!(i, Some(17));
+ assert_eq!(d.len(), 0);
+ d.push_back(3);
+ assert_eq!(d.len(), 1);
+ d.push_front(2);
+ assert_eq!(d.len(), 2);
+ d.push_back(4);
+ assert_eq!(d.len(), 3);
+ d.push_front(1);
+ assert_eq!(d.len(), 4);
+ debug!("{}", d[0]);
+ debug!("{}", d[1]);
+ debug!("{}", d[2]);
+ debug!("{}", d[3]);
+ assert_eq!(d[0], 1);
+ assert_eq!(d[1], 2);
+ assert_eq!(d[2], 3);
+ assert_eq!(d[3], 4);
+ }
+
+ #[cfg(test)]
+ fn test_parameterized<T:Clone + PartialEq + Debug>(a: T, b: T, c: T, d: T) {
+ let mut deq = VecDeque::new();
+ assert_eq!(deq.len(), 0);
+ deq.push_front(a.clone());
+ deq.push_front(b.clone());
+ deq.push_back(c.clone());
+ assert_eq!(deq.len(), 3);
+ deq.push_back(d.clone());
+ assert_eq!(deq.len(), 4);
+ assert_eq!((*deq.front().unwrap()).clone(), b.clone());
+ assert_eq!((*deq.back().unwrap()).clone(), d.clone());
+ assert_eq!(deq.pop_front().unwrap(), b.clone());
+ assert_eq!(deq.pop_back().unwrap(), d.clone());
+ assert_eq!(deq.pop_back().unwrap(), c.clone());
+ assert_eq!(deq.pop_back().unwrap(), a.clone());
+ assert_eq!(deq.len(), 0);
+ deq.push_back(c.clone());
+ assert_eq!(deq.len(), 1);
+ deq.push_front(b.clone());
+ assert_eq!(deq.len(), 2);
+ deq.push_back(d.clone());
+ assert_eq!(deq.len(), 3);
+ deq.push_front(a.clone());
+ assert_eq!(deq.len(), 4);
+ assert_eq!(deq[0].clone(), a.clone());
+ assert_eq!(deq[1].clone(), b.clone());
+ assert_eq!(deq[2].clone(), c.clone());
+ assert_eq!(deq[3].clone(), d.clone());
+ }
+
+ #[test]
+ fn test_push_front_grow() {
+ let mut deq = VecDeque::new();
+ for i in 0..66 {
+ deq.push_front(i);
+ }
+ assert_eq!(deq.len(), 66);
+
+ for i in 0..66 {
+ assert_eq!(deq[i], 65 - i);
+ }
+
+ let mut deq = VecDeque::new();
+ for i in 0..66 {
+ deq.push_back(i);
+ }
+
+ for i in 0..66 {
+ assert_eq!(deq[i], i);
+ }
+ }
+
+ #[test]
+ fn test_index() {
+ let mut deq = VecDeque::new();
+ for i in 1..4 {
+ deq.push_front(i);
+ }
+ assert_eq!(deq[1], 2);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_index_out_of_bounds() {
+ let mut deq = VecDeque::new();
+ for i in 1..4 {
+ deq.push_front(i);
+ }
+ deq[3];
+ }
+
+ #[bench]
+ fn bench_new(b: &mut test::Bencher) {
+ b.iter(|| {
+ let ring: VecDeque<i32> = VecDeque::new();
+ test::black_box(ring);
+ })
+ }
+
+ #[bench]
+ fn bench_push_back_100(b: &mut test::Bencher) {
+ let mut deq = VecDeque::with_capacity(101);
+ b.iter(|| {
+ for i in 0..100 {
+ deq.push_back(i);
+ }
+ deq.head = 0;
+ deq.tail = 0;
+ })
+ }
+
+ #[bench]
+ fn bench_push_front_100(b: &mut test::Bencher) {
+ let mut deq = VecDeque::with_capacity(101);
+ b.iter(|| {
+ for i in 0..100 {
+ deq.push_front(i);
+ }
+ deq.head = 0;
+ deq.tail = 0;
+ })
+ }
+
+ #[bench]
+ fn bench_pop_back_100(b: &mut test::Bencher) {
+ let mut deq= VecDeque::<i32>::with_capacity(101);
+
+ b.iter(|| {
+ deq.head = 100;
+ deq.tail = 0;
+ while !deq.is_empty() {
+ test::black_box(deq.pop_back());
+ }
+ })
+ }
+
+ #[bench]
+ fn bench_pop_front_100(b: &mut test::Bencher) {
+ let mut deq = VecDeque::<i32>::with_capacity(101);
+
+ b.iter(|| {
+ deq.head = 100;
+ deq.tail = 0;
+ while !deq.is_empty() {
+ test::black_box(deq.pop_front());
+ }
+ })
+ }
+
+ #[bench]
+ fn bench_grow_1025(b: &mut test::Bencher) {
+ b.iter(|| {
+ let mut deq = VecDeque::new();
+ for i in 0..1025 {
+ deq.push_front(i);
+ }
+ test::black_box(deq);
+ })
+ }
+
+ #[bench]
+ fn bench_iter_1000(b: &mut test::Bencher) {
+ let ring: VecDeque<_> = (0..1000).collect();
+
+ b.iter(|| {
+ let mut sum = 0;
+ for &i in &ring {
+ sum += i;
+ }
+ test::black_box(sum);
+ })
+ }
+
+ #[bench]
+ fn bench_mut_iter_1000(b: &mut test::Bencher) {
+ let mut ring: VecDeque<_> = (0..1000).collect();
+
+ b.iter(|| {
+ let mut sum = 0;
+ for i in &mut ring {
+ sum += *i;
+ }
+ test::black_box(sum);
+ })
+ }
+
+ #[derive(Clone, PartialEq, Debug)]
+ enum Taggy {
+ One(i32),
+ Two(i32, i32),
+ Three(i32, i32, i32),
+ }
+
+ #[derive(Clone, PartialEq, Debug)]
+ enum Taggypar<T> {
+ Onepar(T),
+ Twopar(T, T),
+ Threepar(T, T, T),
+ }
+
+ #[derive(Clone, PartialEq, Debug)]
+ struct RecCy {
+ x: i32,
+ y: i32,
+ t: Taggy
+ }
+
+ #[test]
+ fn test_param_int() {
+ test_parameterized::<i32>(5, 72, 64, 175);
+ }
+
+ #[test]
+ fn test_param_taggy() {
+ test_parameterized::<Taggy>(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42));
+ }
+
+ #[test]
+ fn test_param_taggypar() {
+ test_parameterized::<Taggypar<i32>>(Onepar::<i32>(1),
+ Twopar::<i32>(1, 2),
+ Threepar::<i32>(1, 2, 3),
+ Twopar::<i32>(17, 42));
+ }
+
+ #[test]
+ fn test_param_reccy() {
+ let reccy1 = RecCy { x: 1, y: 2, t: One(1) };
+ let reccy2 = RecCy { x: 345, y: 2, t: Two(1, 2) };
+ let reccy3 = RecCy { x: 1, y: 777, t: Three(1, 2, 3) };
+ let reccy4 = RecCy { x: 19, y: 252, t: Two(17, 42) };
+ test_parameterized::<RecCy>(reccy1, reccy2, reccy3, reccy4);
+ }
+
+ #[test]
+ fn test_with_capacity() {
+ let mut d = VecDeque::with_capacity(0);
+ d.push_back(1);
+ assert_eq!(d.len(), 1);
+ let mut d = VecDeque::with_capacity(50);
+ d.push_back(1);
+ assert_eq!(d.len(), 1);
+ }
+
+ #[test]
+ fn test_with_capacity_non_power_two() {
+ let mut d3 = VecDeque::with_capacity(3);
+ d3.push_back(1);
+
+ // X = None, | = lo
+ // [|1, X, X]
+ assert_eq!(d3.pop_front(), Some(1));
+ // [X, |X, X]
+ assert_eq!(d3.front(), None);
+
+ // [X, |3, X]
+ d3.push_back(3);
+ // [X, |3, 6]
+ d3.push_back(6);
+ // [X, X, |6]
+ assert_eq!(d3.pop_front(), Some(3));
+
+ // Pushing the lo past half way point to trigger
+ // the 'B' scenario for growth
+ // [9, X, |6]
+ d3.push_back(9);
+ // [9, 12, |6]
+ d3.push_back(12);
+
+ d3.push_back(15);
+ // There used to be a bug here about how the
+ // VecDeque made growth assumptions about the
+ // underlying Vec which didn't hold and lead
+ // to corruption.
+ // (Vec grows to next power of two)
+ //good- [9, 12, 15, X, X, X, X, |6]
+ //bug- [15, 12, X, X, X, |6, X, X]
+ assert_eq!(d3.pop_front(), Some(6));
+
+ // Which leads us to the following state which
+ // would be a failure case.
+ //bug- [15, 12, X, X, X, X, |X, X]
+ assert_eq!(d3.front(), Some(&9));
+ }
+
+ #[test]
+ fn test_reserve_exact() {
+ let mut d = VecDeque::new();
+ d.push_back(0);
+ d.reserve_exact(50);
+ assert!(d.capacity() >= 51);
+ }
+
+ #[test]
+ fn test_reserve() {
+ let mut d = VecDeque::new();
+ d.push_back(0);
+ d.reserve(50);
+ assert!(d.capacity() >= 51);
+ }
+
+ #[test]
+ fn test_swap() {
+ let mut d: VecDeque<_> = (0..5).collect();
+ d.pop_front();
+ d.swap(0, 3);
+ assert_eq!(d.iter().cloned().collect::<Vec<_>>(), vec!(4, 2, 3, 1));
+ }
+
+ #[test]
+ fn test_iter() {
+ let mut d = VecDeque::new();
+ assert_eq!(d.iter().next(), None);
+ assert_eq!(d.iter().size_hint(), (0, Some(0)));
+
+ for i in 0..5 {
+ d.push_back(i);
+ }
+ {
+ let b: &[_] = &[&0,&1,&2,&3,&4];
+ assert_eq!(d.iter().collect::<Vec<_>>(), b);
+ }
+
+ for i in 6..9 {
+ d.push_front(i);
+ }
+ {
+ let b: &[_] = &[&8,&7,&6,&0,&1,&2,&3,&4];
+ assert_eq!(d.iter().collect::<Vec<_>>(), b);
+ }
+
+ let mut it = d.iter();
+ let mut len = d.len();
+ loop {
+ match it.next() {
+ None => break,
+ _ => { len -= 1; assert_eq!(it.size_hint(), (len, Some(len))) }
+ }
+ }
+ }
+
+ #[test]
+ fn test_rev_iter() {
+ let mut d = VecDeque::new();
+ assert_eq!(d.iter().rev().next(), None);
+
+ for i in 0..5 {
+ d.push_back(i);
+ }
+ {
+ let b: &[_] = &[&4,&3,&2,&1,&0];
+ assert_eq!(d.iter().rev().collect::<Vec<_>>(), b);
+ }
+
+ for i in 6..9 {
+ d.push_front(i);
+ }
+ let b: &[_] = &[&4,&3,&2,&1,&0,&6,&7,&8];
+ assert_eq!(d.iter().rev().collect::<Vec<_>>(), b);
+ }
+
+ #[test]
+ fn test_mut_rev_iter_wrap() {
+ let mut d = VecDeque::with_capacity(3);
+ assert!(d.iter_mut().rev().next().is_none());
+
+ d.push_back(1);
+ d.push_back(2);
+ d.push_back(3);
+ assert_eq!(d.pop_front(), Some(1));
+ d.push_back(4);
+
+ assert_eq!(d.iter_mut().rev().cloned().collect::<Vec<_>>(),
+ vec![4, 3, 2]);
+ }
+
+ #[test]
+ fn test_mut_iter() {
+ let mut d = VecDeque::new();
+ assert!(d.iter_mut().next().is_none());
+
+ for i in 0..3 {
+ d.push_front(i);
+ }
+
+ for (i, elt) in d.iter_mut().enumerate() {
+ assert_eq!(*elt, 2 - i);
+ *elt = i;
+ }
+
+ {
+ let mut it = d.iter_mut();
+ assert_eq!(*it.next().unwrap(), 0);
+ assert_eq!(*it.next().unwrap(), 1);
+ assert_eq!(*it.next().unwrap(), 2);
+ assert!(it.next().is_none());
+ }
+ }
+
+ #[test]
+ fn test_mut_rev_iter() {
+ let mut d = VecDeque::new();
+ assert!(d.iter_mut().rev().next().is_none());
+
+ for i in 0..3 {
+ d.push_front(i);
+ }
+
+ for (i, elt) in d.iter_mut().rev().enumerate() {
+ assert_eq!(*elt, i);
+ *elt = i;
+ }
+
+ {
+ let mut it = d.iter_mut().rev();
+ assert_eq!(*it.next().unwrap(), 0);
+ assert_eq!(*it.next().unwrap(), 1);
+ assert_eq!(*it.next().unwrap(), 2);
+ assert!(it.next().is_none());
+ }
+ }
+
+ #[test]
+ fn test_into_iter() {
+
+ // Empty iter
+ {
+ let d: VecDeque<i32> = VecDeque::new();
+ let mut iter = d.into_iter();
+
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ }
+
+ // simple iter
+ {
+ let mut d = VecDeque::new();
+ for i in 0..5 {
+ d.push_back(i);
+ }
+
+ let b = vec![0,1,2,3,4];
+ assert_eq!(d.into_iter().collect::<Vec<_>>(), b);
+ }
+
+ // wrapped iter
+ {
+ let mut d = VecDeque::new();
+ for i in 0..5 {
+ d.push_back(i);
+ }
+ for i in 6..9 {
+ d.push_front(i);
+ }
+
+ let b = vec![8,7,6,0,1,2,3,4];
+ assert_eq!(d.into_iter().collect::<Vec<_>>(), b);
+ }
+
+ // partially used
+ {
+ let mut d = VecDeque::new();
+ for i in 0..5 {
+ d.push_back(i);
+ }
+ for i in 6..9 {
+ d.push_front(i);
+ }
+
+ let mut it = d.into_iter();
+ assert_eq!(it.size_hint(), (8, Some(8)));
+ assert_eq!(it.next(), Some(8));
+ assert_eq!(it.size_hint(), (7, Some(7)));
+ assert_eq!(it.next_back(), Some(4));
+ assert_eq!(it.size_hint(), (6, Some(6)));
+ assert_eq!(it.next(), Some(7));
+ assert_eq!(it.size_hint(), (5, Some(5)));
+ }
+ }
+
+ #[test]
+ fn test_drain() {
+
+ // Empty iter
+ {
+ let mut d: VecDeque<i32> = VecDeque::new();
+
+ {
+ let mut iter = d.drain();
+
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ assert_eq!(iter.next(), None);
+ assert_eq!(iter.size_hint(), (0, Some(0)));
+ }
+
+ assert!(d.is_empty());
+ }
+
+ // simple iter
+ {
+ let mut d = VecDeque::new();
+ for i in 0..5 {
+ d.push_back(i);
+ }
+
+ assert_eq!(d.drain().collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
+ assert!(d.is_empty());
+ }
+
+ // wrapped iter
+ {
+ let mut d = VecDeque::new();
+ for i in 0..5 {
+ d.push_back(i);
+ }
+ for i in 6..9 {
+ d.push_front(i);
+ }
+
+ assert_eq!(d.drain().collect::<Vec<_>>(), [8,7,6,0,1,2,3,4]);
+ assert!(d.is_empty());
+ }
+
+ // partially used
+ {
+ let mut d: VecDeque<_> = VecDeque::new();
+ for i in 0..5 {
+ d.push_back(i);
+ }
+ for i in 6..9 {
+ d.push_front(i);
+ }
+
+ {
+ let mut it = d.drain();
+ assert_eq!(it.size_hint(), (8, Some(8)));
+ assert_eq!(it.next(), Some(8));
+ assert_eq!(it.size_hint(), (7, Some(7)));
+ assert_eq!(it.next_back(), Some(4));
+ assert_eq!(it.size_hint(), (6, Some(6)));
+ assert_eq!(it.next(), Some(7));
+ assert_eq!(it.size_hint(), (5, Some(5)));
+ }
+ assert!(d.is_empty());
+ }
+ }
+
+ #[test]
+ fn test_from_iter() {
+ use core::iter;
+ let v = vec!(1,2,3,4,5,6,7);
+ let deq: VecDeque<_> = v.iter().cloned().collect();
+ let u: Vec<_> = deq.iter().cloned().collect();
+ assert_eq!(u, v);
+
+ let seq = iter::count(0, 2).take(256);
+ let deq: VecDeque<_> = seq.collect();
+ for (i, &x) in deq.iter().enumerate() {
+ assert_eq!(2*i, x);
+ }
+ assert_eq!(deq.len(), 256);
+ }
+
+ #[test]
+ fn test_clone() {
+ let mut d = VecDeque::new();
+ d.push_front(17);
+ d.push_front(42);
+ d.push_back(137);
+ d.push_back(137);
+ assert_eq!(d.len(), 4);
+ let mut e = d.clone();
+ assert_eq!(e.len(), 4);
+ while !d.is_empty() {
+ assert_eq!(d.pop_back(), e.pop_back());
+ }
+ assert_eq!(d.len(), 0);
+ assert_eq!(e.len(), 0);
+ }
+
+ #[test]
+ fn test_eq() {
+ let mut d = VecDeque::new();
+ assert!(d == VecDeque::with_capacity(0));
+ d.push_front(137);
+ d.push_front(17);
+ d.push_front(42);
+ d.push_back(137);
+ let mut e = VecDeque::with_capacity(0);
+ e.push_back(42);
+ e.push_back(17);
+ e.push_back(137);
+ e.push_back(137);
+ assert!(&e == &d);
+ e.pop_back();
+ e.push_back(0);
+ assert!(e != d);
+ e.clear();
+ assert!(e == VecDeque::new());
+ }
+
+ #[test]
+ fn test_hash() {
+ let mut x = VecDeque::new();
+ let mut y = VecDeque::new();
+
+ x.push_back(1);
+ x.push_back(2);
+ x.push_back(3);
+
+ y.push_back(0);
+ y.push_back(1);
+ y.pop_front();
+ y.push_back(2);
+ y.push_back(3);
+
+ assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y));
+ }
+
+ #[test]
+ fn test_ord() {
+ let x = VecDeque::new();
+ let mut y = VecDeque::new();
+ y.push_back(1);
+ y.push_back(2);
+ y.push_back(3);
+ assert!(x < y);
+ assert!(y > x);
+ assert!(x <= x);
+ assert!(x >= x);
+ }
+
+ #[test]
+ fn test_show() {
+ let ringbuf: VecDeque<_> = (0..10).collect();
+ assert_eq!(format!("{:?}", ringbuf), "VecDeque [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
+
+ let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"].iter()
+ .cloned()
+ .collect();
+ assert_eq!(format!("{:?}", ringbuf), "VecDeque [\"just\", \"one\", \"test\", \"more\"]");
+ }
+
+ #[test]
+ fn test_drop() {
+ static mut drops: i32 = 0;
+ struct Elem;
+ impl Drop for Elem {
+ fn drop(&mut self) {
+ unsafe { drops += 1; }
+ }
+ }
+
+ let mut ring = VecDeque::new();
+ ring.push_back(Elem);
+ ring.push_front(Elem);
+ ring.push_back(Elem);
+ ring.push_front(Elem);
+ drop(ring);
+
+ assert_eq!(unsafe {drops}, 4);
+ }
+
+ #[test]
+ fn test_drop_with_pop() {
+ static mut drops: i32 = 0;
+ struct Elem;
+ impl Drop for Elem {
+ fn drop(&mut self) {
+ unsafe { drops += 1; }
+ }
+ }
+
+ let mut ring = VecDeque::new();
+ ring.push_back(Elem);
+ ring.push_front(Elem);
+ ring.push_back(Elem);
+ ring.push_front(Elem);
+
+ drop(ring.pop_back());
+ drop(ring.pop_front());
+ assert_eq!(unsafe {drops}, 2);
+
+ drop(ring);
+ assert_eq!(unsafe {drops}, 4);
+ }
+
+ #[test]
+ fn test_drop_clear() {
+ static mut drops: i32 = 0;
+ struct Elem;
+ impl Drop for Elem {
+ fn drop(&mut self) {
+ unsafe { drops += 1; }
+ }
+ }
+
+ let mut ring = VecDeque::new();
+ ring.push_back(Elem);
+ ring.push_front(Elem);
+ ring.push_back(Elem);
+ ring.push_front(Elem);
+ ring.clear();
+ assert_eq!(unsafe {drops}, 4);
+
+ drop(ring);
+ assert_eq!(unsafe {drops}, 4);
+ }
+
+ #[test]
+ fn test_reserve_grow() {
+ // test growth path A
+ // [T o o H] -> [T o o H . . . . ]
+ let mut ring = VecDeque::with_capacity(4);
+ for i in 0..3 {
+ ring.push_back(i);
+ }
+ ring.reserve(7);
+ for i in 0..3 {
+ assert_eq!(ring.pop_front(), Some(i));
+ }
+
+ // test growth path B
+ // [H T o o] -> [. T o o H . . . ]
+ let mut ring = VecDeque::with_capacity(4);
+ for i in 0..1 {
+ ring.push_back(i);
+ assert_eq!(ring.pop_front(), Some(i));
+ }
+ for i in 0..3 {
+ ring.push_back(i);
+ }
+ ring.reserve(7);
+ for i in 0..3 {
+ assert_eq!(ring.pop_front(), Some(i));
+ }
+
+ // test growth path C
+ // [o o H T] -> [o o H . . . . T ]
+ let mut ring = VecDeque::with_capacity(4);
+ for i in 0..3 {
+ ring.push_back(i);
+ assert_eq!(ring.pop_front(), Some(i));
+ }
+ for i in 0..3 {
+ ring.push_back(i);
+ }
+ ring.reserve(7);
+ for i in 0..3 {
+ assert_eq!(ring.pop_front(), Some(i));
+ }
+ }
+
+ #[test]
+ fn test_get() {
+ let mut ring = VecDeque::new();
+ ring.push_back(0);
+ assert_eq!(ring.get(0), Some(&0));
+ assert_eq!(ring.get(1), None);
+
+ ring.push_back(1);
+ assert_eq!(ring.get(0), Some(&0));
+ assert_eq!(ring.get(1), Some(&1));
+ assert_eq!(ring.get(2), None);
+
+ ring.push_back(2);
+ assert_eq!(ring.get(0), Some(&0));
+ assert_eq!(ring.get(1), Some(&1));
+ assert_eq!(ring.get(2), Some(&2));
+ assert_eq!(ring.get(3), None);
+
+ assert_eq!(ring.pop_front(), Some(0));
+ assert_eq!(ring.get(0), Some(&1));
+ assert_eq!(ring.get(1), Some(&2));
+ assert_eq!(ring.get(2), None);
+
+ assert_eq!(ring.pop_front(), Some(1));
+ assert_eq!(ring.get(0), Some(&2));
+ assert_eq!(ring.get(1), None);
+
+ assert_eq!(ring.pop_front(), Some(2));
+ assert_eq!(ring.get(0), None);
+ assert_eq!(ring.get(1), None);
+ }
+
+ #[test]
+ fn test_get_mut() {
+ let mut ring = VecDeque::new();
+ for i in 0..3 {
+ ring.push_back(i);
+ }
+
+ match ring.get_mut(1) {
+ Some(x) => *x = -1,
+ None => ()
+ };
+
+ assert_eq!(ring.get_mut(0), Some(&mut 0));
+ assert_eq!(ring.get_mut(1), Some(&mut -1));
+ assert_eq!(ring.get_mut(2), Some(&mut 2));
+ assert_eq!(ring.get_mut(3), None);
+
+ assert_eq!(ring.pop_front(), Some(0));
+ assert_eq!(ring.get_mut(0), Some(&mut -1));
+ assert_eq!(ring.get_mut(1), Some(&mut 2));
+ assert_eq!(ring.get_mut(2), None);
+ }
+
+ #[test]
+ fn test_swap_front_back_remove() {
+ fn test(back: bool) {
+ // This test checks that every single combination of tail position and length is tested.
+ // Capacity 15 should be large enough to cover every case.
+ let mut tester = VecDeque::with_capacity(15);
+ let usable_cap = tester.capacity();
+ let final_len = usable_cap / 2;
+
+ for len in 0..final_len {
+ let expected = if back {
+ (0..len).collect()
+ } else {
+ (0..len).rev().collect()
+ };
+ for tail_pos in 0..usable_cap {
+ tester.tail = tail_pos;
+ tester.head = tail_pos;
+ if back {
+ for i in 0..len * 2 {
+ tester.push_front(i);
+ }
+ for i in 0..len {
+ assert_eq!(tester.swap_back_remove(i), Some(len * 2 - 1 - i));
+ }
+ } else {
+ for i in 0..len * 2 {
+ tester.push_back(i);
+ }
+ for i in 0..len {
+ let idx = tester.len() - 1 - i;
+ assert_eq!(tester.swap_front_remove(idx), Some(len * 2 - 1 - i));
+ }
+ }
+ assert!(tester.tail < tester.cap);
+ assert!(tester.head < tester.cap);
+ assert_eq!(tester, expected);
+ }
+ }
+ }
+ test(true);
+ test(false);
+ }
+
+ #[test]
+ fn test_insert() {
+ // This test checks that every single combination of tail position, length, and
+ // insertion position is tested. Capacity 15 should be large enough to cover every case.
+
+ let mut tester = VecDeque::with_capacity(15);
+ // can't guarantee we got 15, so have to get what we got.
+ // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
+ // this test isn't covering what it wants to
+ let cap = tester.capacity();
+
+
+ // len is the length *after* insertion
+ for len in 1..cap {
+ // 0, 1, 2, .., len - 1
+ let expected = iter::count(0, 1).take(len).collect();
+ for tail_pos in 0..cap {
+ for to_insert in 0..len {
+ tester.tail = tail_pos;
+ tester.head = tail_pos;
+ for i in 0..len {
+ if i != to_insert {
+ tester.push_back(i);
+ }
+ }
+ tester.insert(to_insert, to_insert);
+ assert!(tester.tail < tester.cap);
+ assert!(tester.head < tester.cap);
+ assert_eq!(tester, expected);
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_remove() {
+ // This test checks that every single combination of tail position, length, and
+ // removal position is tested. Capacity 15 should be large enough to cover every case.
+
+ let mut tester = VecDeque::with_capacity(15);
+ // can't guarantee we got 15, so have to get what we got.
+ // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
+ // this test isn't covering what it wants to
+ let cap = tester.capacity();
+
+ // len is the length *after* removal
+ for len in 0..cap - 1 {
+ // 0, 1, 2, .., len - 1
+ let expected = iter::count(0, 1).take(len).collect();
+ for tail_pos in 0..cap {
+ for to_remove in 0..len + 1 {
+ tester.tail = tail_pos;
+ tester.head = tail_pos;
+ for i in 0..len {
+ if i == to_remove {
+ tester.push_back(1234);
+ }
+ tester.push_back(i);
+ }
+ if to_remove == len {
+ tester.push_back(1234);
+ }
+ tester.remove(to_remove);
+ assert!(tester.tail < tester.cap);
+ assert!(tester.head < tester.cap);
+ assert_eq!(tester, expected);
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_shrink_to_fit() {
+ // This test checks that every single combination of head and tail position,
+ // is tested. Capacity 15 should be large enough to cover every case.
+
+ let mut tester = VecDeque::with_capacity(15);
+ // can't guarantee we got 15, so have to get what we got.
+ // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
+ // this test isn't covering what it wants to
+ let cap = tester.capacity();
+ tester.reserve(63);
+ let max_cap = tester.capacity();
+
+ for len in 0..cap + 1 {
+ // 0, 1, 2, .., len - 1
+ let expected = iter::count(0, 1).take(len).collect();
+ for tail_pos in 0..max_cap + 1 {
+ tester.tail = tail_pos;
+ tester.head = tail_pos;
+ tester.reserve(63);
+ for i in 0..len {
+ tester.push_back(i);
+ }
+ tester.shrink_to_fit();
+ assert!(tester.capacity() <= cap);
+ assert!(tester.tail < tester.cap);
+ assert!(tester.head < tester.cap);
+ assert_eq!(tester, expected);
+ }
+ }
+ }
+
+ #[test]
+ fn test_front() {
+ let mut ring = VecDeque::new();
+ ring.push_back(10);
+ ring.push_back(20);
+ assert_eq!(ring.front(), Some(&10));
+ ring.pop_front();
+ assert_eq!(ring.front(), Some(&20));
+ ring.pop_front();
+ assert_eq!(ring.front(), None);
+ }
+
+ #[test]
+ fn test_as_slices() {
+ let mut ring: VecDeque<i32> = VecDeque::with_capacity(127);
+ let cap = ring.capacity() as i32;
+ let first = cap/2;
+ let last = cap - first;
+ for i in 0..first {
+ ring.push_back(i);
+
+ let (left, right) = ring.as_slices();
+ let expected: Vec<_> = (0..i+1).collect();
+ assert_eq!(left, expected);
+ assert_eq!(right, []);
+ }
+
+ for j in -last..0 {
+ ring.push_front(j);
+ let (left, right) = ring.as_slices();
+ let expected_left: Vec<_> = (-last..j+1).rev().collect();
+ let expected_right: Vec<_> = (0..first).collect();
+ assert_eq!(left, expected_left);
+ assert_eq!(right, expected_right);
+ }
+
+ assert_eq!(ring.len() as i32, cap);
+ assert_eq!(ring.capacity() as i32, cap);
+ }
+
+ #[test]
+ fn test_as_mut_slices() {
+ let mut ring: VecDeque<i32> = VecDeque::with_capacity(127);
+ let cap = ring.capacity() as i32;
+ let first = cap/2;
+ let last = cap - first;
+ for i in 0..first {
+ ring.push_back(i);
+
+ let (left, right) = ring.as_mut_slices();
+ let expected: Vec<_> = (0..i+1).collect();
+ assert_eq!(left, expected);
+ assert_eq!(right, []);
+ }
+
+ for j in -last..0 {
+ ring.push_front(j);
+ let (left, right) = ring.as_mut_slices();
+ let expected_left: Vec<_> = (-last..j+1).rev().collect();
+ let expected_right: Vec<_> = (0..first).collect();
+ assert_eq!(left, expected_left);
+ assert_eq!(right, expected_right);
+ }
+
+ assert_eq!(ring.len() as i32, cap);
+ assert_eq!(ring.capacity() as i32, cap);
+ }
+
+ #[test]
+ fn test_split_off() {
+ // This test checks that every single combination of tail position, length, and
+ // split position is tested. Capacity 15 should be large enough to cover every case.
+
+ let mut tester = VecDeque::with_capacity(15);
+ // can't guarantee we got 15, so have to get what we got.
+ // 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
+ // this test isn't covering what it wants to
+ let cap = tester.capacity();
+
+ // len is the length *before* splitting
+ for len in 0..cap {
+ // index to split at
+ for at in 0..len + 1 {
+ // 0, 1, 2, .., at - 1 (may be empty)
+ let expected_self = iter::count(0, 1).take(at).collect();
+ // at, at + 1, .., len - 1 (may be empty)
+ let expected_other = iter::count(at, 1).take(len - at).collect();
+
+ for tail_pos in 0..cap {
+ tester.tail = tail_pos;
+ tester.head = tail_pos;
+ for i in 0..len {
+ tester.push_back(i);
+ }
+ let result = tester.split_off(at);
+ assert!(tester.tail < tester.cap);
+ assert!(tester.head < tester.cap);
+ assert!(result.tail < result.cap);
+ assert!(result.head < result.cap);
+ assert_eq!(tester, expected_self);
+ assert_eq!(result, expected_other);
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_append() {
+ let mut a: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
+ let mut b: VecDeque<_> = vec![4, 5, 6].into_iter().collect();
+
+ // normal append
+ a.append(&mut b);
+ assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
+ assert_eq!(b.iter().cloned().collect(), vec![]);
+
+ // append nothing to something
+ a.append(&mut b);
+ assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
+ assert_eq!(b.iter().cloned().collect(), vec![]);
+
+ // append something to nothing
+ b.append(&mut a);
+ assert_eq!(b.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
+ assert_eq!(a.iter().cloned().collect(), vec![]);
+ }
+}
use core::cmp::Ordering;
use core::default::Default;
use core::fmt;
-use core::hash::{Hash, Writer, Hasher};
+use core::hash::{Hash, Hasher};
+#[cfg(stage0)] use core::hash::Writer;
use core::iter::{Enumerate, FilterMap, Map, FromIterator, IntoIterator};
use core::iter;
use core::mem::replace;
fn default() -> VecMap<V> { VecMap::new() }
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl<V:Clone> Clone for VecMap<V> {
#[inline]
fn clone(&self) -> 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
count.hash(state);
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
+#[cfg(not(stage0))]
+impl<V: Hash> Hash for VecMap<V> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ // 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);
+ }
+}
impl<V> VecMap<V> {
/// Creates an empty `VecMap`.
#[stable(feature = "rust1", since = "1.0.0")]
impl<V> FromIterator<(usize, V)> for VecMap<V> {
- fn from_iter<Iter: Iterator<Item=(usize, V)>>(iter: Iter) -> VecMap<V> {
+ fn from_iter<I: IntoIterator<Item=(usize, V)>>(iter: I) -> VecMap<V> {
let mut map = VecMap::new();
map.extend(iter);
map
#[stable(feature = "rust1", since = "1.0.0")]
impl<V> Extend<(usize, V)> for VecMap<V> {
- fn extend<Iter: Iterator<Item=(usize, V)>>(&mut self, iter: Iter) {
+ fn extend<I: IntoIterator<Item=(usize, V)>>(&mut self, iter: I) {
for (k, v) in iter {
self.insert(k, v);
}
}
#[unstable(feature = "collections")]
-pub struct Drain<'a, V> {
+pub struct Drain<'a, V:'a> {
iter: FilterMap<
Enumerate<vec::Drain<'a, Option<V>>>,
fn((usize, Option<V>)) -> Option<(usize, V)>>
use clone::Clone;
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use fmt;
-use hash::{Hash, Hasher, self};
+use hash::{Hash, self};
use iter::IntoIterator;
use marker::Copy;
use ops::Deref;
}
}
- impl<S: hash::Writer + Hasher, T: Hash<S>> Hash<S> for [T; $N] {
+ #[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)
+ Hash::hash(&self[..], state)
+ }
+ }
+ #[cfg(not(stage0))]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ impl<T: Hash> Hash for [T; $N] {
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ Hash::hash(&self[..], state)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: fmt::Debug> fmt::Debug for [T; $N] {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- fmt::Debug::fmt(&&self[], f)
+ fmt::Debug::fmt(&&self[..], f)
}
}
impl<A, B> PartialEq<[B; $N]> for [A; $N] where A: PartialEq<B> {
#[inline]
fn eq(&self, other: &[B; $N]) -> bool {
- &self[] == &other[]
+ &self[..] == &other[..]
}
#[inline]
fn ne(&self, other: &[B; $N]) -> bool {
- &self[] != &other[]
+ &self[..] != &other[..]
}
}
{
#[inline(always)]
fn eq(&self, other: &Rhs) -> bool {
- PartialEq::eq(&self[], &**other)
+ PartialEq::eq(&self[..], &**other)
}
#[inline(always)]
fn ne(&self, other: &Rhs) -> bool {
- PartialEq::ne(&self[], &**other)
+ PartialEq::ne(&self[..], &**other)
}
}
{
#[inline(always)]
fn eq(&self, other: &[B; $N]) -> bool {
- PartialEq::eq(&**self, &other[])
+ PartialEq::eq(&**self, &other[..])
}
#[inline(always)]
fn ne(&self, other: &[B; $N]) -> bool {
- PartialEq::ne(&**self, &other[])
+ PartialEq::ne(&**self, &other[..])
}
}
impl<T:PartialOrd> PartialOrd for [T; $N] {
#[inline]
fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
- PartialOrd::partial_cmp(&&self[], &&other[])
+ PartialOrd::partial_cmp(&&self[..], &&other[..])
}
#[inline]
fn lt(&self, other: &[T; $N]) -> bool {
- PartialOrd::lt(&&self[], &&other[])
+ PartialOrd::lt(&&self[..], &&other[..])
}
#[inline]
fn le(&self, other: &[T; $N]) -> bool {
- PartialOrd::le(&&self[], &&other[])
+ PartialOrd::le(&&self[..], &&other[..])
}
#[inline]
fn ge(&self, other: &[T; $N]) -> bool {
- PartialOrd::ge(&&self[], &&other[])
+ PartialOrd::ge(&&self[..], &&other[..])
}
#[inline]
fn gt(&self, other: &[T; $N]) -> bool {
- PartialOrd::gt(&&self[], &&other[])
+ PartialOrd::gt(&&self[..], &&other[..])
}
}
impl<T:Ord> Ord for [T; $N] {
#[inline]
fn cmp(&self, other: &[T; $N]) -> Ordering {
- Ord::cmp(&&self[], &&other[])
+ Ord::cmp(&&self[..], &&other[..])
}
}
)+
use intrinsics;
use cell::UnsafeCell;
+use marker::PhantomData;
/// A boolean type which can be safely shared between threads.
#[stable(feature = "rust1", since = "1.0.0")]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct AtomicPtr<T> {
p: UnsafeCell<usize>,
+ _marker: PhantomData<*mut T>,
}
unsafe impl<T> Sync for AtomicPtr<T> {}
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(p: *mut T) -> AtomicPtr<T> {
- AtomicPtr { p: UnsafeCell::new(p as usize) }
+ AtomicPtr { p: UnsafeCell::new(p as usize),
+ _marker: PhantomData }
}
/// Loads a value from the pointer.
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! A module for working with borrowed data.
-//!
-//! # The `BorrowFrom` traits
-//!
-//! In general, there may be several ways to "borrow" a piece of data. The
-//! typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
-//! (a mutable borrow). But types like `Vec<T>` provide additional kinds of
-//! borrows: the borrowed slices `&[T]` and `&mut [T]`.
-//!
-//! When writing generic code, it is often desirable to abstract over all ways
-//! of borrowing data from a given type. That is the role of the `BorrowFrom`
-//! trait: if `T: BorrowFrom<U>`, then `&T` can be borrowed from `&U`. A given
-//! type can be borrowed as multiple different types. In particular, `Vec<T>:
-//! BorrowFrom<Vec<T>>` and `[T]: BorrowFrom<Vec<T>>`.
-//!
-//! # The `ToOwned` trait
-//!
-//! Some types make it possible to go from borrowed to owned, usually by
-//! implementing the `Clone` trait. But `Clone` works only for going from `&T`
-//! to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
-//! from any borrow of a given type.
-//!
-//! # The `Cow` (clone-on-write) type
-//!
-//! The type `Cow` is a smart pointer providing clone-on-write functionality: it
-//! can enclose and provide immutable access to borrowed data, and clone the
-//! data lazily when mutation or ownership is required. The type is designed to
-//! work with general borrowed data via the `BorrowFrom` trait.
-//!
-//! `Cow` implements both `Deref`, which means that you can call
-//! non-mutating methods directly on the data it encloses. If mutation
-//! is desired, `to_mut` will obtain a mutable references to an owned
-//! value, cloning if necessary.
-
-#![unstable(feature = "core",
- reason = "recently added as part of collections reform")]
-
-use clone::Clone;
-use cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
-use fmt;
-use marker::Sized;
-use ops::Deref;
-use option::Option;
-use self::Cow::*;
-
-/// A trait for borrowing data.
-#[old_orphan_check]
-pub trait BorrowFrom<Owned: ?Sized> {
- /// Immutably borrow from an owned value.
- fn borrow_from(owned: &Owned) -> &Self;
-}
-
-/// A trait for mutably borrowing data.
-#[old_orphan_check]
-pub trait BorrowFromMut<Owned: ?Sized> : BorrowFrom<Owned> {
- /// Mutably borrow from an owned value.
- fn borrow_from_mut(owned: &mut Owned) -> &mut Self;
-}
-
-impl<T: ?Sized> BorrowFrom<T> for T {
- fn borrow_from(owned: &T) -> &T { owned }
-}
-
-impl<T: ?Sized> BorrowFromMut<T> for T {
- fn borrow_from_mut(owned: &mut T) -> &mut T { owned }
-}
-
-impl<'a, T: ?Sized> BorrowFrom<&'a T> for T {
- fn borrow_from<'b>(owned: &'b &'a T) -> &'b T { &**owned }
-}
-
-impl<'a, T: ?Sized> BorrowFrom<&'a mut T> for T {
- fn borrow_from<'b>(owned: &'b &'a mut T) -> &'b T { &**owned }
-}
-
-impl<'a, T: ?Sized> BorrowFromMut<&'a mut T> for T {
- fn borrow_from_mut<'b>(owned: &'b mut &'a mut T) -> &'b mut T { &mut **owned }
-}
-
-impl<'a, T, B: ?Sized> BorrowFrom<Cow<'a, T, B>> for B where B: ToOwned<T> {
- fn borrow_from<'b>(owned: &'b Cow<'a, T, B>) -> &'b B {
- &**owned
- }
-}
-
-/// Trait for moving into a `Cow`
-#[old_orphan_check]
-pub trait IntoCow<'a, T, B: ?Sized> {
- /// Moves `self` into `Cow`
- fn into_cow(self) -> Cow<'a, T, B>;
-}
-
-impl<'a, T, B: ?Sized> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned<T> {
- fn into_cow(self) -> Cow<'a, T, B> {
- self
- }
-}
-
-/// A generalization of Clone to borrowed data.
-#[old_orphan_check]
-pub trait ToOwned<Owned>: BorrowFrom<Owned> {
- /// Create owned data from borrowed data, usually by copying.
- fn to_owned(&self) -> Owned;
-}
-
-impl<T> ToOwned<T> for T where T: Clone {
- fn to_owned(&self) -> T { self.clone() }
-}
-
-/// A clone-on-write smart pointer.
-///
-/// # Example
-///
-/// ```rust
-/// use std::borrow::Cow;
-///
-/// fn abs_all(input: &mut Cow<Vec<int>, [int]>) {
-/// for i in 0..input.len() {
-/// let v = input[i];
-/// if v < 0 {
-/// // clones into a vector the first time (if not already owned)
-/// input.to_mut()[i] = -v;
-/// }
-/// }
-/// }
-/// ```
-pub enum Cow<'a, T, B: ?Sized + 'a> where B: ToOwned<T> {
- /// Borrowed data.
- Borrowed(&'a B),
-
- /// Owned data.
- Owned(T)
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, B: ?Sized> Clone for Cow<'a, T, B> where B: ToOwned<T> {
- fn clone(&self) -> Cow<'a, T, B> {
- match *self {
- Borrowed(b) => Borrowed(b),
- Owned(ref o) => {
- let b: &B = BorrowFrom::borrow_from(o);
- Owned(b.to_owned())
- },
- }
- }
-}
-
-impl<'a, T, B: ?Sized> Cow<'a, T, B> where B: ToOwned<T> {
- /// Acquire a mutable reference to the owned form of the data.
- ///
- /// Copies the data if it is not already owned.
- pub fn to_mut(&mut self) -> &mut T {
- match *self {
- Borrowed(borrowed) => {
- *self = Owned(borrowed.to_owned());
- self.to_mut()
- }
- Owned(ref mut owned) => owned
- }
- }
-
- /// Extract the owned data.
- ///
- /// Copies the data if it is not already owned.
- pub fn into_owned(self) -> T {
- match self {
- Borrowed(borrowed) => borrowed.to_owned(),
- Owned(owned) => owned
- }
- }
-
- /// Returns true if this `Cow` wraps a borrowed value
- pub fn is_borrowed(&self) -> bool {
- match *self {
- Borrowed(_) => true,
- _ => false,
- }
- }
-
- /// Returns true if this `Cow` wraps an owned value
- pub fn is_owned(&self) -> bool {
- match *self {
- Owned(_) => true,
- _ => false,
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, B: ?Sized> Deref for Cow<'a, T, B> where B: ToOwned<T> {
- type Target = B;
-
- fn deref(&self) -> &B {
- match *self {
- Borrowed(borrowed) => borrowed,
- Owned(ref owned) => BorrowFrom::borrow_from(owned)
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, B: ?Sized> Eq for Cow<'a, T, B> where B: Eq + ToOwned<T> {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, B: ?Sized> Ord for Cow<'a, T, B> where B: Ord + ToOwned<T> {
- #[inline]
- fn cmp(&self, other: &Cow<'a, T, B>) -> Ordering {
- Ord::cmp(&**self, &**other)
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, T, U, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, U, C>> for Cow<'a, T, B> where
- B: PartialEq<C> + ToOwned<T>,
- C: ToOwned<U>,
-{
- #[inline]
- fn eq(&self, other: &Cow<'b, U, C>) -> bool {
- PartialEq::eq(&**self, &**other)
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, B: ?Sized> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned<T> {
- #[inline]
- fn partial_cmp(&self, other: &Cow<'a, T, B>) -> Option<Ordering> {
- PartialOrd::partial_cmp(&**self, &**other)
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, B: ?Sized> fmt::Debug for Cow<'a, T, B> where
- B: fmt::Debug + ToOwned<T>,
- T: fmt::Debug,
-{
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Borrowed(ref b) => fmt::Debug::fmt(b, f),
- Owned(ref o) => fmt::Debug::fmt(o, f),
- }
- }
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, B: ?Sized> fmt::Display for Cow<'a, T, B> where
- B: fmt::Display + ToOwned<T>,
- T: fmt::Display,
-{
- fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- Borrowed(ref b) => fmt::Display::fmt(b, f),
- Owned(ref o) => fmt::Display::fmt(o, f),
- }
- }
-}
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn cmp(&self, other: &Ordering) -> Ordering {
- (*self as int).cmp(&(*other as int))
+ (*self as i32).cmp(&(*other as i32))
}
}
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
- (*self as int).partial_cmp(&(*other as int))
+ (*self as i32).partial_cmp(&(*other as i32))
}
}
}
partial_eq_impl! {
- bool char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64
+ bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64
}
macro_rules! eq_impl {
)*)
}
- eq_impl! { () bool char uint u8 u16 u32 u64 int i8 i16 i32 i64 }
+ eq_impl! { () bool char usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
macro_rules! partial_ord_impl {
($($t:ty)*) => ($(
}
}
- partial_ord_impl! { char uint u8 u16 u32 u64 int i8 i16 i32 i64 f32 f64 }
+ partial_ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
macro_rules! ord_impl {
($($t:ty)*) => ($(
}
}
- ord_impl! { char uint u8 u16 u32 u64 int i8 i16 i32 i64 }
+ ord_impl! { char usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
// & pointers
//!
//! ```
//! struct SomeOptions {
-//! foo: int,
+//! foo: i32,
//! bar: f32,
//! }
//! ```
//!
//! #[derive(Default)]
//! struct SomeOptions {
-//! foo: int,
+//! foo: i32,
//! bar: f32,
//! }
//!
//!
//! #[derive(Default)]
//! struct SomeOptions {
-//! foo: int,
+//! foo: i32,
//! bar: f32,
//! baz: Kind,
//! }
//! # use std::default::Default;
//! # #[derive(Default)]
//! # struct SomeOptions {
-//! # foo: int,
+//! # foo: i32,
//! # bar: f32,
//! # }
//! fn main() {
/// ```
/// #[derive(Default)]
/// struct SomeOptions {
-/// foo: int,
+/// foo: i32,
/// bar: f32,
/// }
/// ```
///
/// let i: i8 = Default::default();
/// let (x, y): (Option<String>, f64) = Default::default();
- /// let (a, b, (c, d)): (int, uint, (bool, bool)) = Default::default();
+ /// let (a, b, (c, d)): (i32, u32, (bool, bool)) = Default::default();
/// ```
///
/// Making your own:
default_impl! { bool, false }
default_impl! { char, '\x00' }
-default_impl! { uint, 0 }
+default_impl! { usize, 0 }
default_impl! { u8, 0 }
default_impl! { u16, 0 }
default_impl! { u32, 0 }
default_impl! { u64, 0 }
-default_impl! { int, 0 }
+default_impl! { isize, 0 }
default_impl! { i8, 0 }
default_impl! { i16, 0 }
default_impl! { i32, 0 }
use cell::{Cell, RefCell, Ref, RefMut, BorrowState};
use char::CharExt;
use iter::{Iterator, IteratorExt};
-use marker::{Copy, Sized};
+use marker::{Copy, PhantomData, Sized};
use mem;
use option::Option;
use option::Option::{Some, None};
f.pad("()")
}
}
+impl<T> Debug for PhantomData<T> {
+ fn fmt(&self, f: &mut Formatter) -> Result {
+ f.pad("PhantomData")
+ }
+}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Copy + Debug> Debug for Cell<T> {
//! the trait `Hash`:
//!
//! ```rust
-//! use std::hash::{hash, Hash, Hasher, Writer, SipHasher};
+//! use std::hash::{hash, Hash, Hasher, SipHasher};
//!
//! struct Person {
//! id: uint,
//! phone: u64,
//! }
//!
-//! impl<H: Hasher + Writer> Hash<H> for Person {
-//! fn hash(&self, state: &mut H) {
+//! impl Hash for Person {
+//! fn hash<H: Hasher>(&self, state: &mut H) {
//! self.id.hash(state);
//! self.phone.hash(state);
//! }
//! assert_eq!(hash::<_, SipHasher>(&person1), hash::<_, SipHasher>(&person2));
//! ```
-#![unstable(feature = "hash",
- reason = "module was recently redesigned")]
+#![stable(feature = "rust1", since = "1.0.0")]
use prelude::*;
-use borrow::{Cow, ToOwned};
use default::Default;
use mem;
-use num::Int;
pub use self::sip::SipHasher;
/// 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(not(stage0))]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait Hash {
+ /// Feeds this value into the state given, updating the hasher as necessary.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn hash<H: Hasher>(&self, state: &mut H);
+
+ /// Feeds a slice of this type into the state provided.
+ #[unstable(feature = "hash", reason = "module was recently redesigned")]
+ fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized {
+ for piece in data {
+ piece.hash(state);
+ }
+ }
+}
+
+/// 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.
+#[stable(feature = "rust1", since = "1.0.0")]
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.
+ #[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")]
+ fn finish(&self) -> u64;
+
+ /// Writes some data into this `Hasher`
+ #[cfg(not(stage0))]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn write(&mut self, bytes: &[u8]);
+
+ /// Write a single `u8` into this hasher
+ #[cfg(not(stage0))]
+ #[inline]
+ #[unstable(feature = "hash", reason = "module was recently redesigned")]
+ fn write_u8(&mut self, i: u8) { self.write(&[i]) }
+ /// Write a single `u16` into this hasher.
+ #[cfg(not(stage0))]
+ #[inline]
+ #[unstable(feature = "hash", reason = "module was recently redesigned")]
+ fn write_u16(&mut self, i: u16) {
+ self.write(&unsafe { mem::transmute::<_, [u8; 2]>(i) })
+ }
+ /// Write a single `u32` into this hasher.
+ #[cfg(not(stage0))]
+ #[inline]
+ #[unstable(feature = "hash", reason = "module was recently redesigned")]
+ fn write_u32(&mut self, i: u32) {
+ self.write(&unsafe { mem::transmute::<_, [u8; 4]>(i) })
+ }
+ /// Write a single `u64` into this hasher.
+ #[cfg(not(stage0))]
+ #[inline]
+ #[unstable(feature = "hash", reason = "module was recently redesigned")]
+ fn write_u64(&mut self, i: u64) {
+ self.write(&unsafe { mem::transmute::<_, [u8; 8]>(i) })
+ }
+ /// Write a single `usize` into this hasher.
+ #[cfg(not(stage0))]
+ #[inline]
+ #[unstable(feature = "hash", reason = "module was recently redesigned")]
+ fn write_usize(&mut self, i: usize) {
+ if cfg!(target_pointer_width = "32") {
+ self.write_u32(i as u32)
+ } else {
+ self.write_u64(i as u64)
+ }
+ }
+
+ /// Write a single `i8` into this hasher.
+ #[cfg(not(stage0))]
+ #[inline]
+ #[unstable(feature = "hash", reason = "module was recently redesigned")]
+ fn write_i8(&mut self, i: i8) { self.write_u8(i as u8) }
+ /// Write a single `i16` into this hasher.
+ #[cfg(not(stage0))]
+ #[inline]
+ #[unstable(feature = "hash", reason = "module was recently redesigned")]
+ fn write_i16(&mut self, i: i16) { self.write_u16(i as u16) }
+ /// Write a single `i32` into this hasher.
+ #[cfg(not(stage0))]
+ #[inline]
+ #[unstable(feature = "hash", reason = "module was recently redesigned")]
+ fn write_i32(&mut self, i: i32) { self.write_u32(i as u32) }
+ /// Write a single `i64` into this hasher.
+ #[cfg(not(stage0))]
+ #[inline]
+ #[unstable(feature = "hash", reason = "module was recently redesigned")]
+ fn write_i64(&mut self, i: i64) { self.write_u64(i as u64) }
+ /// Write a single `isize` into this hasher.
+ #[cfg(not(stage0))]
+ #[inline]
+ #[unstable(feature = "hash", reason = "module was recently redesigned")]
+ 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
#[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]);
}
///
/// The specified value will be hashed with this hasher and then the resulting
/// 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")]
+pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
+ let mut h: H = Default::default();
+ value.hash(&mut h);
+ h.finish()
+}
+
//////////////////////////////////////////////////////////////////////////////
-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 as $uty).to_le() as $ty)
- };
- state.write(&a)
+#[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_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 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)
+ 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);
- )*
+ 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_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<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a 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<'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 *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);
+ }
}
}
-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);
+#[cfg(not(stage0))]
+mod impls {
+ use prelude::*;
+
+ use slice;
+ use super::*;
+
+ macro_rules! impl_write {
+ ($(($ty:ident, $meth:ident),)*) => {$(
+ #[stable(feature = "rust1", since = "1.0.0")]
+ impl Hash for $ty {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ state.$meth(*self)
+ }
+
+ fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
+ let newlen = data.len() * ::$ty::BYTES;
+ let ptr = data.as_ptr() as *const u8;
+ state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
+ }
+ }
+ )*}
}
-}
-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);
+ impl_write! {
+ (u8, write_u8),
+ (u16, write_u16),
+ (u32, write_u32),
+ (u64, write_u64),
+ (usize, write_usize),
+ (i8, write_i8),
+ (i16, write_i16),
+ (i32, write_i32),
+ (i64, write_i64),
+ (isize, write_isize),
}
-}
-impl<'a, T, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, T, B>
- where B: Hash<S> + ToOwned<T>
-{
- #[inline]
- fn hash(&self, state: &mut S) {
- Hash::hash(&**self, state)
+ #[stable(feature = "rust1", since = "1.0.0")]
+ impl Hash for bool {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ state.write_u8(*self as u8)
+ }
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ impl Hash for char {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ state.write_u32(*self as u32)
+ }
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ impl Hash for str {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ state.write(self.as_bytes());
+ state.write_u8(0xff)
+ }
+ }
+
+ macro_rules! impl_hash_tuple {
+ () => (
+ #[stable(feature = "rust1", since = "1.0.0")]
+ impl Hash for () {
+ fn hash<H: Hasher>(&self, _state: &mut H) {}
+ }
+ );
+
+ ( $($name:ident)+) => (
+ #[stable(feature = "rust1", since = "1.0.0")]
+ impl<$($name: Hash),*> Hash for ($($name,)*) {
+ #[allow(non_snake_case)]
+ fn hash<S: Hasher>(&self, state: &mut S) {
+ let ($(ref $name,)*) = *self;
+ $($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 }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ impl<T: Hash> Hash for [T] {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.len().hash(state);
+ Hash::hash_slice(self, state)
+ }
+ }
+
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ impl<'a, T: ?Sized + Hash> Hash for &'a T {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ (**self).hash(state);
+ }
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ impl<'a, T: ?Sized + Hash> Hash for &'a mut T {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ (**self).hash(state);
+ }
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ impl<T> Hash for *const T {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ state.write_usize(*self as usize)
+ }
+ }
+
+ #[stable(feature = "rust1", since = "1.0.0")]
+ impl<T> Hash for *mut T {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ state.write_usize(*self as usize)
+ }
}
}
use prelude::*;
use default::Default;
-use super::{Hasher, Writer};
+use super::Hasher;
+#[cfg(stage0)]
+use super::Writer;
/// An implementation of SipHash 2-4.
///
/// strong, this implementation has not been reviewed for such purposes.
/// As such, all cryptographic uses of this implementation are strongly
/// discouraged.
+#[stable(feature = "rust1", since = "1.0.0")]
pub struct SipHasher {
k0: u64,
k1: u64,
impl SipHasher {
/// Creates a new `SipHasher` with the two initial keys set to 0.
#[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn new() -> SipHasher {
SipHasher::new_with_keys(0, 0)
}
/// Creates a `SipHasher` that is keyed off the provided keys.
#[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
let mut state = SipHasher {
k0: key0,
#[unstable(feature = "hash")]
#[deprecated(since = "1.0.0", reason = "renamed to finish")]
pub fn result(&self) -> u64 { self.finish() }
-}
-impl Writer for SipHasher {
- #[inline]
+ fn reset(&mut self) {
+ self.length = 0;
+ self.v0 = self.k0 ^ 0x736f6d6570736575;
+ self.v1 = self.k1 ^ 0x646f72616e646f6d;
+ self.v2 = self.k0 ^ 0x6c7967656e657261;
+ self.v3 = self.k1 ^ 0x7465646279746573;
+ self.ntail = 0;
+ }
+
fn write(&mut self, msg: &[u8]) {
let length = msg.len();
self.length += length;
}
}
+#[cfg(stage0)]
+impl Writer for SipHasher {
+ #[inline]
+ fn write(&mut self, msg: &[u8]) {
+ self.write(msg)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
impl Hasher for SipHasher {
+ #[cfg(stage0)]
type Output = u64;
+ #[cfg(stage0)]
fn reset(&mut self) {
- self.length = 0;
- self.v0 = self.k0 ^ 0x736f6d6570736575;
- self.v1 = self.k1 ^ 0x646f72616e646f6d;
- self.v2 = self.k0 ^ 0x6c7967656e657261;
- self.v3 = self.k1 ^ 0x7465646279746573;
- self.ntail = 0;
+ self.reset();
+ }
+
+ #[inline]
+ #[cfg(not(stage0))]
+ fn write(&mut self, msg: &[u8]) {
+ self.write(msg)
}
fn finish(&self) -> u64 {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Clone for SipHasher {
#[inline]
fn clone(&self) -> SipHasher {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
impl Default for SipHasher {
fn default() -> SipHasher {
SipHasher::new()
#[derive(Copy)]
pub struct TyDesc {
// sizeof(T)
- pub size: uint,
+ pub size: usize,
// alignof(T)
- pub align: uint,
+ pub align: usize,
// Called when a value of type `T` is no longer needed
pub drop_glue: GlueFn,
/// would *exactly* overwrite a value. When laid out in vectors
/// and structures there may be additional padding between
/// elements.
- pub fn size_of<T>() -> uint;
+ pub fn size_of<T>() -> usize;
/// Move a value to an uninitialized memory location.
///
/// Drop glue is not run on the destination.
pub fn move_val_init<T>(dst: &mut T, src: T);
- pub fn min_align_of<T>() -> uint;
- pub fn pref_align_of<T>() -> uint;
+ pub fn min_align_of<T>() -> usize;
+ pub fn pref_align_of<T>() -> usize;
/// Get a static pointer to a type descriptor.
pub fn get_tydesc<T: ?Sized>() -> *const TyDesc;
///
/// This is implemented as an intrinsic to avoid converting to and from an
/// integer, since the conversion would throw away aliasing information.
- pub fn offset<T>(dst: *const T, offset: int) -> *const T;
+ pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
/// and destination may *not* overlap.
/// }
/// ```
#[unstable(feature = "core")]
- pub fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint);
+ pub fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
/// and destination may overlap.
/// ```
///
#[unstable(feature = "core")]
- pub fn copy_memory<T>(dst: *mut T, src: *const T, count: uint);
+ pub fn copy_memory<T>(dst: *mut T, src: *const T, count: usize);
/// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
/// bytes of memory starting at `dst` to `c`.
#[unstable(feature = "core",
reason = "uncertain about naming and semantics")]
- pub fn set_memory<T>(dst: *mut T, val: u8, count: uint);
+ pub fn set_memory<T>(dst: *mut T, val: u8, count: usize);
/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
/// a size of `count` * `size_of::<T>()` and an alignment of
///
/// The volatile parameter parameter is set to `true`, so it will not be optimized out.
pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
- count: uint);
+ count: usize);
/// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with
/// a size of `count` * `size_of::<T>()` and an alignment of
/// `min_align_of::<T>()`
///
/// The volatile parameter parameter is set to `true`, so it will not be optimized out.
- pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: uint);
+ pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize);
/// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
/// size of `count` * `size_of::<T>()` and an alignment of
/// `min_align_of::<T>()`.
///
/// The volatile parameter parameter is set to `true`, so it will not be optimized out.
- pub fn volatile_set_memory<T>(dst: *mut T, val: u8, count: uint);
+ pub fn volatile_set_memory<T>(dst: *mut T, val: u8, count: usize);
/// Perform a volatile load from the `src` pointer.
pub fn volatile_load<T>(src: *const T) -> T;
use cmp;
use cmp::Ord;
use default::Default;
+use marker;
use mem;
use num::{ToPrimitive, Int};
use ops::{Add, Deref, FnMut};
#[rustc_on_unimplemented="a collection of type `{Self}` cannot be \
built from an iterator over elements of type `{A}`"]
pub trait FromIterator<A> {
- /// Build a container with elements from an external iterator.
+ /// Build a container with elements from something iterable.
#[stable(feature = "rust1", since = "1.0.0")]
- fn from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
+ fn from_iter<T: IntoIterator<Item=A>>(iterator: T) -> Self;
}
/// Conversion into an `Iterator`
pub trait Extend<A> {
/// Extend a container with the elements yielded by an arbitrary iterator
#[stable(feature = "rust1", since = "1.0.0")]
- fn extend<T: Iterator<Item=A>>(&mut self, iterator: T);
+ fn extend<T: IntoIterator<Item=A>>(&mut self, iterable: T);
}
/// An extension trait providing numerous methods applicable to all iterators.
///
/// ```
/// let xs = [100, 200, 300];
- /// let mut it = xs.iter().map(|x| *x).peekable();
+ /// let mut it = xs.iter().cloned().peekable();
/// assert_eq!(*it.peek().unwrap(), 100);
/// assert_eq!(it.next().unwrap(), 100);
/// assert_eq!(it.next().unwrap(), 200);
///
/// let a = [1, 4, 2, 3, 8, 9, 6];
/// let sum = a.iter()
- /// .map(|&x| x)
- /// .inspect(|&x| println!("filtering {}", x))
- /// .filter(|&x| x % 2 == 0)
- /// .inspect(|&x| println!("{} made it through", x))
- /// .sum();
+ /// .map(|x| *x)
+ /// .inspect(|&x| println!("filtering {}", x))
+ /// .filter(|&x| x % 2 == 0)
+ /// .inspect(|&x| println!("{} made it through", x))
+ /// .sum();
/// println!("{}", sum);
/// ```
#[inline]
///
/// ```
/// let a = [1, 2, 3, 4, 5];
- /// let b: Vec<_> = a.iter().map(|&x| x).collect();
+ /// let b: Vec<_> = a.iter().cloned().collect();
/// assert_eq!(a, b);
/// ```
#[inline]
///
/// ```
/// let a = [(1, 2), (3, 4)];
- /// let (left, right): (Vec<_>, Vec<_>) = a.iter().map(|&x| x).unzip();
+ /// let (left, right): (Vec<_>, Vec<_>) = a.iter().cloned().unzip();
/// assert_eq!([1, 3], left);
/// assert_eq!([2, 4], right);
/// ```
FromB: Default + Extend<B>,
Self: Iterator<Item=(A, B)>,
{
- struct SizeHint<A>(usize, Option<usize>);
+ struct SizeHint<A>(usize, Option<usize>, marker::PhantomData<A>);
impl<A> Iterator for SizeHint<A> {
type Item = A;
let mut ts: FromA = Default::default();
let mut us: FromB = Default::default();
- ts.extend(SizeHint(lo, hi));
- us.extend(SizeHint(lo, hi));
+ ts.extend(SizeHint(lo, hi, marker::PhantomData));
+ us.extend(SizeHint(lo, hi, marker::PhantomData));
for (t, u) in self {
ts.extend(Some(t).into_iter());
/// use std::iter::AdditiveIterator;
///
/// let a = [1i32, 2, 3, 4, 5];
- /// let mut it = a.iter().map(|&x| x);
+ /// let mut it = a.iter().cloned();
/// assert!(it.sum() == 15);
/// ```
fn sum(self) -> A;
I: ExactSizeIterator<Item=D>,
{}
+#[unstable(feature = "core", reason = "trait is experimental")]
+impl<T, D, I> RandomAccessIterator for Cloned<I> where
+ T: Clone,
+ D: Deref<Target=T>,
+ I: RandomAccessIterator<Item=D>
+{
+ #[inline]
+ fn indexable(&self) -> usize {
+ self.it.indexable()
+ }
+
+ #[inline]
+ fn idx(&mut self, index: usize) -> Option<T> {
+ self.it.idx(index).cloned()
+ }
+}
+
/// An iterator that repeats endlessly
#[derive(Clone)]
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<B, I: Iterator, St, F> Iterator for Scan<I, St, F> where
- F: FnMut(&mut St, I::Item) -> Option<B>,
+impl<A, B, I: Iterator<Item=A>, St, F> Iterator for Scan<I, St, F> where
+ F: FnMut(&mut St, A) -> Option<B>,
{
type Item = B;
pub mod any;
pub mod atomic;
-pub mod borrow;
pub mod cell;
pub mod char;
pub mod panicking;
#![stable(feature = "rust1", since = "1.0.0")]
use clone::Clone;
+use cmp;
+use option::Option;
+use hash::Hash;
+use hash::Hasher;
/// Types able to be transferred across thread boundaries.
#[unstable(feature = "core",
// empty.
}
/// Types able to be transferred across thread boundaries.
-#[unstable(feature = "core",
- reason = "will be overhauled with new lifetime rules; see RFC 458")]
+#[stable(feature = "rust1", since = "1.0.0")]
#[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
#[cfg(not(stage0))]
-pub unsafe trait Send {
+pub unsafe trait Send : MarkerTrait {
// empty.
}
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
-pub trait Sized {
+pub trait Sized : MarkerTrait {
// Empty.
}
/// change: that second example would fail to compile if we made `Foo` non-`Copy`.
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="copy"]
-pub trait Copy {
+pub trait Copy : MarkerTrait {
// Empty.
}
/// around the value(s) which can be mutated when behind a `&`
/// reference; not doing this is undefined behaviour (for example,
/// `transmute`-ing from `&T` to `&mut T` is illegal).
-#[unstable(feature = "core",
- reason = "will be overhauled with new lifetime rules; see RFC 458")]
+#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
-pub unsafe trait Sync {
+pub unsafe trait Sync : MarkerTrait {
// Empty
}
-/// A marker type that indicates to the compiler that the instances
-/// of the type itself owns instances of the type parameter `T`.
-///
-/// This is used to indicate that one or more instances of the type
-/// `T` could be dropped when instances of the type itself is dropped,
-/// though that may not be apparent from the other structure of the
-/// type itself. For example, the type may hold a `*mut T`, which the
-/// compiler does not automatically treat as owned.
+/// A type which is considered "not POD", meaning that it is not
+/// implicitly copyable. This is typically embedded in other types to
+/// ensure that they are never copied, even if they lack a destructor.
#[unstable(feature = "core",
- reason = "Newly added to deal with scoping and destructor changes")]
-#[lang="phantom_data"]
-#[derive(PartialEq, Eq, PartialOrd, Ord)]
-pub struct PhantomData<T: ?Sized>;
+ reason = "likely to change with new variance strategy")]
+#[lang="no_copy_bound"]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct NoCopy;
-impl<T: ?Sized> Copy for PhantomData<T> {}
-impl<T: ?Sized> Clone for PhantomData<T> {
- fn clone(&self) -> PhantomData<T> { *self }
+/// A type which is considered managed by the GC. This is typically
+/// embedded in other types.
+#[unstable(feature = "core",
+ reason = "likely to change with new variance strategy")]
+#[lang="managed_bound"]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Managed;
+
+macro_rules! impls{
+ ($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> {
+ #[inline]
+ fn hash<H: Hasher>(&self, _: &mut H) {
+ }
+ }
+
+ impl<T:?Sized> cmp::PartialEq for $t<T> {
+ fn eq(&self, _other: &$t<T>) -> bool {
+ true
+ }
+ }
+
+ impl<T:?Sized> cmp::Eq for $t<T> {
+ }
+
+ impl<T:?Sized> cmp::PartialOrd for $t<T> {
+ fn partial_cmp(&self, _other: &$t<T>) -> Option<cmp::Ordering> {
+ Option::Some(cmp::Ordering::Equal)
+ }
+ }
+
+ impl<T:?Sized> cmp::Ord for $t<T> {
+ fn cmp(&self, _other: &$t<T>) -> cmp::Ordering {
+ cmp::Ordering::Equal
+ }
+ }
+
+ impl<T:?Sized> Copy for $t<T> { }
+
+ impl<T:?Sized> Clone for $t<T> {
+ fn clone(&self) -> $t<T> {
+ $t
+ }
+ }
+ )
}
-/// A marker type whose type parameter `T` is considered to be
-/// covariant with respect to the type itself. This is (typically)
-/// used to indicate that an instance of the type `T` is being stored
-/// into memory and read from, even though that may not be apparent.
-///
-/// For more information about variance, refer to this Wikipedia
-/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
-///
-/// *Note:* It is very unusual to have to add a covariant constraint.
-/// If you are not sure, you probably want to use `InvariantType`.
+/// `MarkerTrait` is intended to be used as the supertrait for traits
+/// that don't have any methods but instead serve just to designate
+/// categories of types. An example would be the `Send` trait, which
+/// indicates types that are sendable: `Send` does not itself offer
+/// any methods, but instead is used to gate access to data.
+///
+/// FIXME. Better documentation needed here!
+pub trait MarkerTrait : PhantomFn<Self> { }
+impl<T:?Sized> MarkerTrait for T { }
+
+/// `PhantomFn` is a marker trait for use with traits that contain
+/// type or lifetime parameters that do not appear in any of their
+/// methods. In that case, you can either remove those parameters, or
+/// add a `PhantomFn` supertrait that reflects the signature of
+/// methods that compiler should "pretend" exists. This most commonly
+/// occurs for traits with no methods: in that particular case, you
+/// can extend `MarkerTrait`, which is equivalent to
+/// `PhantomFn<Self>`.
///
/// # Example
///
-/// Given a struct `S` that includes a type parameter `T`
-/// but does not actually *reference* that type parameter:
+/// As an example, consider a trait with no methods like `Even`, meant
+/// to represent types that are "even":
///
-/// ```ignore
-/// use std::mem;
-///
-/// struct S<T> { x: *() }
-/// fn get<T>(s: &S<T>) -> T {
-/// unsafe {
-/// let x: *T = mem::transmute(s.x);
-/// *x
-/// }
-/// }
+/// ```rust,ignore
+/// trait Even { }
/// ```
///
-/// The type system would currently infer that the value of
-/// the type parameter `T` is irrelevant, and hence a `S<int>` is
-/// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
-/// any `U`). But this is incorrect because `get()` converts the
-/// `*()` into a `*T` and reads from it. Therefore, we should include the
-/// a marker field `CovariantType<T>` to inform the type checker that
-/// `S<T>` is a subtype of `S<U>` if `T` is a subtype of `U`
-/// (for example, `S<&'static int>` is a subtype of `S<&'a int>`
-/// for some lifetime `'a`, but not the other way around).
-#[unstable(feature = "core",
- reason = "likely to change with new variance strategy")]
-#[lang="covariant_type"]
-#[derive(PartialEq, Eq, PartialOrd, Ord)]
-pub struct CovariantType<T: ?Sized>;
-
-impl<T: ?Sized> Copy for CovariantType<T> {}
-impl<T: ?Sized> Clone for CovariantType<T> {
- fn clone(&self) -> CovariantType<T> { *self }
-}
-
-/// A marker type whose type parameter `T` is considered to be
-/// contravariant with respect to the type itself. This is (typically)
-/// used to indicate that an instance of the type `T` will be consumed
-/// (but not read from), even though that may not be apparent.
+/// In this case, because the implicit parameter `Self` is unused, the
+/// compiler will issue an error. The only purpose of this trait is to
+/// categorize types (and hence instances of those types) as "even" or
+/// not, so if we *were* going to have a method, it might look like:
///
-/// For more information about variance, refer to this Wikipedia
-/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
+/// ```rust,ignore
+/// trait Even {
+/// fn is_even(self) -> bool { true }
+/// }
+/// ```
///
-/// *Note:* It is very unusual to have to add a contravariant constraint.
-/// If you are not sure, you probably want to use `InvariantType`.
+/// Therefore, we can model a method like this as follows:
///
-/// # Example
+/// ```rust
+/// use std::marker::PhantomFn;
+/// trait Even : PhantomFn<Self> { }
+/// ```
///
-/// Given a struct `S` that includes a type parameter `T`
-/// but does not actually *reference* that type parameter:
+/// Another equivalent, but clearer, option would be to use
+/// `MarkerTrait`:
///
+/// ```rust
+/// use std::marker::MarkerTrait;
+/// trait Even : MarkerTrait { }
/// ```
-/// use std::mem;
-///
-/// struct S<T> { x: *const () }
-/// fn get<T>(s: &S<T>, v: T) {
-/// unsafe {
-/// let x: fn(T) = mem::transmute(s.x);
-/// x(v)
-/// }
-/// }
-/// ```
-///
-/// The type system would currently infer that the value of
-/// the type parameter `T` is irrelevant, and hence a `S<int>` is
-/// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
-/// any `U`). But this is incorrect because `get()` converts the
-/// `*()` into a `fn(T)` and then passes a value of type `T` to it.
-///
-/// Supplying a `ContravariantType` marker would correct the
-/// problem, because it would mark `S` so that `S<T>` is only a
-/// subtype of `S<U>` if `U` is a subtype of `T`; given that the
-/// function requires arguments of type `T`, it must also accept
-/// arguments of type `U`, hence such a conversion is safe.
-#[unstable(feature = "core",
- reason = "likely to change with new variance strategy")]
-#[lang="contravariant_type"]
-#[derive(PartialEq, Eq, PartialOrd, Ord)]
-pub struct ContravariantType<T: ?Sized>;
-
-impl<T: ?Sized> Copy for ContravariantType<T> {}
-impl<T: ?Sized> Clone for ContravariantType<T> {
- fn clone(&self) -> ContravariantType<T> { *self }
-}
-
-/// A marker type whose type parameter `T` is considered to be
-/// invariant with respect to the type itself. This is (typically)
-/// used to indicate that instances of the type `T` may be read or
-/// written, even though that may not be apparent.
///
-/// For more information about variance, refer to this Wikipedia
-/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
+/// # Parameters
///
-/// # Example
+/// - `A` represents the type of the method's argument. You can use a
+/// tuple to represent "multiple" arguments. Any types appearing here
+/// will be considered "contravariant".
+/// - `R`, if supplied, represents the method's return type. This defaults
+/// to `()` as it is rarely needed.
///
-/// The Cell type is an example of an `InvariantType` which uses unsafe
-/// code to achieve "interior" mutability:
+/// # Additional reading
///
-/// ```
-/// struct Cell<T> { value: T }
-/// ```
+/// More details and background can be found in [RFC 738][738].
///
-/// The type system would infer that `value` is only read here
-/// and never written, but in fact `Cell` uses unsafe code to achieve
-/// interior mutability. In order to get correct behavior, the
-/// `InvariantType` marker must be applied.
-#[unstable(feature = "core",
- reason = "likely to change with new variance strategy")]
-#[lang="invariant_type"]
-#[derive(PartialEq, Eq, PartialOrd, Ord)]
-pub struct InvariantType<T: ?Sized>;
-
-#[unstable(feature = "core",
- reason = "likely to change with new variance strategy")]
-impl<T: ?Sized> Copy for InvariantType<T> {}
-#[unstable(feature = "core",
- reason = "likely to change with new variance strategy")]
-impl<T: ?Sized> Clone for InvariantType<T> {
- fn clone(&self) -> InvariantType<T> { *self }
-}
-
-/// As `CovariantType`, but for lifetime parameters. Using
-/// `CovariantLifetime<'a>` indicates that it is ok to substitute
-/// a *longer* lifetime for `'a` than the one you originally
-/// started with (e.g., you could convert any lifetime `'foo` to
-/// `'static`). You almost certainly want `ContravariantLifetime`
-/// instead, or possibly `InvariantLifetime`. The only case where
-/// it would be appropriate is that you have a (type-casted, and
-/// hence hidden from the type system) function pointer with a
-/// signature like `fn(&'a T)` (and no other uses of `'a`). In
-/// this case, it is ok to substitute a larger lifetime for `'a`
-/// (e.g., `fn(&'static T)`), because the function is only
-/// becoming more selective in terms of what it accepts as
-/// argument.
-///
-/// For more information about variance, refer to this Wikipedia
-/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
-#[unstable(feature = "core",
- reason = "likely to change with new variance strategy")]
-#[lang="covariant_lifetime"]
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct CovariantLifetime<'a>;
+/// [738]: https://github.com/rust-lang/rfcs/blob/master/text/0738-variance.md
+#[lang="phantom_fn"]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
-/// As `ContravariantType`, but for lifetime parameters. Using
-/// `ContravariantLifetime<'a>` indicates that it is ok to
-/// substitute a *shorter* lifetime for `'a` than the one you
-/// originally started with (e.g., you could convert `'static` to
-/// any lifetime `'foo`). This is appropriate for cases where you
-/// have an unsafe pointer that is actually a pointer into some
-/// memory with lifetime `'a`, and thus you want to limit the
-/// lifetime of your data structure to `'a`. An example of where
-/// this is used is the iterator for vectors.
-///
-/// For more information about variance, refer to this Wikipedia
-/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
-#[unstable(feature = "core",
- reason = "likely to change with new variance strategy")]
-#[lang="contravariant_lifetime"]
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct ContravariantLifetime<'a>;
+#[cfg(stage0)] // built into the trait matching system after stage0
+impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
-/// As `InvariantType`, but for lifetime parameters. Using
-/// `InvariantLifetime<'a>` indicates that it is not ok to
-/// substitute any other lifetime for `'a` besides its original
-/// value. This is appropriate for cases where you have an unsafe
-/// pointer that is actually a pointer into memory with lifetime `'a`,
-/// and this pointer is itself stored in an inherently mutable
-/// location (such as a `Cell`).
-#[unstable(feature = "core",
- reason = "likely to change with new variance strategy")]
-#[lang="invariant_lifetime"]
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
-pub struct InvariantLifetime<'a>;
+/// Specific to stage0. You should not be seeing these docs!
+#[cfg(stage0)]
+#[lang="covariant_type"] // only relevant to stage0
+pub struct PhantomData<T:?Sized>;
-/// A type which is considered "not POD", meaning that it is not
-/// implicitly copyable. This is typically embedded in other types to
-/// ensure that they are never copied, even if they lack a destructor.
-#[unstable(feature = "core",
- reason = "likely to change with new variance strategy")]
-#[lang="no_copy_bound"]
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub struct NoCopy;
+/// `PhantomData` is a way to tell the compiler about fake fields.
+/// Phantom data is required whenever type parameters are not used.
+/// The idea is that if the compiler encounters a `PhantomData<T>`
+/// instance, it will behave *as if* an instance of the type `T` were
+/// present for the purpose of various automatic analyses.
+///
+/// For example, embedding a `PhantomData<T>` will inform the compiler
+/// that one or more instances of the type `T` could be dropped when
+/// instances of the type itself is dropped, though that may not be
+/// apparent from the other structure of the type itself. This is
+/// commonly necessary if the structure is using an unsafe pointer
+/// like `*mut T` whose referent may be dropped when the type is
+/// dropped, as a `*mut T` is otherwise not treated as owned.
+///
+/// FIXME. Better documentation and examples of common patterns needed
+/// here! For now, please see [RFC 738][738] for more information.
+///
+/// [738]: https://github.com/rust-lang/rfcs/blob/master/text/0738-variance.md
+#[cfg(not(stage0))]
+#[lang="phantom_data"]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct PhantomData<T:?Sized>;
-/// A type which is considered managed by the GC. This is typically
-/// embedded in other types.
-#[unstable(feature = "core",
- reason = "likely to change with new variance strategy")]
-#[lang="managed_bound"]
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
-pub struct Managed;
+impls! { PhantomData }
#[cfg(not(stage0))]
mod impls {
unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {}
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
}
+
+/// Old-style marker trait. Deprecated.
+#[unstable(feature = "core", reason = "deprecated")]
+#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<&'a ()>`")]
+#[lang="contravariant_lifetime"]
+pub struct ContravariantLifetime<'a>;
+
+/// Old-style marker trait. Deprecated.
+#[unstable(feature = "core", reason = "deprecated")]
+#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<fn(&'a ())>`")]
+#[lang="covariant_lifetime"]
+pub struct CovariantLifetime<'a>;
+
+/// Old-style marker trait. Deprecated.
+#[unstable(feature = "core", reason = "deprecated")]
+#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<Cell<&'a ()>>`")]
+#[lang="invariant_lifetime"]
+pub struct InvariantLifetime<'a>;
+
+/// Old-style marker trait. Deprecated.
+#[unstable(feature = "core", reason = "deprecated")]
+#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<fn(T)>`")]
+#[lang="contravariant_type"]
+pub struct ContravariantType<T>;
+
+/// Old-style marker trait. Deprecated.
+#[unstable(feature = "core", reason = "deprecated")]
+#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<T>`")]
+#[lang="covariant_type"]
+#[cfg(not(stage0))]
+pub struct CovariantType<T>;
+
+/// Old-style marker trait. Deprecated.
+#[unstable(feature = "core", reason = "deprecated")]
+#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<Cell<T>>`")]
+#[lang="invariant_type"]
+pub struct InvariantType<T>;
//! Exposes the NonZero lang item which provides optimization hints.
+use marker::{Sized, MarkerTrait};
use ops::Deref;
-use ptr::Unique;
/// Unsafe trait to indicate what types are usable with the NonZero struct
-pub unsafe trait Zeroable {}
+pub unsafe trait Zeroable : MarkerTrait {}
-unsafe impl<T> Zeroable for *const T {}
-unsafe impl<T> Zeroable for *mut T {}
-unsafe impl<T> Zeroable for Unique<T> { }
+unsafe impl<T:?Sized> Zeroable for *const T {}
+unsafe impl<T:?Sized> Zeroable for *mut T {}
unsafe impl Zeroable for isize {}
unsafe impl Zeroable for usize {}
unsafe impl Zeroable for i8 {}
use cmp::{Eq, Ord};
use default::Default;
use iter::{ExactSizeIterator};
-use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator};
+use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, IntoIterator};
use mem;
use ops::{Deref, FnOnce};
use result::Result::{Ok, Err};
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- fn from_iter<I: Iterator<Item=Option<A>>>(iter: I) -> Option<V> {
+ fn from_iter<I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> {
// FIXME(#11084): This could be replaced with Iterator::scan when this
// performance bug is closed.
}
}
- let mut adapter = Adapter { iter: iter, found_none: false };
+ let mut adapter = Adapter { iter: iter.into_iter(), found_none: false };
let v: V = FromIterator::from_iter(adapter.by_ref());
if adapter.found_none {
use mem;
use clone::Clone;
use intrinsics;
+use ops::Deref;
use option::Option::{self, Some, None};
-use marker::{self, Send, Sized, Sync};
+use marker::{PhantomData, Send, Sized, Sync};
+use nonzero::NonZero;
use cmp::{PartialEq, Eq, Ord, PartialOrd};
use cmp::Ordering::{self, Less, Equal, Greater};
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- fn is_null(self) -> bool { self as usize == 0 }
+ fn is_null(self) -> bool { self == 0 as *const T }
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- fn is_null(self) -> bool { self as usize == 0 }
+ fn is_null(self) -> bool { self == 0 as *mut T }
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
/// A wrapper around a raw `*mut T` that indicates that the possessor
/// of this wrapper owns the referent. This in turn implies that the
-/// `Unique<T>` is `Send`/`Sync` if `T` is `Send`/`Sync`, unlike a
-/// raw `*mut T` (which conveys no particular ownership semantics).
-/// Useful for building abstractions like `Vec<T>` or `Box<T>`, which
+/// `Unique<T>` is `Send`/`Sync` if `T` is `Send`/`Sync`, unlike a raw
+/// `*mut T` (which conveys no particular ownership semantics). It
+/// also implies that the referent of the pointer should not be
+/// modified without a unique path to the `Unique` reference. Useful
+/// for building abstractions like `Vec<T>` or `Box<T>`, which
/// internally use raw pointers to manage the memory that they own.
#[unstable(feature = "core", reason = "recently added to this module")]
-pub struct Unique<T: ?Sized> {
- /// The wrapped `*mut T`.
- pub ptr: *mut T,
- _own: marker::PhantomData<T>,
+pub struct Unique<T:?Sized> {
+ pointer: NonZero<*const T>,
+ _marker: PhantomData<T>,
}
/// `Unique` pointers are `Send` if `T` is `Send` because the data they
#[unstable(feature = "core", reason = "recently added to this module")]
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
-impl<T> Unique<T> {
- /// Returns a null Unique.
+impl<T:?Sized> Unique<T> {
+ /// Create a new `Unique`.
#[unstable(feature = "core",
reason = "recently added to this module")]
- pub fn null() -> Unique<T> {
- Unique(null_mut())
+ pub unsafe fn new(ptr: *mut T) -> Unique<T> {
+ Unique { pointer: NonZero::new(ptr as *const T), _marker: PhantomData }
}
- /// Return an (unsafe) pointer into the memory owned by `self`.
+ /// Dereference the content.
#[unstable(feature = "core",
reason = "recently added to this module")]
- pub unsafe fn offset(self, offset: isize) -> *mut T {
- self.ptr.offset(offset)
+ pub unsafe fn get(&self) -> &T {
+ &**self.pointer
+ }
+
+ /// Mutably dereference the content.
+ #[unstable(feature = "core",
+ reason = "recently added to this module")]
+ pub unsafe fn get_mut(&mut self) -> &mut T {
+ &mut ***self
}
}
-/// Creates a `Unique` wrapped around `ptr`, taking ownership of the
-/// data referenced by `ptr`.
-#[allow(non_snake_case)]
-pub fn Unique<T: ?Sized>(ptr: *mut T) -> Unique<T> {
- Unique { ptr: ptr, _own: marker::PhantomData }
+impl<T:?Sized> Deref for Unique<T> {
+ type Target = *mut T;
+
+ #[inline]
+ fn deref<'a>(&'a self) -> &'a *mut T {
+ unsafe { mem::transmute(&*self.pointer) }
+ }
}
use clone::Clone;
use fmt;
-use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, ExactSizeIterator};
+use iter::{Iterator, IteratorExt, DoubleEndedIterator,
+ FromIterator, ExactSizeIterator, IntoIterator};
use ops::{FnMut, FnOnce};
use option::Option::{self, None, Some};
use slice::AsSlice;
/// assert!(res == Ok(vec!(2, 3)));
/// ```
#[inline]
- fn from_iter<I: Iterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
+ fn from_iter<I: IntoIterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
// FIXME(#11084): This could be replaced with Iterator::scan when this
// performance bug is closed.
}
}
- let mut adapter = Adapter { iter: iter, err: None };
+ let mut adapter = Adapter { iter: iter.into_iter(), err: None };
let v: V = FromIterator::from_iter(adapter.by_ref());
match adapter.err {
if mem::size_of::<T>() == 0 {
Iter {ptr: p,
end: (p as usize + self.len()) as *const T,
- marker: marker::ContravariantLifetime::<'a>}
+ _marker: marker::PhantomData}
} else {
Iter {ptr: p,
end: p.offset(self.len() as isize),
- marker: marker::ContravariantLifetime::<'a>}
+ _marker: marker::PhantomData}
}
}
}
if mem::size_of::<T>() == 0 {
IterMut {ptr: p,
end: (p as usize + self.len()) as *mut T,
- marker: marker::ContravariantLifetime::<'a>}
+ _marker: marker::PhantomData}
} else {
IterMut {ptr: p,
end: p.offset(self.len() as isize),
- marker: marker::ContravariantLifetime::<'a>}
+ _marker: marker::PhantomData}
}
}
}
pub struct Iter<'a, T: 'a> {
ptr: *const T,
end: *const T,
- marker: marker::ContravariantLifetime<'a>
+ _marker: marker::PhantomData<&'a T>,
}
#[unstable(feature = "core")]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Clone for Iter<'a, T> {
- fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, marker: self.marker } }
+ fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: self._marker } }
}
#[unstable(feature = "core", reason = "trait is experimental")]
pub struct IterMut<'a, T: 'a> {
ptr: *mut T,
end: *mut T,
- marker: marker::ContravariantLifetime<'a>,
+ _marker: marker::PhantomData<&'a mut T>,
}
/// Any string that can be represented as a slice
#[unstable(feature = "core",
reason = "Instead of taking this bound generically, this trait will be \
- replaced with one of slicing syntax (&foo[]), deref coercions, or \
+ replaced with one of slicing syntax (&foo[..]), deref coercions, or \
a more generic conversion trait")]
pub trait Str {
/// Work with `self` as a slice.
// except according to those terms.
use std::mem;
-use std::hash::{Hash, Hasher, Writer};
+use std::hash::{Hash, Hasher};
use std::default::Default;
struct MyHasher {
}
}
-impl Writer for MyHasher {
- // Most things we'll just add up the bytes.
+impl Hasher for MyHasher {
fn write(&mut self, buf: &[u8]) {
for byte in buf {
self.hash += *byte as u64;
}
}
-}
-
-impl Hasher for MyHasher {
- type Output = u64;
- fn reset(&mut self) { self.hash = 0; }
fn finish(&self) -> u64 { self.hash }
}
#[test]
fn test_writer_hasher() {
- fn hash<T: Hash<MyHasher>>(t: &T) -> u64 {
+ fn hash<T: Hash>(t: &T) -> u64 {
::std::hash::hash::<_, MyHasher>(t)
}
struct CustomHasher { output: u64 }
impl Hasher for CustomHasher {
- type Output = u64;
- fn reset(&mut self) { self.output = 0; }
fn finish(&self) -> u64 { self.output }
+ fn write(&mut self, data: &[u8]) { panic!() }
+ fn write_u64(&mut self, data: u64) { self.output = data; }
}
impl Default for CustomHasher {
}
}
-impl Hash<CustomHasher> for Custom {
- fn hash(&self, state: &mut CustomHasher) {
- state.output = self.hash;
+impl Hash for Custom {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ state.write_u64(self.hash);
}
}
#[test]
fn test_custom_state() {
- fn hash<T: Hash<CustomHasher>>(t: &T) -> u64 {
+ fn hash<T: Hash>(t: &T) -> u64 {
::std::hash::hash::<_, CustomHasher>(t)
}
assert_eq!(i, expected.len());
let ys = count(30, 10).take(4);
- let mut it = xs.iter().map(|&x| x).chain(ys);
+ let mut it = xs.iter().cloned().chain(ys);
let mut i = 0;
for x in it {
assert_eq!(x, expected[i]);
#[test]
fn test_iterator_peekable() {
let xs = vec![0, 1, 2, 3, 4, 5];
- let mut it = xs.iter().map(|&x|x).peekable();
+ let mut it = xs.iter().cloned().peekable();
assert_eq!(it.len(), 6);
assert_eq!(it.peek().unwrap(), &0);
let mut n = 0;
let ys = xs.iter()
- .map(|&x| x)
+ .cloned()
.inspect(|_| n += 1)
.collect::<Vec<uint>>();
assert_eq!(n, xs.len());
- assert_eq!(&xs[], &ys[]);
+ assert_eq!(&xs[..], &ys[..]);
}
#[test]
#[test]
fn test_iterator_sum() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- assert_eq!(v[..4].iter().map(|&x| x).sum(), 6);
- assert_eq!(v.iter().map(|&x| x).sum(), 55);
- assert_eq!(v[..0].iter().map(|&x| x).sum(), 0);
+ assert_eq!(v[..4].iter().cloned().sum(), 6);
+ assert_eq!(v.iter().cloned().sum(), 55);
+ assert_eq!(v[..0].iter().cloned().sum(), 0);
}
#[test]
fn test_iterator_product() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- assert_eq!(v[..4].iter().map(|&x| x).product(), 0);
- assert_eq!(v[1..5].iter().map(|&x| x).product(), 24);
- assert_eq!(v[..0].iter().map(|&x| x).product(), 1);
+ assert_eq!(v[..4].iter().cloned().product(), 0);
+ assert_eq!(v[1..5].iter().cloned().product(), 24);
+ assert_eq!(v[..0].iter().cloned().product(), 1);
}
#[test]
fn test_iterator_max() {
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- assert_eq!(v[..4].iter().map(|&x| x).max(), Some(3));
- assert_eq!(v.iter().map(|&x| x).max(), Some(10));
- assert_eq!(v[..0].iter().map(|&x| x).max(), None);
+ assert_eq!(v[..4].iter().cloned().max(), Some(3));
+ assert_eq!(v.iter().cloned().max(), Some(10));
+ assert_eq!(v[..0].iter().cloned().max(), None);
}
#[test]
fn test_iterator_min() {
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
- assert_eq!(v[..4].iter().map(|&x| x).min(), Some(0));
- assert_eq!(v.iter().map(|&x| x).min(), Some(0));
- assert_eq!(v[..0].iter().map(|&x| x).min(), None);
+ assert_eq!(v[..4].iter().cloned().min(), Some(0));
+ assert_eq!(v.iter().cloned().min(), Some(0));
+ assert_eq!(v[..0].iter().cloned().min(), None);
}
#[test]
assert_eq!(c.clone().take_while(|_| false).size_hint(), (0, None));
assert_eq!(c.clone().skip_while(|_| false).size_hint(), (0, None));
assert_eq!(c.clone().enumerate().size_hint(), (uint::MAX, None));
- assert_eq!(c.clone().chain(vi.clone().map(|&i| i)).size_hint(), (uint::MAX, None));
+ assert_eq!(c.clone().chain(vi.clone().cloned()).size_hint(), (uint::MAX, None));
assert_eq!(c.clone().zip(vi.clone()).size_hint(), (10, Some(10)));
assert_eq!(c.clone().scan(0, |_,_| Some(0)).size_hint(), (0, None));
assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None));
#[test]
fn test_collect() {
let a = vec![1, 2, 3, 4, 5];
- let b: Vec<int> = a.iter().map(|&x| x).collect();
+ let b: Vec<int> = a.iter().cloned().collect();
assert!(a == b);
}
let mut it = xs.iter();
it.next();
it.next();
- assert!(it.rev().map(|&x| x).collect::<Vec<int>>() ==
+ assert!(it.rev().cloned().collect::<Vec<int>>() ==
vec![16, 14, 12, 10, 8, 6]);
}
#[test]
fn test_double_ended_enumerate() {
let xs = [1, 2, 3, 4, 5, 6];
- let mut it = xs.iter().map(|&x| x).enumerate();
+ let mut it = xs.iter().cloned().enumerate();
assert_eq!(it.next(), Some((0, 1)));
assert_eq!(it.next(), Some((1, 2)));
assert_eq!(it.next_back(), Some((5, 6)));
fn test_double_ended_zip() {
let xs = [1, 2, 3, 4, 5, 6];
let ys = [1, 2, 3, 7];
- let a = xs.iter().map(|&x| x);
- let b = ys.iter().map(|&x| x);
+ let a = xs.iter().cloned();
+ let b = ys.iter().cloned();
let mut it = a.zip(b);
assert_eq!(it.next(), Some((1, 1)));
assert_eq!(it.next(), Some((2, 2)));
fn test_random_access_map() {
let xs = [1, 2, 3, 4, 5];
- let mut it = xs.iter().map(|x| *x);
+ let mut it = xs.iter().cloned();
assert_eq!(xs.len(), it.indexable());
for (i, elt) in xs.iter().enumerate() {
assert_eq!(Some(*elt), it.idx(i));
#[test]
fn test_transmute() {
- trait Foo {}
+ trait Foo { fn dummy(&self) { } }
impl Foo for int {}
let a = box 100 as Box<Foo>;
#[test]
fn test_unsized_unique() {
let xs: &mut [_] = &mut [1, 2, 3];
- let ptr = Unique(xs as *mut [_]);
- let ys = unsafe { &mut *ptr.ptr };
+ let ptr = unsafe { Unique::new(xs as *mut [_]) };
+ let ys = unsafe { &mut **ptr };
let zs: &mut [_] = &mut [1, 2, 3];
assert!(ys == zs);
}
{
let mut iter = data.iter();
- assert_eq!(&iter[], &other_data[]);
+ assert_eq!(&iter[..], &other_data[..]);
iter.next();
- assert_eq!(&iter[], &other_data[1..]);
+ assert_eq!(&iter[..], &other_data[1..]);
iter.next_back();
- assert_eq!(&iter[], &other_data[1..2]);
+ assert_eq!(&iter[..], &other_data[1..2]);
let s = iter.as_slice();
iter.next();
}
{
let mut iter = data.iter_mut();
- assert_eq!(&iter[], &other_data[]);
+ assert_eq!(&iter[..], &other_data[..]);
// mutability:
assert!(&mut iter[] == other_data);
iter.next();
- assert_eq!(&iter[], &other_data[1..]);
+ assert_eq!(&iter[..], &other_data[1..]);
assert!(&mut iter[] == &mut other_data[1..]);
iter.next_back();
- assert_eq!(&iter[], &other_data[1..2]);
+ assert_eq!(&iter[..], &other_data[1..2]);
assert!(&mut iter[] == &mut other_data[1..2]);
let s = iter.into_slice();
impl Deref for Bytes {
type Target = [u8];
fn deref(&self) -> &[u8] {
- unsafe { slice::from_raw_parts_mut(self.ptr.ptr, self.len) }
+ unsafe { slice::from_raw_parts(*self.ptr, self.len) }
}
}
impl Drop for Bytes {
fn drop(&mut self) {
- unsafe { libc::free(self.ptr.ptr as *mut _); }
+ unsafe { libc::free(*self.ptr as *mut _); }
}
}
&mut outsz,
flags);
if !res.is_null() {
- let res = Unique(res as *mut u8);
+ let res = Unique::new(res as *mut u8);
Some(Bytes { ptr: res, len: outsz as uint })
} else {
None
&mut outsz,
flags);
if !res.is_null() {
- let res = Unique(res as *mut u8);
+ let res = Unique::new(res as *mut u8);
Some(Bytes { ptr: res, len: outsz as uint })
} else {
None
}
Some((_, other)) => {
self.err(&format!("expected `{:?}`, found `{:?}`", c,
- other)[]);
+ other));
}
None => {
self.err(&format!("expected `{:?}` but string was terminated",
- c)[]);
+ c));
}
}
}
impl Matches {
fn opt_vals(&self, nm: &str) -> Vec<Optval> {
- match find_opt(&self.opts[], Name::from_str(nm)) {
+ match find_opt(&self.opts[..], Name::from_str(nm)) {
Some(id) => self.vals[id].clone(),
None => panic!("No option '{}' defined", nm)
}
/// Returns the string argument supplied to one of several matching options or `None`.
pub fn opts_str(&self, names: &[String]) -> Option<String> {
for nm in names {
- match self.opt_val(&nm[]) {
+ match self.opt_val(&nm[..]) {
Some(Val(ref s)) => return Some(s.clone()),
_ => ()
}
while i < l {
let cur = args[i].clone();
let curlen = cur.len();
- if !is_arg(&cur[]) {
+ if !is_arg(&cur[..]) {
free.push(cur);
} else if cur == "--" {
let mut j = i + 1;
v.push(Val((i_arg.clone())
.unwrap()));
} else if name_pos < names.len() || i + 1 == l ||
- is_arg(&args[i + 1][]) {
+ is_arg(&args[i + 1][..]) {
let v = &mut vals[optid];
v.push(Given);
} else {
0 => {}
1 => {
row.push('-');
- row.push_str(&short_name[]);
+ row.push_str(&short_name[..]);
row.push(' ');
}
_ => panic!("the short name should only be 1 ascii char long"),
0 => {}
_ => {
row.push_str("--");
- row.push_str(&long_name[]);
+ row.push_str(&long_name[..]);
row.push(' ');
}
}
// arg
match hasarg {
No => {}
- Yes => row.push_str(&hint[]),
+ Yes => row.push_str(&hint[..]),
Maybe => {
row.push('[');
- row.push_str(&hint[]);
+ row.push_str(&hint[..]);
row.push(']');
}
}
row.push(' ');
}
} else {
- row.push_str(&desc_sep[]);
+ row.push_str(&desc_sep[..]);
}
// Normalize desc to contain words separated by one space character
// FIXME: #5516 should be graphemes not codepoints
let mut desc_rows = Vec::new();
- each_split_within(&desc_normalized_whitespace[], 54, |substr| {
+ each_split_within(&desc_normalized_whitespace[..], 54, |substr| {
desc_rows.push(substr.to_string());
true
});
// FIXME: #5516 should be graphemes not codepoints
// wrapped description
- row.push_str(&desc_rows.connect(&desc_sep[])[]);
+ row.push_str(&desc_rows.connect(&desc_sep[..])[]);
row
});
// Use short_name is possible, but fallback to long_name.
if opt.short_name.len() > 0 {
line.push('-');
- line.push_str(&opt.short_name[]);
+ line.push_str(&opt.short_name[..]);
} else {
line.push_str("--");
- line.push_str(&opt.long_name[]);
+ line.push_str(&opt.long_name[..]);
}
if opt.hasarg != No {
if opt.hasarg == Maybe {
line.push('[');
}
- line.push_str(&opt.hint[]);
+ line.push_str(&opt.hint[..]);
if opt.hasarg == Maybe {
line.push(']');
}
line.push_str(&opts.iter()
.map(format_option)
.collect::<Vec<String>>()
- .connect(" ")[]);
+ .connect(" ")[..]);
line
}
html_root_url = "http://doc.rust-lang.org/nightly/")]
#![feature(int_uint)]
#![feature(collections)]
-#![feature(core)]
#![feature(old_io)]
use self::LabelText::*;
-use std::borrow::IntoCow;
+use std::borrow::{IntoCow, Cow};
use std::old_io;
-use std::string::CowString;
-use std::vec::CowVec;
/// The text for a graphviz label on a node or edge.
pub enum LabelText<'a> {
///
/// Occurrences of backslashes (`\`) are escaped, and thus appear
/// as backslashes in the rendered label.
- LabelStr(CowString<'a>),
+ LabelStr(Cow<'a, str>),
/// This kind of label uses the graphviz label escString type:
/// http://www.graphviz.org/content/attrs#kescString
/// to break a line (centering the line preceding the `\n`), there
/// are also the escape sequences `\l` which left-justifies the
/// preceding line and `\r` which right-justifies it.
- EscStr(CowString<'a>),
+ EscStr(Cow<'a, str>),
}
// There is a tension in the design of the labelling API.
/// `Id` is a Graphviz `ID`.
pub struct Id<'a> {
- name: CowString<'a>,
+ name: Cow<'a, str>,
}
impl<'a> Id<'a> {
///
/// Passing an invalid string (containing spaces, brackets,
/// quotes, ...) will return an empty `Err` value.
- pub fn new<Name: IntoCow<'a, String, str>>(name: Name) -> Result<Id<'a>, ()> {
+ pub fn new<Name: IntoCow<'a, str>>(name: Name) -> Result<Id<'a>, ()> {
let name = name.into_cow();
{
let mut chars = name.chars();
&*self.name
}
- pub fn name(self) -> CowString<'a> {
+ pub fn name(self) -> Cow<'a, str> {
self.name
}
}
}
impl<'a> LabelText<'a> {
- pub fn label<S:IntoCow<'a, String, str>>(s: S) -> LabelText<'a> {
+ pub fn label<S:IntoCow<'a, str>>(s: S) -> LabelText<'a> {
LabelStr(s.into_cow())
}
- pub fn escaped<S:IntoCow<'a, String, str>>(s: S) -> LabelText<'a> {
+ pub fn escaped<S:IntoCow<'a, str>>(s: S) -> LabelText<'a> {
EscStr(s.into_cow())
}
pub fn escape(&self) -> String {
match self {
&LabelStr(ref s) => s.escape_default(),
- &EscStr(ref s) => LabelText::escape_str(&s[]),
+ &EscStr(ref s) => LabelText::escape_str(&s[..]),
}
}
/// yields same content as self. The result obeys the law
/// render(`lt`) == render(`EscStr(lt.pre_escaped_content())`) for
/// all `lt: LabelText`.
- fn pre_escaped_content(self) -> CowString<'a> {
+ fn pre_escaped_content(self) -> Cow<'a, str> {
match self {
EscStr(s) => s,
LabelStr(s) => if s.contains_char('\\') {
let mut prefix = self.pre_escaped_content().into_owned();
let suffix = suffix.pre_escaped_content();
prefix.push_str(r"\n\n");
- prefix.push_str(&suffix[]);
+ prefix.push_str(&suffix[..]);
EscStr(prefix.into_cow())
}
}
-pub type Nodes<'a,N> = CowVec<'a,N>;
-pub type Edges<'a,E> = CowVec<'a,E>;
+pub type Nodes<'a,N> = Cow<'a,[N]>;
+pub type Edges<'a,E> = Cow<'a,[E]>;
// (The type parameters in GraphWalk should be associated items,
// when/if Rust supports such.)
impl<'a> Labeller<'a, Node, &'a Edge> for LabelledGraph {
fn graph_id(&'a self) -> Id<'a> {
- Id::new(&self.name[]).unwrap()
+ Id::new(&self.name[..]).unwrap()
}
fn node_id(&'a self, n: &Node) -> Id<'a> {
id_name(n)
// Test the literal string from args against the current filter, if there
// is one.
match unsafe { FILTER.as_ref() } {
- Some(filter) if !args.to_string().contains(&filter[]) => return,
+ Some(filter) if !args.to_string().contains(&filter[..]) => return,
_ => {}
}
// Search for the longest match, the vector is assumed to be pre-sorted.
for directive in iter.rev() {
match directive.name {
- Some(ref name) if !module.starts_with(&name[]) => {},
+ Some(ref name) if !module.starts_with(&name[..]) => {},
Some(..) | None => {
return level <= directive.level
}
/// `Once` primitive (and this function is called from that primitive).
fn init() {
let (mut directives, filter) = match env::var("RUST_LOG") {
- Ok(spec) => directive::parse_logging_spec(&spec[]),
+ Ok(spec) => directive::parse_logging_spec(&spec[..]),
Err(..) => (Vec::new(), None),
};
use core::prelude::*;
use core::num::{Float, Int};
+use core::marker::PhantomData;
use {Rng, Rand};
/// A wrapper for generating types that implement `Rand` via the
/// `Sample` & `IndependentSample` traits.
-pub struct RandSample<Sup>;
+pub struct RandSample<Sup> { _marker: PhantomData<Sup> }
+
+impl<Sup> RandSample<Sup> {
+ pub fn new() -> RandSample<Sup> {
+ RandSample { _marker: PhantomData }
+ }
+}
impl<Sup: Rand> Sample<Sup> for RandSample<Sup> {
fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
#[test]
fn test_rand_sample() {
- let mut rand_sample = RandSample::<ConstRand>;
+ let mut rand_sample = RandSample::<ConstRand>::new();
assert_eq!(rand_sample.sample(&mut ::test::rng()), ConstRand(0));
assert_eq!(rand_sample.ind_sample(&mut ::test::rng()), ConstRand(0));
fn reseed(&mut self, seed: &'a [u32]) {
// make the seed into [seed[0], seed[1], ..., seed[seed.len()
// - 1], 0, 0, ...], to fill rng.rsl.
- let seed_iter = seed.iter().map(|&x| x).chain(repeat(0u32));
+ let seed_iter = seed.iter().cloned().chain(repeat(0u32));
for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
*rsl_elem = seed_elem;
fn reseed(&mut self, seed: &'a [u64]) {
// make the seed into [seed[0], seed[1], ..., seed[seed.len()
// - 1], 0, 0, ...], to fill rng.rsl.
- let seed_iter = seed.iter().map(|&x| x).chain(repeat(0u64));
+ let seed_iter = seed.iter().cloned().chain(repeat(0u64));
for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
*rsl_elem = seed_elem;
#[cfg(test)] #[macro_use] extern crate log;
use core::prelude::*;
+use core::marker::PhantomData;
pub use isaac::{IsaacRng, Isaac64Rng};
pub use chacha::ChaChaRng;
/// .collect::<Vec<(f64, bool)>>());
/// ```
fn gen_iter<'a, T: Rand>(&'a mut self) -> Generator<'a, T, Self> {
- Generator { rng: self }
+ Generator { rng: self, _marker: PhantomData }
}
/// Generate a random value in the range [`low`, `high`).
/// This iterator is created via the `gen_iter` method on `Rng`.
pub struct Generator<'a, T, R:'a> {
rng: &'a mut R,
+ _marker: PhantomData<T>
}
impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> {
use util::nodemap::{FnvHashMap, NodeSet};
use lint::{Level, Context, LintPass, LintArray, Lint};
-use std::collections::BitvSet;
+use std::collections::BitSet;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::num::SignedInt;
use std::{cmp, slice};
if n_uniq > 0 {
let s = ty_to_string(cx.tcx, ty);
let m = format!("type uses owned (Box type) pointers: {}", s);
- cx.span_lint(BOX_POINTERS, span, &m[]);
+ cx.span_lint(BOX_POINTERS, span, &m[..]);
}
}
}
}
} else {
let attrs = csearch::get_item_attrs(&cx.sess().cstore, did);
- warned |= check_must_use(cx, &attrs[], s.span);
+ warned |= check_must_use(cx, &attrs[..], s.span);
}
}
_ => {}
} else {
format!("{} `{}` should have a camel case name such as `{}`", sort, s, c)
};
- cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[]);
+ cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[..]);
}
}
}
if !is_snake_case(ident) {
let sc = NonSnakeCase::to_snake_case(&s);
- if sc != &s[] {
+ if sc != &s[..] {
cx.span_lint(NON_SNAKE_CASE, span,
&*format!("{} `{}` should have a snake case name such as `{}`",
sort, s, sc));
if s.chars().any(|c| c.is_lowercase()) {
let uc: String = NonSnakeCase::to_snake_case(&s).chars()
.map(|c| c.to_uppercase()).collect();
- if uc != &s[] {
+ if uc != &s[..] {
cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
&format!("{} `{}` should have an upper case name such as `{}`",
sort, s, uc));
let m = format!("braces around {} is unnecessary",
&token::get_ident(*name));
cx.span_lint(UNUSED_IMPORT_BRACES, item.span,
- &m[]);
+ &m[..]);
},
_ => ()
}
let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| {
attr.check_name("doc") && match attr.meta_item_list() {
None => false,
- Some(l) => attr::contains_name(&l[], "hidden"),
+ Some(l) => attr::contains_name(&l[..], "hidden"),
}
});
self.doc_hidden_stack.push(doc_hidden);
_ => format!("use of {} item", label)
};
- cx.span_lint(lint, span, &msg[]);
+ cx.span_lint(lint, span, &msg[..]);
}
}
}
let mut work_queue = vec![cfg.entry];
let mut reached_exit_without_self_call = false;
let mut self_call_spans = vec![];
- let mut visited = BitvSet::new();
+ let mut visited = BitSet::new();
while let Some(idx) = work_queue.pop() {
let cfg_id = idx.node_id();
match (sess, from_plugin) {
// We load builtin lints first, so a duplicate is a compiler bug.
// Use early_error when handling -W help with no crate.
- (None, _) => early_error(&msg[]),
- (Some(sess), false) => sess.bug(&msg[]),
+ (None, _) => early_error(&msg[..]),
+ (Some(sess), false) => sess.bug(&msg[..]),
// A duplicate name from a plugin is a user error.
- (Some(sess), true) => sess.err(&msg[]),
+ (Some(sess), true) => sess.err(&msg[..]),
}
}
match (sess, from_plugin) {
// We load builtin lints first, so a duplicate is a compiler bug.
// Use early_error when handling -W help with no crate.
- (None, _) => early_error(&msg[]),
- (Some(sess), false) => sess.bug(&msg[]),
+ (None, _) => early_error(&msg[..]),
+ (Some(sess), false) => sess.bug(&msg[..]),
// A duplicate name from a plugin is a user error.
- (Some(sess), true) => sess.err(&msg[]),
+ (Some(sess), true) => sess.err(&msg[..]),
}
}
}
let warning = format!("lint {} has been renamed to {}",
lint_name, new_name);
match span {
- Some(span) => sess.span_warn(span, &warning[]),
- None => sess.warn(&warning[]),
+ Some(span) => sess.span_warn(span, &warning[..]),
+ None => sess.warn(&warning[..]),
};
Some(lint_id)
}
pub fn process_command_line(&mut self, sess: &Session) {
for &(ref lint_name, level) in &sess.opts.lint_opts {
- match self.find_lint(&lint_name[], sess, None) {
+ match self.find_lint(&lint_name[..], sess, None) {
Some(lint_id) => self.set_level(lint_id, (level, CommandLine)),
None => {
match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone()))
.collect::<FnvHashMap<&'static str,
Vec<LintId>>>()
- .get(&lint_name[]) {
+ .get(&lint_name[..]) {
Some(v) => {
v.iter()
.map(|lint_id: &LintId|
if level == Forbid { level = Deny; }
match (level, span) {
- (Warn, Some(sp)) => sess.span_warn(sp, &msg[]),
- (Warn, None) => sess.warn(&msg[]),
- (Deny, Some(sp)) => sess.span_err(sp, &msg[]),
- (Deny, None) => sess.err(&msg[]),
+ (Warn, Some(sp)) => sess.span_warn(sp, &msg[..]),
+ (Warn, None) => sess.warn(&msg[..]),
+ (Deny, Some(sp)) => sess.span_err(sp, &msg[..]),
+ (Deny, None) => sess.err(&msg[..]),
_ => sess.bug("impossible level in raw_emit_lint"),
}
if let Some(note) = note {
- sess.note(¬e[]);
+ sess.note(¬e[..]);
}
if let Some(span) = def {
match self.lints.find_lint(&lint_name, &self.tcx.sess, Some(span)) {
Some(lint_id) => vec![(lint_id, level, span)],
None => {
- match self.lints.lint_groups.get(&lint_name[]) {
+ match self.lints.lint_groups.get(&lint_name[..]) {
Some(&(ref v, _)) => v.iter()
.map(|lint_id: &LintId|
(*lint_id, level, span))
None => {}
Some(lints) => {
for (lint_id, span, msg) in lints {
- self.span_lint(lint_id.lint, span, &msg[])
+ self.span_lint(lint_id.lint, span, &msg[..])
}
}
}
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 {
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ let ptr = self.lint as *const Lint;
+ ptr.hash(state);
+ }
+}
impl LintId {
/// Get the `LintId` for a `Lint`.
let name = match *path_opt {
Some((ref path_str, _)) => {
let name = path_str.to_string();
- validate_crate_name(Some(self.sess), &name[],
+ validate_crate_name(Some(self.sess), &name[..],
Some(i.span));
name
}
let source = self.sess.cstore.get_used_crate_source(cnum).unwrap();
if let Some(locs) = self.sess.opts.externs.get(name) {
let found = locs.iter().any(|l| {
- let l = fs::realpath(&Path::new(&l[])).ok();
+ let l = fs::realpath(&Path::new(&l[..])).ok();
source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
});
let mut load_ctxt = loader::Context {
sess: self.sess,
span: span,
- ident: &ident[],
- crate_name: &name[],
+ ident: &ident[..],
+ crate_name: &name[..],
hash: None,
filesearch: self.sess.host_filesearch(PathKind::Crate),
target: &self.sess.host,
name,
config::host_triple(),
self.sess.opts.target_triple);
- self.sess.span_err(span, &message[]);
+ self.sess.span_err(span, &message[..]);
self.sess.abort_if_errors();
}
let message = format!("plugin `{}` only found in rlib format, \
but must be available in dylib format",
name);
- self.sess.span_err(span, &message[]);
+ self.sess.span_err(span, &message[..]);
// No need to abort because the loading code will just ignore this
// empty dylib.
None
pub fn get_used_crate_source(&self, cnum: ast::CrateNum)
-> Option<CrateSource> {
self.used_crate_sources.borrow_mut()
- .iter().find(|source| source.cnum == cnum)
- .map(|source| source.clone())
+ .iter().find(|source| source.cnum == cnum).cloned()
}
pub fn reset(&self) {
pub fn find_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId)
-> Option<ast::CrateNum> {
- self.extern_mod_crate_map.borrow().get(&emod_id).map(|x| *x)
+ self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
}
}
rbml_w.end_tag();
rbml_w.start_tag(tag_mod_child);
- rbml_w.wr_str(&s[]);
+ rbml_w.wr_str(&s[..]);
rbml_w.end_tag();
}
let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
let idx = encode_info_for_struct(ecx,
rbml_w,
- &fields[],
+ &fields[..],
index);
- encode_struct_fields(rbml_w, &fields[], def_id);
+ encode_struct_fields(rbml_w, &fields[..], def_id);
encode_index(rbml_w, idx, write_i64);
}
}
class itself */
let idx = encode_info_for_struct(ecx,
rbml_w,
- &fields[],
+ &fields[..],
index);
/* Index the class*/
/* Encode def_ids for each field and method
for methods, write all the stuff get_trait_method
needs to know*/
- encode_struct_fields(rbml_w, &fields[], def_id);
+ encode_struct_fields(rbml_w, &fields[..], def_id);
encode_inlined_item(ecx, rbml_w, IIItemRef(item));
// 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>,
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
+ F: FnMut(&mut SeekableMemWriter, &T),
+ T: Hash,
+{
+ 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();
+}
fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
let wr: &mut SeekableMemWriter = writer;
&Some(ref r) => format!("{} which `{}` depends on",
message, r.ident)
};
- self.sess.span_err(self.span, &message[]);
+ self.sess.span_err(self.span, &message[..]);
if self.rejected_via_triple.len() > 0 {
let mismatches = self.rejected_via_triple.iter();
None => return FileDoesntMatch,
Some(file) => file,
};
- let (hash, rlib) = if file.starts_with(&rlib_prefix[]) &&
+ let (hash, rlib) = if file.starts_with(&rlib_prefix[..]) &&
file.ends_with(".rlib") {
(&file[(rlib_prefix.len()) .. (file.len() - ".rlib".len())],
true)
(&file[(dylib_prefix.len()) .. (file.len() - dypair.1.len())],
false)
} else {
- if file.starts_with(&staticlib_prefix[]) &&
+ if file.starts_with(&staticlib_prefix[..]) &&
file.ends_with(".a") {
staticlibs.push(CrateMismatch {
path: path.clone(),
let mut rlibs = HashMap::new();
let mut dylibs = HashMap::new();
{
- let locs = locs.iter().map(|l| Path::new(&l[])).filter(|loc| {
+ let locs = locs.iter().map(|l| Path::new(&l[..])).filter(|loc| {
if !loc.exists() {
sess.err(&format!("extern location for {} does not exist: {}",
self.crate_name, loc.display())[]);
return true
} else {
let (ref prefix, ref suffix) = dylibname;
- if file.starts_with(&prefix[]) &&
- file.ends_with(&suffix[]) {
+ if file.starts_with(&prefix[..]) &&
+ file.ends_with(&suffix[..]) {
return true
}
}
}
}
unsafe {
- let buf = CString::from_slice(filename.as_vec());
+ let buf = CString::new(filename.as_vec()).unwrap();
let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
if mb as int == 0 {
return Err(format!("error reading library: '{}'",
assert_eq!(next(st), '[');
scan(st, |c| c == ']', |bytes| {
let abi_str = str::from_utf8(bytes).unwrap();
- abi::lookup(&abi_str[]).expect(abi_str)
+ abi::lookup(&abi_str[..]).expect(abi_str)
})
}
// Do an Option dance to use the path after it is moved below.
let s = ast_map::path_to_string(path.iter().cloned());
path_as_str = Some(s);
- path_as_str.as_ref().map(|x| &x[])
+ path_as_str.as_ref().map(|x| &x[..])
});
let mut ast_dsr = reader::Decoder::new(ast_doc);
let from_id_range = Decodable::decode(&mut ast_dsr).unwrap();
let s = replace_newline_with_backslash_l(s);
label.push_str(&format!("exiting scope_{} {}",
i,
- &s[])[]);
+ &s[..])[]);
}
dot::LabelText::EscStr(label.into_cow())
}
use middle::ty;
use std::cmp::Ordering;
use std::fmt;
-use std::iter::{range_inclusive, AdditiveIterator, FromIterator, repeat};
+use std::iter::{range_inclusive, AdditiveIterator, FromIterator, IntoIterator, repeat};
use std::num::Float;
use std::slice;
use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat};
pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0)
}).collect();
- let total_width = column_widths.iter().map(|n| *n).sum() + column_count * 3 + 1;
+ let total_width = column_widths.iter().cloned().sum() + column_count * 3 + 1;
let br = repeat('+').take(total_width).collect::<String>();
try!(write!(f, "{}\n", br));
for row in pretty_printed_matrix {
}
impl<'a> FromIterator<Vec<&'a Pat>> for Matrix<'a> {
- fn from_iter<T: Iterator<Item=Vec<&'a Pat>>>(iterator: T) -> Matrix<'a> {
- Matrix(iterator.collect())
+ fn from_iter<T: IntoIterator<Item=Vec<&'a Pat>>>(iter: T) -> Matrix<'a> {
+ Matrix(iter.into_iter().collect())
}
}
}
// Fourth, check for unreachable arms.
- check_arms(cx, &inlined_arms[], source);
+ check_arms(cx, &inlined_arms[..], source);
// Finally, check if the whole match expression is exhaustive.
// Check for empty enum, because is_useful only works on inhabited types.
for pat in pats {
let v = vec![&**pat];
- match is_useful(cx, &seen, &v[], LeaveOutWitness) {
+ match is_useful(cx, &seen, &v[..], LeaveOutWitness) {
NotUseful => {
match source {
ast::MatchSource::IfLetDesugar { .. } => {
fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: ast::MatchSource) {
match is_useful(cx, matrix, &[DUMMY_WILD_PAT], ConstructWitness) {
UsefulWithWitness(pats) => {
- let witness = match &pats[] {
+ let witness = match &pats[..] {
[ref witness] => &**witness,
[] => DUMMY_WILD_PAT,
_ => unreachable!()
ast::MatchSource::ForLoopDesugar => {
// `witness` has the form `Some(<head>)`, peel off the `Some`
let witness = match witness.node {
- ast::PatEnum(_, Some(ref pats)) => match &pats[] {
+ ast::PatEnum(_, Some(ref pats)) => match &pats[..] {
[ref pat] => &**pat,
_ => unreachable!(),
},
UsefulWithWitness(pats) => UsefulWithWitness({
let arity = constructor_arity(cx, &c, left_ty);
let mut result = {
- let pat_slice = &pats[];
+ let pat_slice = &pats[..];
let subpats: Vec<_> = (0..arity).map(|i| {
pat_slice.get(i).map_or(DUMMY_WILD_PAT, |p| &**p)
}).collect();
witness: WitnessPreference) -> Usefulness {
let arity = constructor_arity(cx, &ctor, lty);
let matrix = Matrix(m.iter().filter_map(|r| {
- specialize(cx, &r[], &ctor, 0, arity)
+ specialize(cx, &r[..], &ctor, 0, arity)
}).collect());
match specialize(cx, v, &ctor, 0, arity) {
- Some(v) => is_useful(cx, &matrix, &v[], witness),
+ Some(v) => is_useful(cx, &matrix, &v[..], witness),
None => NotUseful
}
}
None => None,
Some(ast_map::NodeItem(it)) => match it.node {
ast::ItemEnum(ast::EnumDef { ref variants }, _) => {
- variant_expr(&variants[], variant_def.node)
+ variant_expr(&variants[..], variant_def.node)
}
_ => None
},
// NOTE this doesn't do the right thing, it compares inlined
// NodeId's to the original variant_def's NodeId, but they
// come from different crates, so they will likely never match.
- variant_expr(&variants[], variant_def.node).map(|e| e.id)
+ variant_expr(&variants[..], variant_def.node).map(|e| e.id)
}
_ => None
},
pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val {
match eval_const_expr_partial(tcx, e, None) {
Ok(r) => r,
- Err(s) => tcx.sess.span_fatal(e.span, &s[])
+ Err(s) => tcx.sess.span_fatal(e.span, &s[..])
}
}
match lit.node {
ast::LitStr(ref s, _) => const_str((*s).clone()),
ast::LitBinary(ref data) => {
- const_binary(Rc::new(data.iter().map(|x| *x).collect()))
+ const_binary(data.clone())
}
ast::LitByte(n) => const_uint(n as u64),
ast::LitChar(n) => const_uint(n as u64),
let a = match eval_const_expr_partial(tcx, a, ty_hint) {
Ok(a) => a,
Err(s) => {
- tcx.sess.span_err(a.span, &s[]);
+ tcx.sess.span_err(a.span, &s[..]);
return None;
}
};
let b = match eval_const_expr_partial(tcx, b, ty_hint) {
Ok(b) => b,
Err(s) => {
- tcx.sess.span_err(b.span, &s[]);
+ tcx.sess.span_err(b.span, &s[..]);
return None;
}
};
}
fn to_cfgidx_or_die(id: ast::NodeId, index: &NodeMap<CFGIndex>) -> CFGIndex {
- let opt_cfgindex = index.get(&id).map(|&i|i);
+ let opt_cfgindex = index.get(&id).cloned();
opt_cfgindex.unwrap_or_else(|| {
panic!("nodeid_to_index does not have entry for NodeId {}", id);
})
let mut t = on_entry.to_vec();
self.apply_gen_kill(cfgidx, &mut t);
temp_bits = t;
- &temp_bits[]
+ &temp_bits[..]
}
};
debug!("{} each_bit_for_node({:?}, cfgidx={:?}) bits={}",
let mut changed = false;
for &node_id in &edge.data.exiting_scopes {
- let opt_cfg_idx = self.nodeid_to_index.get(&node_id).map(|&i|i);
+ let opt_cfg_idx = self.nodeid_to_index.get(&node_id).cloned();
match opt_cfg_idx {
Some(cfg_idx) => {
let (start, end) = self.compute_id_range(cfg_idx);
let bits = &mut self.kills[start.. end];
debug!("{} add_kills_from_flow_exits flow_exit={:?} bits={} [before]",
self.analysis_name, flow_exit, mut_bits_to_string(bits));
- bits.clone_from_slice(&orig_kills[]);
+ bits.clone_from_slice(&orig_kills[..]);
debug!("{} add_kills_from_flow_exits flow_exit={:?} bits={} [after]",
self.analysis_name, flow_exit, mut_bits_to_string(bits));
}
for attr in lint::gather_attrs(attrs) {
match attr {
Ok((ref name, lint::Allow, _))
- if &name[] == dead_code => return true,
+ if &name[..] == dead_code => return true,
_ => (),
}
}
// Collect what we've got so far in the return vector.
let mut ret = (1..sess.cstore.next_crate_num()).map(|i| {
- match formats.get(&i).map(|v| *v) {
+ match formats.get(&i).cloned() {
v @ Some(cstore::RequireDynamic) => v,
_ => None,
}
use middle::ty::{MethodStatic, MethodStaticClosure};
use util::ppaux::Repr;
-use std::marker;
use syntax::{ast, ast_util};
use syntax::ptr::P;
use syntax::codemap::Span;
MovingMatch,
}
-#[derive(PartialEq,Debug)]
-enum TrackMatchMode<T> {
+#[derive(Copy, PartialEq, Debug)]
+enum TrackMatchMode {
Unknown,
Definite(MatchMode),
Conflicting,
}
-impl<T> marker::Copy for TrackMatchMode<T> {}
-
-impl<T> TrackMatchMode<T> {
+impl TrackMatchMode {
// Builds up the whole match mode for a pattern from its constituent
// parts. The lattice looks like this:
//
return true;
}
- fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &ast::Arm) -> TrackMatchMode<Span> {
+ fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &ast::Arm) -> TrackMatchMode {
let mut mode = Unknown;
for pat in &arm.pats {
self.determine_pat_move_mode(discr_cmt.clone(), &**pat, &mut mode);
fn determine_pat_move_mode(&mut self,
cmt_discr: mc::cmt<'tcx>,
pat: &ast::Pat,
- mode: &mut TrackMatchMode<Span>) {
+ mode: &mut TrackMatchMode) {
debug!("determine_pat_move_mode cmt_discr={} pat={}", cmt_discr.repr(self.tcx()),
pat.repr(self.tcx()));
return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| {
let msg = format!("Pattern has unexpected def: {:?} and type {}",
def,
cmt_pat.ty.repr(tcx));
- tcx.sess.span_bug(pat.span, &msg[])
+ tcx.sess.span_bug(pat.span, &msg[..])
}
}
}
use std::fmt::{Formatter, Error, Debug};
use std::usize;
-use std::collections::BitvSet;
+use std::collections::BitSet;
pub struct Graph<N,E> {
nodes: Vec<Node<N>> ,
DepthFirstTraversal {
graph: self,
stack: vec![start],
- visited: BitvSet::new()
+ visited: BitSet::new()
}
}
}
pub struct DepthFirstTraversal<'g, N:'g, E:'g> {
graph: &'g Graph<N, E>,
stack: Vec<NodeIndex>,
- visited: BitvSet
+ visited: BitSet
}
impl<'g, N, E> Iterator for DepthFirstTraversal<'g, N, E> {
--- /dev/null
+// 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.
+
+//! Applies the "bivariance relationship" to two types and/or regions.
+//! If (A,B) are bivariant then either A <: B or B <: A. It occurs
+//! when type/lifetime parameters are unconstrained. Usually this is
+//! an error, but we permit it in the specific case where a type
+//! parameter is constrained in a where-clause via an associated type.
+//!
+//! There are several ways one could implement bivariance. You could
+//! just do nothing at all, for example, or you could fully verify
+//! that one of the two subtyping relationships hold. We choose to
+//! thread a middle line: we relate types up to regions, but ignore
+//! all region relationships.
+//!
+//! At one point, handling bivariance in this fashion was necessary
+//! for inference, but I'm actually not sure if that is true anymore.
+//! In particular, it might be enough to say (A,B) are bivariant for
+//! all (A,B).
+
+use middle::ty::{BuiltinBounds};
+use middle::ty::{self, Ty};
+use middle::ty::TyVar;
+use middle::infer::combine::*;
+use middle::infer::{cres};
+use middle::infer::type_variable::{BiTo};
+use util::ppaux::{Repr};
+
+use syntax::ast::{Unsafety};
+
+pub struct Bivariate<'f, 'tcx: 'f> {
+ fields: CombineFields<'f, 'tcx>
+}
+
+#[allow(non_snake_case)]
+pub fn Bivariate<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Bivariate<'f, 'tcx> {
+ Bivariate { fields: cf }
+}
+
+impl<'f, 'tcx> Combine<'tcx> for Bivariate<'f, 'tcx> {
+ fn tag(&self) -> String { "Bivariate".to_string() }
+ fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
+
+ fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
+ -> cres<'tcx, Ty<'tcx>>
+ {
+ match v {
+ ty::Invariant => self.equate().tys(a, b),
+ ty::Covariant => self.tys(a, b),
+ ty::Contravariant => self.tys(a, b),
+ ty::Bivariant => self.tys(a, b),
+ }
+ }
+
+ fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
+ -> cres<'tcx, ty::Region>
+ {
+ match v {
+ ty::Invariant => self.equate().regions(a, b),
+ ty::Covariant => self.regions(a, b),
+ ty::Contravariant => self.regions(a, b),
+ ty::Bivariant => self.regions(a, b),
+ }
+ }
+
+ fn regions(&self, a: ty::Region, _: ty::Region) -> cres<'tcx, ty::Region> {
+ Ok(a)
+ }
+
+ fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> {
+ debug!("mts({} <: {})",
+ a.repr(self.fields.infcx.tcx),
+ b.repr(self.fields.infcx.tcx));
+
+ if a.mutbl != b.mutbl { return Err(ty::terr_mutability); }
+ let t = try!(self.tys(a.ty, b.ty));
+ Ok(ty::mt { mutbl: a.mutbl, ty: t })
+ }
+
+ fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> {
+ if a != b {
+ Err(ty::terr_unsafety_mismatch(expected_found(self, a, b)))
+ } else {
+ Ok(a)
+ }
+ }
+
+ fn builtin_bounds(&self,
+ a: BuiltinBounds,
+ b: BuiltinBounds)
+ -> cres<'tcx, BuiltinBounds>
+ {
+ if a != b {
+ Err(ty::terr_builtin_bounds(expected_found(self, a, b)))
+ } else {
+ Ok(a)
+ }
+ }
+
+ fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
+ debug!("{}.tys({}, {})", self.tag(),
+ a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
+ if a == b { return Ok(a); }
+
+ let infcx = self.fields.infcx;
+ let a = infcx.type_variables.borrow().replace_if_possible(a);
+ let b = infcx.type_variables.borrow().replace_if_possible(b);
+ match (&a.sty, &b.sty) {
+ (&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => {
+ infcx.type_variables.borrow_mut().relate_vars(a_id, BiTo, b_id);
+ Ok(a)
+ }
+
+ (&ty::ty_infer(TyVar(a_id)), _) => {
+ try!(self.fields.instantiate(b, BiTo, a_id));
+ Ok(a)
+ }
+
+ (_, &ty::ty_infer(TyVar(b_id))) => {
+ try!(self.fields.instantiate(a, BiTo, b_id));
+ Ok(a)
+ }
+
+ _ => {
+ super_tys(self, a, b)
+ }
+ }
+ }
+
+ fn binders<T>(&self, a: &ty::Binder<T>, b: &ty::Binder<T>) -> cres<'tcx, ty::Binder<T>>
+ where T : Combineable<'tcx>
+ {
+ let a1 = ty::erase_late_bound_regions(self.tcx(), a);
+ let b1 = ty::erase_late_bound_regions(self.tcx(), b);
+ let c = try!(Combineable::combine(self, &a1, &b1));
+ Ok(ty::Binder(c))
+ }
+}
// is also useful to track which value is the "expected" value in
// terms of error reporting.
+use super::bivariate::Bivariate;
use super::equate::Equate;
use super::glb::Glb;
use super::lub::Lub;
use super::unify::InferCtxtMethodsForSimplyUnifiableTypes;
use super::{InferCtxt, cres};
use super::{MiscVariable, TypeTrace};
-use super::type_variable::{RelationDir, EqTo, SubtypeOf, SupertypeOf};
+use super::type_variable::{RelationDir, BiTo, EqTo, SubtypeOf, SupertypeOf};
use middle::subst;
use middle::subst::{ErasedRegions, NonerasedRegions, Substs};
use middle::ty::{BuiltinBounds};
use middle::ty::{self, Ty};
use middle::ty_fold;
-use middle::ty_fold::{TypeFoldable};
+use middle::ty_fold::{TypeFolder, TypeFoldable};
use util::ppaux::Repr;
use std::rc::Rc;
use syntax::codemap::Span;
pub trait Combine<'tcx> : Sized {
- fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx>;
fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.infcx().tcx }
fn tag(&self) -> String;
- fn a_is_expected(&self) -> bool;
- fn trace(&self) -> TypeTrace<'tcx>;
- fn equate<'a>(&'a self) -> Equate<'a, 'tcx>;
- fn sub<'a>(&'a self) -> Sub<'a, 'tcx>;
- fn lub<'a>(&'a self) -> Lub<'a, 'tcx>;
- fn glb<'a>(&'a self) -> Glb<'a, 'tcx>;
+ fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx>;
+
+ fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx> { self.fields().infcx }
+ fn a_is_expected(&self) -> bool { self.fields().a_is_expected }
+ fn trace(&self) -> TypeTrace<'tcx> { self.fields().trace.clone() }
+ fn equate<'a>(&'a self) -> Equate<'a, 'tcx> { self.fields().equate() }
+ fn bivariate<'a>(&'a self) -> Bivariate<'a, 'tcx> { self.fields().bivariate() }
+
+ fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { self.fields().sub() }
+ fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields().clone()) }
+ fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields().clone()) }
fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>>;
- fn contratys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>>;
+
+ fn tys_with_variance(&self, variance: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
+ -> cres<'tcx, Ty<'tcx>>;
+
fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>>;
- fn tps(&self,
- _: subst::ParamSpace,
- as_: &[Ty<'tcx>],
- bs: &[Ty<'tcx>])
- -> cres<'tcx, Vec<Ty<'tcx>>> {
- // FIXME -- In general, we treat variance a bit wrong
- // here. For historical reasons, we treat tps and Self
- // as invariant. This is overly conservative.
-
- if as_.len() != bs.len() {
- return Err(ty::terr_ty_param_size(expected_found(self,
- as_.len(),
- bs.len())));
- }
+ fn regions_with_variance(&self, variance: ty::Variance, a: ty::Region, b: ty::Region)
+ -> cres<'tcx, ty::Region>;
- try!(as_.iter().zip(bs.iter())
- .map(|(a, b)| self.equate().tys(*a, *b))
- .collect::<cres<Vec<Ty>>>());
- Ok(as_.to_vec())
- }
+ fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region>;
fn substs(&self,
item_def_id: ast::DefId,
b_subst: &subst::Substs<'tcx>)
-> cres<'tcx, subst::Substs<'tcx>>
{
+ debug!("substs: item_def_id={} a_subst={} b_subst={}",
+ item_def_id.repr(self.infcx().tcx),
+ a_subst.repr(self.infcx().tcx),
+ b_subst.repr(self.infcx().tcx));
+
let variances = if self.infcx().tcx.variance_computed.get() {
Some(ty::item_variances(self.infcx().tcx, item_def_id))
} else {
for &space in &subst::ParamSpace::all() {
let a_tps = a_subst.types.get_slice(space);
let b_tps = b_subst.types.get_slice(space);
- let tps = try!(self.tps(space, a_tps, b_tps));
+ let t_variances = variances.map(|v| v.types.get_slice(space));
+ let tps = try!(relate_type_params(self, t_variances, a_tps, b_tps));
substs.types.replace(space, tps);
}
for &space in &subst::ParamSpace::all() {
let a_regions = a.get_slice(space);
let b_regions = b.get_slice(space);
-
- let mut invariance = Vec::new();
- let r_variances = match variances {
- Some(variances) => {
- variances.regions.get_slice(space)
- }
- None => {
- for _ in a_regions {
- invariance.push(ty::Invariant);
- }
- &invariance[]
- }
- };
-
+ let r_variances = variances.map(|v| v.regions.get_slice(space));
let regions = try!(relate_region_params(self,
r_variances,
a_regions,
return Ok(substs);
+ fn relate_type_params<'tcx, C: Combine<'tcx>>(this: &C,
+ variances: Option<&[ty::Variance]>,
+ a_tys: &[Ty<'tcx>],
+ b_tys: &[Ty<'tcx>])
+ -> cres<'tcx, Vec<Ty<'tcx>>>
+ {
+ if a_tys.len() != b_tys.len() {
+ return Err(ty::terr_ty_param_size(expected_found(this,
+ a_tys.len(),
+ b_tys.len())));
+ }
+
+ range(0, a_tys.len()).map(|i| {
+ let a_ty = a_tys[i];
+ let b_ty = b_tys[i];
+ let v = variances.map_or(ty::Invariant, |v| v[i]);
+ this.tys_with_variance(v, a_ty, b_ty)
+ }).collect()
+ }
+
fn relate_region_params<'tcx, C: Combine<'tcx>>(this: &C,
- variances: &[ty::Variance],
+ variances: Option<&[ty::Variance]>,
a_rs: &[ty::Region],
b_rs: &[ty::Region])
- -> cres<'tcx, Vec<ty::Region>> {
+ -> cres<'tcx, Vec<ty::Region>>
+ {
let tcx = this.infcx().tcx;
- let num_region_params = variances.len();
+ let num_region_params = a_rs.len();
debug!("relate_region_params(\
a_rs={}, \
b_rs.repr(tcx),
variances.repr(tcx));
- assert_eq!(num_region_params, a_rs.len());
+ assert_eq!(num_region_params,
+ variances.map_or(num_region_params,
+ |v| v.len()));
+
assert_eq!(num_region_params, b_rs.len());
- let mut rs = vec!();
- for i in 0..num_region_params {
+
+ (0..a_rs.len()).map(|i| {
let a_r = a_rs[i];
let b_r = b_rs[i];
- let variance = variances[i];
- let r = match variance {
- ty::Invariant => this.equate().regions(a_r, b_r),
- ty::Covariant => this.regions(a_r, b_r),
- ty::Contravariant => this.contraregions(a_r, b_r),
- ty::Bivariant => Ok(a_r),
- };
- rs.push(try!(r));
- }
- Ok(rs)
+ let variance = variances.map_or(ty::Invariant, |v| v[i]);
+ this.regions_with_variance(variance, a_r, b_r)
+ }).collect()
}
}
}
fn args(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
- self.contratys(a, b).and_then(|t| Ok(t))
+ self.tys_with_variance(ty::Contravariant, a, b).and_then(|t| Ok(t))
}
fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety>;
b: &ty::ExistentialBounds<'tcx>)
-> cres<'tcx, ty::ExistentialBounds<'tcx>>
{
- let r = try!(self.contraregions(a.region_bound, b.region_bound));
+ let r = try!(self.regions_with_variance(ty::Contravariant, a.region_bound, b.region_bound));
let nb = try!(self.builtin_bounds(a.builtin_bounds, b.builtin_bounds));
let pb = try!(self.projection_bounds(&a.projection_bounds, &b.projection_bounds));
Ok(ty::ExistentialBounds { region_bound: r,
b: ty::BuiltinBounds)
-> cres<'tcx, ty::BuiltinBounds>;
- fn contraregions(&self, a: ty::Region, b: ty::Region)
- -> cres<'tcx, ty::Region>;
-
- fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region>;
-
fn trait_refs(&self,
a: &ty::TraitRef<'tcx>,
b: &ty::TraitRef<'tcx>)
}
(&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => {
- let r = try!(this.contraregions(*a_r, *b_r));
+ let r = try!(this.regions_with_variance(ty::Contravariant, *a_r, *b_r));
+
// FIXME(14985) If we have mutable references to trait objects, we
// used to use covariant subtyping. I have preserved this behaviour,
// even though it is probably incorrect. So don't go down the usual
Equate((*self).clone())
}
+ fn bivariate(&self) -> Bivariate<'f, 'tcx> {
+ Bivariate((*self).clone())
+ }
+
fn sub(&self) -> Sub<'f, 'tcx> {
Sub((*self).clone())
}
EqTo => {
self.generalize(a_ty, b_vid, false)
}
- SupertypeOf | SubtypeOf => {
+ BiTo | SupertypeOf | SubtypeOf => {
self.generalize(a_ty, b_vid, true)
}
});
// to associate causes/spans with each of the relations in
// the stack to get this right.
match dir {
+ BiTo => {
+ try!(self.bivariate().tys(a_ty, b_ty));
+ }
+
EqTo => {
try!(self.equate().tys(a_ty, b_ty));
}
}
SupertypeOf => {
- try!(self.sub().contratys(a_ty, b_ty));
+ try!(self.sub().tys_with_variance(ty::Contravariant, a_ty, b_ty));
}
}
}
use middle::ty::TyVar;
use middle::infer::combine::*;
use middle::infer::{cres};
-use middle::infer::glb::Glb;
-use middle::infer::InferCtxt;
-use middle::infer::lub::Lub;
-use middle::infer::sub::Sub;
-use middle::infer::{TypeTrace, Subtype};
+use middle::infer::{Subtype};
use middle::infer::type_variable::{EqTo};
use util::ppaux::{Repr};
}
impl<'f, 'tcx> Combine<'tcx> for Equate<'f, 'tcx> {
- fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx> { self.fields.infcx }
- fn tag(&self) -> String { "eq".to_string() }
- fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
- fn trace(&self) -> TypeTrace<'tcx> { self.fields.trace.clone() }
+ fn tag(&self) -> String { "Equate".to_string() }
+ fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
- fn equate<'a>(&'a self) -> Equate<'a, 'tcx> { Equate(self.fields.clone()) }
- fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { Sub(self.fields.clone()) }
- fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) }
- fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) }
-
- fn contratys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
+ fn tys_with_variance(&self, _: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
+ -> cres<'tcx, Ty<'tcx>>
+ {
+ // Once we're equating, it doesn't matter what the variance is.
self.tys(a, b)
}
- fn contraregions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> {
+ fn regions_with_variance(&self, _: ty::Variance, a: ty::Region, b: ty::Region)
+ -> cres<'tcx, ty::Region>
+ {
+ // Once we're equating, it doesn't matter what the variance is.
self.regions(a, b)
}
ref trace_origins,
ref same_regions) => {
if !same_regions.is_empty() {
- self.report_processed_errors(&var_origins[],
- &trace_origins[],
- &same_regions[]);
+ self.report_processed_errors(&var_origins[..],
+ &trace_origins[..],
+ &same_regions[..]);
}
}
}
sup,
"");
}
+ infer::Operand(span) => {
+ self.tcx.sess.span_err(
+ span,
+ "lifetime of operand does not outlive \
+ the operation");
+ note_and_explain_region(
+ self.tcx,
+ "the operand is only valid for ",
+ sup,
+ "");
+ }
infer::AddrOf(span) => {
self.tcx.sess.span_err(
span,
let parent = self.tcx.map.get_parent(scope_id);
let parent_node = self.tcx.map.find(parent);
let taken = lifetimes_in_scope(self.tcx, scope_id);
- let life_giver = LifeGiver::with_taken(&taken[]);
+ let life_giver = LifeGiver::with_taken(&taken[..]);
let node_inner = match parent_node {
Some(ref node) => match *node {
ast_map::NodeItem(ref item) => {
fn rebuild(&self)
-> (ast::FnDecl, Option<ast::ExplicitSelf_>, ast::Generics) {
- let mut expl_self_opt = self.expl_self_opt.map(|x| x.clone());
+ let mut expl_self_opt = self.expl_self_opt.cloned();
let mut inputs = self.fn_decl.inputs.clone();
let mut output = self.fn_decl.output.clone();
let mut ty_params = self.generics.ty_params.clone();
}
expl_self_opt = self.rebuild_expl_self(expl_self_opt, lifetime,
&anon_nums, ®ion_names);
- inputs = self.rebuild_args_ty(&inputs[], lifetime,
+ inputs = self.rebuild_args_ty(&inputs[..], lifetime,
&anon_nums, ®ion_names);
output = self.rebuild_output(&output, lifetime, &anon_nums, ®ion_names);
ty_params = self.rebuild_ty_params(ty_params, lifetime,
opt_explicit_self, generics);
let msg = format!("consider using an explicit lifetime \
parameter as shown: {}", suggested_fn);
- self.tcx.sess.span_help(span, &msg[]);
+ self.tcx.sess.span_help(span, &msg[..]);
}
fn report_inference_failure(&self,
span,
"...so that return value is valid for the call");
}
+ infer::Operand(span) => {
+ self.tcx.sess.span_err(
+ span,
+ "...so that operand is valid for operation");
+ }
infer::AddrOf(span) => {
self.tcx.sess.span_note(
span,
s.push_str(&num_to_string(self.counter.get())[]);
if !self.taken.contains(&s) {
lifetime = name_to_dummy_lifetime(
- token::str_to_ident(&s[]).name);
+ token::str_to_ident(&s[..]).name);
self.generated.borrow_mut().push(lifetime);
break;
}
use super::combine::*;
use super::lattice::*;
-use super::equate::Equate;
use super::higher_ranked::HigherRankedRelations;
-use super::lub::Lub;
-use super::sub::Sub;
-use super::{cres, InferCtxt};
-use super::{TypeTrace, Subtype};
+use super::{cres};
+use super::Subtype;
use middle::ty::{BuiltinBounds};
use middle::ty::{self, Ty};
}
impl<'f, 'tcx> Combine<'tcx> for Glb<'f, 'tcx> {
- fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx> { self.fields.infcx }
- fn tag(&self) -> String { "glb".to_string() }
- fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
- fn trace(&self) -> TypeTrace<'tcx> { self.fields.trace.clone() }
+ fn tag(&self) -> String { "Glb".to_string() }
+ fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
- fn equate<'a>(&'a self) -> Equate<'a, 'tcx> { Equate(self.fields.clone()) }
- fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { Sub(self.fields.clone()) }
- fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) }
- fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) }
+ fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
+ -> cres<'tcx, Ty<'tcx>>
+ {
+ match v {
+ ty::Invariant => self.equate().tys(a, b),
+ ty::Covariant => self.tys(a, b),
+ ty::Bivariant => self.bivariate().tys(a, b),
+ ty::Contravariant => self.lub().tys(a, b),
+ }
+ }
+
+ fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
+ -> cres<'tcx, ty::Region>
+ {
+ match v {
+ ty::Invariant => self.equate().regions(a, b),
+ ty::Covariant => self.regions(a, b),
+ ty::Bivariant => self.bivariate().regions(a, b),
+ ty::Contravariant => self.lub().regions(a, b),
+ }
+ }
fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> {
let tcx = self.fields.infcx.tcx;
}
}
- fn contratys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
- self.lub().tys(a, b)
- }
-
fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> {
match (a, b) {
(Unsafety::Normal, _) | (_, Unsafety::Normal) => Ok(Unsafety::Normal),
Ok(self.fields.infcx.region_vars.glb_regions(Subtype(self.trace()), a, b))
}
- fn contraregions(&self, a: ty::Region, b: ty::Region)
- -> cres<'tcx, ty::Region> {
- self.lub().regions(a, b)
- }
-
fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
super_lattice_tys(self, a, b)
}
where T : Combineable<'tcx>;
}
-trait InferCtxtExt<'tcx> {
+trait InferCtxtExt {
fn tainted_regions(&self, snapshot: &CombinedSnapshot, r: ty::Region) -> Vec<ty::Region>;
fn region_vars_confined_to_snapshot(&self,
}))
}
-impl<'a,'tcx> InferCtxtExt<'tcx> for InferCtxt<'a,'tcx> {
+impl<'a,'tcx> InferCtxtExt for InferCtxt<'a,'tcx> {
fn tainted_regions(&self, snapshot: &CombinedSnapshot, r: ty::Region) -> Vec<ty::Region> {
self.region_vars.tainted(&snapshot.region_vars_snapshot, r)
}
// except according to those terms.
use super::combine::*;
-use super::equate::Equate;
-use super::glb::Glb;
use super::higher_ranked::HigherRankedRelations;
use super::lattice::*;
-use super::sub::Sub;
-use super::{cres, InferCtxt};
-use super::{TypeTrace, Subtype};
+use super::{cres};
+use super::{Subtype};
use middle::ty::{BuiltinBounds};
use middle::ty::{self, Ty};
}
impl<'f, 'tcx> Combine<'tcx> for Lub<'f, 'tcx> {
- fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx> { self.fields.infcx }
- fn tag(&self) -> String { "lub".to_string() }
- fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
- fn trace(&self) -> TypeTrace<'tcx> { self.fields.trace.clone() }
+ fn tag(&self) -> String { "Lub".to_string() }
+ fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
- fn equate<'a>(&'a self) -> Equate<'a, 'tcx> { Equate(self.fields.clone()) }
- fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { Sub(self.fields.clone()) }
- fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) }
- fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) }
+ fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
+ -> cres<'tcx, Ty<'tcx>>
+ {
+ match v {
+ ty::Invariant => self.equate().tys(a, b),
+ ty::Covariant => self.tys(a, b),
+ ty::Bivariant => self.bivariate().tys(a, b),
+ ty::Contravariant => self.glb().tys(a, b),
+ }
+ }
+
+ fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
+ -> cres<'tcx, ty::Region>
+ {
+ match v {
+ ty::Invariant => self.equate().regions(a, b),
+ ty::Covariant => self.regions(a, b),
+ ty::Bivariant => self.bivariate().regions(a, b),
+ ty::Contravariant => self.glb().regions(a, b),
+ }
+ }
fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> {
let tcx = self.tcx();
}
}
- fn contratys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
- self.glb().tys(a, b)
- }
-
fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> {
match (a, b) {
(Unsafety::Unsafe, _) | (_, Unsafety::Unsafe) => Ok(Unsafety::Unsafe),
Ok(a.intersection(b))
}
- fn contraregions(&self, a: ty::Region, b: ty::Region)
- -> cres<'tcx, ty::Region> {
- self.glb().regions(a, b)
- }
-
fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> {
debug!("{}.regions({}, {})",
self.tag(),
use self::unify::{UnificationTable, InferCtxtMethodsForSimplyUnifiableTypes};
use self::error_reporting::ErrorReporting;
+pub mod bivariate;
pub mod combine;
pub mod equate;
pub mod error_reporting;
// Region in return type of invoked fn must enclose call
CallReturn(Span),
+ // Operands must be in scope
+ Operand(Span),
+
// Region resulting from a `&` expr must enclose the `&` expr
AddrOf(Span),
CallRcvr(a) => a,
CallArg(a) => a,
CallReturn(a) => a,
+ Operand(a) => a,
AddrOf(a) => a,
AutoBorrow(a) => a,
SafeDestructor(a) => a,
CallRcvr(a) => format!("CallRcvr({})", a.repr(tcx)),
CallArg(a) => format!("CallArg({})", a.repr(tcx)),
CallReturn(a) => format!("CallReturn({})", a.repr(tcx)),
+ Operand(a) => format!("Operand({})", a.repr(tcx)),
AddrOf(a) => format!("AddrOf({})", a.repr(tcx)),
AutoBorrow(a) => format!("AutoBorrow({})", a.repr(tcx)),
SafeDestructor(a) => format!("SafeDestructor({})", a.repr(tcx)),
self.expansion(&mut var_data);
self.contraction(&mut var_data);
let values =
- self.extract_values_and_collect_conflicts(&var_data[],
+ self.extract_values_and_collect_conflicts(&var_data[..],
errors);
self.collect_concrete_region_errors(&values, errors);
values
use super::combine::*;
use super::{cres, CresCompare};
-use super::equate::Equate;
-use super::glb::Glb;
use super::higher_ranked::HigherRankedRelations;
-use super::InferCtxt;
-use super::lub::Lub;
-use super::{TypeTrace, Subtype};
+use super::{Subtype};
use super::type_variable::{SubtypeOf, SupertypeOf};
use middle::ty::{BuiltinBounds};
}
impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> {
- fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx> { self.fields.infcx }
- fn tag(&self) -> String { "sub".to_string() }
- fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
- fn trace(&self) -> TypeTrace<'tcx> { self.fields.trace.clone() }
-
- fn equate<'a>(&'a self) -> Equate<'a, 'tcx> { Equate(self.fields.clone()) }
- fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { Sub(self.fields.clone()) }
- fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) }
- fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) }
-
- fn contratys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
- Sub(self.fields.switch_expected()).tys(b, a)
+ fn tag(&self) -> String { "Sub".to_string() }
+ fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
+
+ fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
+ -> cres<'tcx, Ty<'tcx>>
+ {
+ match v {
+ ty::Invariant => self.equate().tys(a, b),
+ ty::Covariant => self.tys(a, b),
+ ty::Bivariant => self.bivariate().tys(a, b),
+ ty::Contravariant => Sub(self.fields.switch_expected()).tys(b, a),
+ }
}
- fn contraregions(&self, a: ty::Region, b: ty::Region)
- -> cres<'tcx, ty::Region> {
- let opp = CombineFields {
- a_is_expected: !self.fields.a_is_expected,
- ..self.fields.clone()
- };
- Sub(opp).regions(b, a)
- }
+ fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
+ -> cres<'tcx, ty::Region>
+ {
+ match v {
+ ty::Invariant => self.equate().regions(a, b),
+ ty::Covariant => self.regions(a, b),
+ ty::Bivariant => self.bivariate().regions(a, b),
+ ty::Contravariant => Sub(self.fields.switch_expected()).regions(b, a),
+ }
+ }
fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> {
debug!("{}.regions({}, {})",
use middle::ty::{self, Ty};
use std::cmp::min;
+use std::marker::PhantomData;
use std::mem;
use std::u32;
use util::snapshot_vec as sv;
Relate(ty::TyVid, ty::TyVid),
}
-struct Delegate<'tcx>;
+struct Delegate<'tcx>(PhantomData<&'tcx ()>);
type Relation = (RelationDir, ty::TyVid);
#[derive(Copy, PartialEq, Debug)]
pub enum RelationDir {
- SubtypeOf, SupertypeOf, EqTo
+ SubtypeOf, SupertypeOf, EqTo, BiTo
}
impl RelationDir {
match self {
SubtypeOf => SupertypeOf,
SupertypeOf => SubtypeOf,
- EqTo => EqTo
+ EqTo => EqTo,
+ BiTo => BiTo,
}
}
}
impl<'tcx> TypeVariableTable<'tcx> {
pub fn new() -> TypeVariableTable<'tcx> {
- TypeVariableTable { values: sv::SnapshotVec::new(Delegate) }
+ TypeVariableTable { values: sv::SnapshotVec::new(Delegate(PhantomData)) }
}
fn relations<'a>(&'a mut self, a: ty::TyVid) -> &'a mut Vec<Relation> {
use middle::infer::InferCtxt;
use std::cell::RefCell;
use std::fmt::Debug;
+use std::marker::PhantomData;
use syntax::ast;
use util::snapshot_vec as sv;
/// made during the snapshot may either be *committed* or *rolled back*.
pub struct Snapshot<K:UnifyKey> {
// Link snapshot to the key type `K` of the table.
- marker: marker::CovariantType<K>,
+ marker: marker::PhantomData<K>,
snapshot: sv::Snapshot,
}
}
#[derive(Copy)]
-pub struct Delegate<K>;
+pub struct Delegate<K>(PhantomData<K>);
// We can't use V:LatticeValue, much as I would like to,
// because frequently the pattern is that V=Option<U> for some
impl<K:UnifyKey> UnificationTable<K> {
pub fn new() -> UnificationTable<K> {
UnificationTable {
- values: sv::SnapshotVec::new(Delegate),
+ values: sv::SnapshotVec::new(Delegate(PhantomData)),
}
}
/// Starts a new snapshot. Each snapshot must be either
/// rolled back or committed in a "LIFO" (stack) order.
pub fn snapshot(&mut self) -> Snapshot<K> {
- Snapshot { marker: marker::CovariantType::<K>,
+ Snapshot { marker: marker::PhantomData::<K>,
snapshot: self.values.start_snapshot() }
}
impl<'a, 'v> Visitor<'v> for LanguageItemCollector<'a> {
fn visit_item(&mut self, item: &ast::Item) {
- match extract(&item.attrs) {
- Some(value) => {
- let item_index = self.item_refs.get(&value[]).map(|x| *x);
-
- match item_index {
- Some(item_index) => {
- self.collect_item(item_index, local_def(item.id), item.span)
- }
- None => {}
- }
+ if let Some(value) = extract(&item.attrs) {
+ let item_index = self.item_refs.get(&value[..]).cloned();
+
+ if let Some(item_index) = item_index {
+ self.collect_item(item_index, local_def(item.id), item.span)
}
- None => {}
}
visit::walk_item(self, item);
ExchangeHeapLangItem, "exchange_heap", exchange_heap;
OwnedBoxLangItem, "owned_box", owned_box;
+ PhantomFnItem, "phantom_fn", phantom_fn;
PhantomDataItem, "phantom_data", phantom_data;
+ // Deprecated:
CovariantTypeItem, "covariant_type", covariant_type;
ContravariantTypeItem, "contravariant_type", contravariant_type;
InvariantTypeItem, "invariant_type", invariant_type;
-
CovariantLifetimeItem, "covariant_lifetime", covariant_lifetime;
ContravariantLifetimeItem, "contravariant_lifetime", contravariant_lifetime;
InvariantLifetimeItem, "invariant_lifetime", invariant_lifetime;
// Uninteresting cases: just propagate in rev exec order
ast::ExprVec(ref exprs) => {
- self.propagate_through_exprs(&exprs[], succ)
+ self.propagate_through_exprs(&exprs[..], succ)
}
ast::ExprRepeat(ref element, ref count) => {
} else {
succ
};
- let succ = self.propagate_through_exprs(&args[], succ);
+ let succ = self.propagate_through_exprs(&args[..], succ);
self.propagate_through_expr(&**f, succ)
}
} else {
succ
};
- self.propagate_through_exprs(&args[], succ)
+ self.propagate_through_exprs(&args[..], succ)
}
ast::ExprTup(ref exprs) => {
- self.propagate_through_exprs(&exprs[], succ)
+ self.propagate_through_exprs(&exprs[..], succ)
}
ast::ExprBinary(op, ref l, ref r) if ast_util::lazy_binop(op.node) => {
pub fn opt_encl_scope(&self, id: CodeExtent) -> Option<CodeExtent> {
//! Returns the narrowest scope that encloses `id`, if any.
- self.scope_map.borrow().get(&id).map(|x| *x)
+ self.scope_map.borrow().get(&id).cloned()
}
#[allow(dead_code)] // used in middle::cfg
generics.lifetimes.iter()
.filter(|l| referenced_idents.iter().any(|&i| i == l.lifetime.name))
- .map(|l| (*l).clone())
+ .cloned()
.collect()
}
}
pub fn self_ty(&self) -> Option<Ty<'tcx>> {
- self.types.get_self().map(|&t| t)
+ self.types.get_self().cloned()
}
pub fn with_self_ty(&self, self_ty: Ty<'tcx>) -> Substs<'tcx> {
//! See `doc.rs` for high-level documentation
+use super::Normalized;
use super::SelectionContext;
-use super::{Obligation, ObligationCause};
+use super::{ObligationCause};
+use super::PredicateObligation;
use super::project;
use super::util;
use middle::subst::{Subst, TypeSpace};
-use middle::ty::{self, Ty};
-use middle::infer::InferCtxt;
+use middle::ty::{self, ToPolyTraitRef, Ty};
+use middle::infer::{self, InferCtxt};
use std::collections::HashSet;
use std::rc::Rc;
use syntax::ast;
use syntax::codemap::DUMMY_SP;
use util::ppaux::Repr;
-pub fn impl_can_satisfy(infcx: &InferCtxt,
- impl1_def_id: ast::DefId,
- impl2_def_id: ast::DefId)
- -> bool
+/// True if there exist types that satisfy both of the two given impls.
+pub fn overlapping_impls(infcx: &InferCtxt,
+ impl1_def_id: ast::DefId,
+ impl2_def_id: ast::DefId)
+ -> bool
{
debug!("impl_can_satisfy(\
impl1_def_id={}, \
impl1_def_id.repr(infcx.tcx),
impl2_def_id.repr(infcx.tcx));
- let param_env = ty::empty_parameter_environment(infcx.tcx);
- let mut selcx = SelectionContext::intercrate(infcx, ¶m_env);
- let cause = ObligationCause::dummy();
-
- // `impl1` provides an implementation of `Foo<X,Y> for Z`.
- let impl1_substs =
- util::fresh_substs_for_impl(infcx, DUMMY_SP, impl1_def_id);
- let impl1_trait_ref =
- (*ty::impl_trait_ref(infcx.tcx, impl1_def_id).unwrap()).subst(infcx.tcx, &impl1_substs);
- let impl1_trait_ref =
- project::normalize(&mut selcx, cause.clone(), &impl1_trait_ref);
-
- // Determine whether `impl2` can provide an implementation for those
- // same types.
- let obligation = Obligation::new(cause,
- ty::Binder(ty::TraitPredicate {
- trait_ref: Rc::new(impl1_trait_ref.value),
- }));
- debug!("impl_can_satisfy(obligation={})", obligation.repr(infcx.tcx));
- selcx.evaluate_impl(impl2_def_id, &obligation) &&
- impl1_trait_ref.obligations.iter().all(
- |o| selcx.evaluate_obligation(o))
+ let param_env = &ty::empty_parameter_environment(infcx.tcx);
+ let selcx = &mut SelectionContext::intercrate(infcx, param_env);
+ infcx.probe(|_| {
+ overlap(selcx, impl1_def_id, impl2_def_id) || overlap(selcx, impl2_def_id, impl1_def_id)
+ })
+}
+
+/// Can the types from impl `a` be used to satisfy impl `b`?
+/// (Including all conditions)
+fn overlap(selcx: &mut SelectionContext,
+ a_def_id: ast::DefId,
+ b_def_id: ast::DefId)
+ -> bool
+{
+ let (a_trait_ref, a_obligations) = impl_trait_ref_and_oblig(selcx, a_def_id);
+ let (b_trait_ref, b_obligations) = impl_trait_ref_and_oblig(selcx, b_def_id);
+
+ // Does `a <: b` hold? If not, no overlap.
+ if let Err(_) = infer::mk_sub_poly_trait_refs(selcx.infcx(),
+ true,
+ infer::Misc(DUMMY_SP),
+ a_trait_ref.to_poly_trait_ref(),
+ b_trait_ref.to_poly_trait_ref()) {
+ return false;
+ }
+
+ // Are any of the obligations unsatisfiable? If so, no overlap.
+ a_obligations.iter()
+ .chain(b_obligations.iter())
+ .all(|o| selcx.evaluate_obligation(o))
+}
+
+/// Instantiate fresh variables for all bound parameters of the impl
+/// and return the impl trait ref with those variables substituted.
+fn impl_trait_ref_and_oblig<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
+ impl_def_id: ast::DefId)
+ -> (Rc<ty::TraitRef<'tcx>>,
+ Vec<PredicateObligation<'tcx>>)
+{
+ let impl_substs =
+ &util::fresh_substs_for_impl(selcx.infcx(), DUMMY_SP, impl_def_id);
+ let impl_trait_ref =
+ ty::impl_trait_ref(selcx.tcx(), impl_def_id).unwrap();
+ let impl_trait_ref =
+ impl_trait_ref.subst(selcx.tcx(), impl_substs);
+ let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
+ project::normalize(selcx, ObligationCause::dummy(), &impl_trait_ref);
+
+ let predicates = ty::lookup_predicates(selcx.tcx(), impl_def_id);
+ let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
+ let Normalized { value: predicates, obligations: normalization_obligations2 } =
+ project::normalize(selcx, ObligationCause::dummy(), &predicates);
+ let impl_obligations =
+ util::predicates_for_generics(selcx.tcx(), ObligationCause::dummy(), 0, &predicates);
+
+ let impl_obligations: Vec<_> =
+ impl_obligations.into_iter()
+ .chain(normalization_obligations1.into_iter())
+ .chain(normalization_obligations2.into_iter())
+ .collect();
+
+ (impl_trait_ref, impl_obligations)
}
pub enum OrphanCheckErr<'tcx> {
pub use self::error_reporting::report_fulfillment_errors;
pub use self::error_reporting::suggest_new_overflow_limit;
pub use self::coherence::orphan_check;
+pub use self::coherence::overlapping_impls;
pub use self::coherence::OrphanCheckErr;
pub use self::fulfill::{FulfillmentContext, RegionObligation};
pub use self::project::MismatchedProjectionTypes;
pub object_ty: Ty<'tcx>,
}
-/// True if there exist types that satisfy both of the two given impls.
-pub fn overlapping_impls(infcx: &InferCtxt,
- impl1_def_id: ast::DefId,
- impl2_def_id: ast::DefId)
- -> bool
-{
- coherence::impl_can_satisfy(infcx, impl1_def_id, impl2_def_id) &&
- coherence::impl_can_satisfy(infcx, impl2_def_id, impl1_def_id)
-}
-
/// Creates predicate obligations from the generic bounds.
pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
cause: ObligationCause<'tcx>,
use super::supertraits;
use super::elaborate_predicates;
-use middle::subst::{self, SelfSpace};
+use middle::subst::{self, SelfSpace, TypeSpace};
use middle::traits;
use middle::ty::{self, Ty};
use std::rc::Rc;
/// Self : Sized declared on the trait
SizedSelf,
+ /// Supertrait reference references `Self` an in illegal location
+ /// (e.g. `trait Foo : Bar<Self>`)
+ SupertraitSelf,
+
/// Method has something illegal
Method(Rc<ty::Method<'tcx>>, MethodViolationCode),
}
{
// Because we query yes/no results frequently, we keep a cache:
let cached_result =
- tcx.object_safety_cache.borrow().get(&trait_ref.def_id()).map(|&r| r);
+ tcx.object_safety_cache.borrow().get(&trait_ref.def_id()).cloned();
let result =
cached_result.unwrap_or_else(|| {
if trait_has_sized_self(tcx, trait_def_id) {
violations.push(ObjectSafetyViolation::SizedSelf);
}
+ if supertraits_reference_self(tcx, trait_def_id) {
+ violations.push(ObjectSafetyViolation::SupertraitSelf);
+ }
debug!("object_safety_violations_for_trait(trait_def_id={}) = {}",
trait_def_id.repr(tcx),
violations
}
+fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
+ trait_def_id: ast::DefId)
+ -> bool
+{
+ let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
+ let trait_ref = trait_def.trait_ref.clone();
+ let predicates = ty::predicates_for_trait_ref(tcx, &ty::Binder(trait_ref));
+ predicates
+ .into_iter()
+ .any(|predicate| {
+ match predicate {
+ ty::Predicate::Trait(ref data) => {
+ // In the case of a trait predicate, we can skip the "self" type.
+ Some(data.def_id()) != tcx.lang_items.phantom_fn() &&
+ data.0.trait_ref.substs.types.get_slice(TypeSpace)
+ .iter()
+ .cloned()
+ .any(is_self)
+ }
+ ty::Predicate::Projection(..) |
+ ty::Predicate::TypeOutlives(..) |
+ ty::Predicate::RegionOutlives(..) |
+ ty::Predicate::Equate(..) => {
+ false
+ }
+ }
+ })
+}
+
fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
trait_def_id: ast::DefId)
-> bool
.any(|predicate| {
match predicate {
ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
- let self_ty = trait_pred.0.self_ty();
- match self_ty.sty {
- ty::ty_param(ref data) => data.space == subst::SelfSpace,
- _ => false,
- }
+ is_self(trait_pred.0.self_ty())
}
ty::Predicate::Projection(..) |
ty::Predicate::Trait(..) |
match *self {
ObjectSafetyViolation::SizedSelf =>
format!("SizedSelf"),
+ ObjectSafetyViolation::SupertraitSelf =>
+ format!("SupertraitSelf"),
ObjectSafetyViolation::Method(ref m, code) =>
format!("Method({},{:?})", m.repr(tcx), code),
}
}
}
+
+fn is_self<'tcx>(ty: Ty<'tcx>) -> bool {
+ match ty.sty {
+ ty::ty_param(ref data) => data.space == subst::SelfSpace,
+ _ => false,
+ }
+}
/// parameters) that would have to be inferred from the impl.
#[derive(PartialEq,Eq,Debug,Clone)]
enum SelectionCandidate<'tcx> {
+ PhantomFnCandidate,
BuiltinCandidate(ty::BuiltinBound),
ParamCandidate(ty::PolyTraitRef<'tcx>),
ImplCandidate(ast::DefId),
{
let cache = self.pick_candidate_cache();
let hashmap = cache.hashmap.borrow();
- hashmap.get(&cache_fresh_trait_pred.0.trait_ref).map(|c| (*c).clone())
+ hashmap.get(&cache_fresh_trait_pred.0.trait_ref).cloned()
}
fn insert_candidate_cache(&mut self,
stack: &TraitObligationStack<'o, 'tcx>)
-> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>>
{
- // Check for overflow.
-
let TraitObligationStack { obligation, .. } = *stack;
let mut candidates = SelectionCandidateSet {
ambiguous: false
};
+ // Check for the `PhantomFn` trait. This is really just a
+ // special annotation that is *always* considered to match, no
+ // matter what the type parameters are etc.
+ if self.tcx().lang_items.phantom_fn() == Some(obligation.predicate.def_id()) {
+ candidates.vec.push(PhantomFnCandidate);
+ return Ok(candidates);
+ }
+
// Other bounds. Consider both in-scope bounds from fn decl
// and applicable impls. There is a certain set of precedence rules here.
let all_bounds =
util::transitive_bounds(
- self.tcx(), &caller_trait_refs[]);
+ self.tcx(), &caller_trait_refs[..]);
let matching_bounds =
all_bounds.filter(
ty::substd_enum_variants(self.tcx(), def_id, substs)
.iter()
.flat_map(|variant| variant.args.iter())
- .map(|&ty| ty)
+ .cloned()
.collect();
nominal(self, bound, def_id, types)
}
try!(self.confirm_builtin_candidate(obligation, builtin_bound))))
}
+ PhantomFnCandidate |
ErrorCandidate => {
Ok(VtableBuiltin(VtableBuiltinData { nested: VecPerParamSpace::empty() }))
}
impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
match *self {
+ PhantomFnCandidate => format!("PhantomFnCandidate"),
ErrorCandidate => format!("ErrorCandidate"),
BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b),
ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)),
use util::nodemap::{FnvHashMap};
use arena::TypedArena;
-use std::borrow::{BorrowFrom, Cow};
+use std::borrow::{Borrow, Cow};
use std::cell::{Cell, RefCell};
use std::cmp;
use std::fmt;
-use std::hash::{Hash, Writer, SipHasher, Hasher};
+use std::hash::{Hash, SipHasher, Hasher};
+#[cfg(stage0)] use std::hash::Writer;
use std::mem;
use std::ops;
use std::rc::Rc;
-use std::vec::CowVec;
+use std::vec::{CowVec, IntoIter};
use collections::enum_set::{EnumSet, CLike};
use std::collections::{HashMap, HashSet};
use syntax::abi;
}
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> {
+ fn hash<H: Hasher>(&self, s: &mut H) {
+ (self as *const _).hash(s)
+ }
+}
pub type Ty<'tcx> = &'tcx TyS<'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> {
+ fn hash<H: Hasher>(&self, s: &mut H) {
+ self.ty.sty.hash(s)
+ }
+}
-impl<'tcx> BorrowFrom<InternedTy<'tcx>> for sty<'tcx> {
- fn borrow_from<'a>(ty: &'a InternedTy<'tcx>) -> &'a sty<'tcx> {
- &ty.ty.sty
+impl<'tcx> Borrow<sty<'tcx>> for InternedTy<'tcx> {
+ fn borrow<'a>(&'a self) -> &'a sty<'tcx> {
+ &self.ty.sty
}
}
}
impl<'tcx> Predicate<'tcx> {
+ /// Iterates over the types in this predicate. Note that in all
+ /// cases this is skipping over a binder, so late-bound regions
+ /// with depth 0 are bound by the predicate.
+ pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> {
+ let vec: Vec<_> = match *self {
+ ty::Predicate::Trait(ref data) => {
+ data.0.trait_ref.substs.types.as_slice().to_vec()
+ }
+ ty::Predicate::Equate(ty::Binder(ref data)) => {
+ vec![data.0, data.1]
+ }
+ ty::Predicate::TypeOutlives(ty::Binder(ref data)) => {
+ vec![data.0]
+ }
+ ty::Predicate::RegionOutlives(..) => {
+ vec![]
+ }
+ ty::Predicate::Projection(ref data) => {
+ let trait_inputs = data.0.projection_ty.trait_ref.substs.types.as_slice();
+ trait_inputs.iter()
+ .cloned()
+ .chain(Some(data.0.ty).into_iter())
+ .collect()
+ }
+ };
+
+ // The only reason to collect into a vector here is that I was
+ // too lazy to make the full (somewhat complicated) iterator
+ // type that would be needed here. But I wanted this fn to
+ // return an iterator conceptually, rather than a `Vec`, so as
+ // to be closer to `Ty::walk`.
+ vec.into_iter()
+ }
+
pub fn has_escaping_regions(&self) -> bool {
match *self {
Predicate::Trait(ref trait_ref) => trait_ref.has_escaping_regions(),
};
match result {
Ok(trait_did) => trait_did,
- Err(err) => cx.sess.fatal(&err[]),
+ Err(err) => cx.sess.fatal(&err[..]),
}
}
}
}
&ty_tup(ref ts) => {
- self.add_tys(&ts[]);
+ self.add_tys(&ts[..]);
}
&ty_bare_fn(_, ref f) => {
def_id: ast::DefId,
input_tys: &[Ty<'tcx>],
output: Ty<'tcx>) -> Ty<'tcx> {
- let input_args = input_tys.iter().map(|ty| *ty).collect();
+ let input_args = input_tys.iter().cloned().collect();
mk_bare_fn(cx,
Some(def_id),
cx.mk_bare_fn(BareFnTy {
assert_eq!(r, Some(self));
walker
}
+
+ pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
+ match self.sty {
+ ty::ty_param(ref d) => Some(d.clone()),
+ _ => None,
+ }
+ }
}
pub fn walk_ty<'tcx, F>(ty_root: Ty<'tcx>, mut f: F)
ty_struct(did, substs) => {
let flds = struct_fields(cx, did, substs);
let mut res =
- TypeContents::union(&flds[],
+ TypeContents::union(&flds[..],
|f| tc_mt(cx, f.mt, cache));
if !lookup_repr_hints(cx, did).contains(&attr::ReprExtern) {
}
ty_tup(ref tys) => {
- TypeContents::union(&tys[],
+ TypeContents::union(&tys[..],
|ty| tc_ty(cx, *ty, cache))
}
ty_enum(did, substs) => {
let variants = substd_enum_variants(cx, did, substs);
let mut res =
- TypeContents::union(&variants[], |variant| {
+ TypeContents::union(&variants[..], |variant| {
TypeContents::union(&variant.args[],
|arg_ty| {
tc_ty(cx, *arg_ty, cache)
-> Representability {
match ty.sty {
ty_tup(ref ts) => {
- find_nonrepresentable(cx, sp, seen, ts.iter().map(|ty| *ty))
+ find_nonrepresentable(cx, sp, seen, ts.iter().cloned())
}
// Fixed-length vectors.
// FIXME(#11924) Behavior undecided for zero-length vectors.
variant: Option<ast::DefId>) -> Option<Ty<'tcx>> {
match (&ty.sty, variant) {
- (&ty_tup(ref v), None) => v.get(i).map(|&t| t),
+ (&ty_tup(ref v), None) => v.get(i).cloned(),
(&ty_struct(def_id, substs), None) => lookup_struct_fields(cx, def_id)
}
pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option<ast::DefId> {
- cx.provided_method_sources.borrow().get(&id).map(|x| *x)
+ cx.provided_method_sources.borrow().get(&id).cloned()
}
pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
match item.node {
ItemTrait(_, _, _, ref ms) => {
let (_, p) =
- ast_util::split_trait_methods(&ms[]);
+ ast_util::split_trait_methods(&ms[..]);
p.iter()
.map(|m| {
match impl_or_trait_item(
}
/// A free variable referred to in a function.
-#[derive(Copy, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
pub struct Freevar {
/// The variable being accessed free.
pub def: def::Def,
{
match tcx.freevars.borrow().get(&fid) {
None => f(&[]),
- Some(d) => f(&d[])
+ Some(d) => f(&d[..])
}
}
pub fn link_name(attrs: &[ast::Attribute]) -> Option<InternedString> {
lang_items::extract(attrs).and_then(|name| {
- $(if &name[] == stringify!($name) {
+ $(if &name[..] == stringify!($name) {
Some(InternedString::new(stringify!($sym)))
} else)* {
None
// inside this crate, so continue would spew "macro undefined"
// errors
Err(err) => {
- self.sess.span_fatal(span, &err[])
+ self.sess.span_fatal(span, &err[..])
}
};
unsafe {
let registrar =
- match lib.symbol(&symbol[]) {
+ match lib.symbol(&symbol[..]) {
Ok(registrar) => {
mem::transmute::<*mut u8,PluginRegistrarFun>(registrar)
}
// again fatal if we can't register macros
Err(err) => {
- self.sess.span_fatal(span, &err[])
+ self.sess.span_fatal(span, &err[..])
}
};
append_configuration(&mut user_cfg, InternedString::new("test"))
}
let mut v = user_cfg.into_iter().collect::<Vec<_>>();
- v.push_all(&default_cfg[]);
+ v.push_all(&default_cfg[..]);
v
}
pub fn build_session_options(matches: &getopts::Matches) -> Options {
let unparsed_crate_types = matches.opt_strs("crate-type");
let crate_types = parse_crate_types_from_list(unparsed_crate_types)
- .unwrap_or_else(|e| early_error(&e[]));
+ .unwrap_or_else(|e| early_error(&e[..]));
let mut lint_opts = vec!();
let mut describe_lints = false;
let mut search_paths = SearchPaths::new();
for s in &matches.opt_strs("L") {
- search_paths.add_path(&s[]);
+ search_paths.add_path(&s[..]);
}
let libs = matches.opt_strs("l").into_iter().map(|s| {
--debuginfo");
}
- let color = match matches.opt_str("color").as_ref().map(|s| &s[]) {
+ let color = match matches.opt_str("color").as_ref().map(|s| &s[..]) {
Some("auto") => Auto,
Some("always") => Always,
Some("never") => Never,
let sessopts = build_session_options(matches);
let sess = build_session(sessopts, None, registry);
let cfg = build_configuration(&sess);
- assert!((attr::contains_name(&cfg[], "test")));
+ assert!((attr::contains_name(&cfg[..], "test")));
}
// When the user supplies --test and --cfg test, don't implicitly add
}
pub fn span_err(&self, sp: Span, msg: &str) {
match split_msg_into_multilines(msg) {
- Some(msg) => self.diagnostic().span_err(sp, &msg[]),
+ Some(msg) => self.diagnostic().span_err(sp, &msg[..]),
None => self.diagnostic().span_err(sp, msg)
}
}
pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
match split_msg_into_multilines(msg) {
- Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[], code),
+ Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[..], code),
None => self.diagnostic().span_err_with_code(sp, msg, code)
}
}
use std::cell::{RefCell, Cell};
use std::collections::HashMap;
use std::fmt::Debug;
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
+#[cfg(stage0)] use std::hash::Hasher;
use std::iter::repeat;
use std::time::Duration;
use std::collections::hash_state::HashState;
/// 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(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,
+ 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,
+ destination: T) -> bool
+ where S: HashState, T: Hash + Eq + Clone,
{
if source == destination {
return true;
/// }
/// ```
#[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
+ where T: Clone + Hash + Eq,
+ U: Clone,
+ S: HashState,
+ F: FnOnce(T) -> U,
{
let key = arg.clone();
let result = cache.borrow().get(&key).map(|result| result.clone());
for c in (0u32..MAX as u32)
.filter_map(|i| from_u32(i))
.map(|i| i.to_string()) {
- assert_eq!(lev_distance(&c[], &c[]), 0);
+ assert_eq!(lev_distance(&c[..], &c[..]), 0);
}
let a = "\nMäry häd ä little lämb\n\nLittle lämb\n";
use std::collections::hash_state::{DefaultState};
use std::collections::{HashMap, HashSet};
use std::default::Default;
-use std::hash::{Hasher, Writer, Hash};
+use std::hash::{Hasher, Hash};
+#[cfg(stage0)] use std::hash::Writer;
use syntax::ast;
pub type FnvHashMap<K, V> = HashMap<K, V, DefaultState<FnvHasher>>;
pub type NodeSet = FnvHashSet<ast::NodeId>;
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> {
+ Default::default()
+}
+#[cfg(not(stage0))]
+pub fn FnvHashSet<V: Hash + Eq>() -> FnvHashSet<V> {
+ Default::default()
+}
pub fn NodeMap<T>() -> NodeMap<T> { FnvHashMap() }
pub fn DefIdMap<T>() -> DefIdMap<T> { FnvHashMap() }
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;
*self = FnvHasher(hash);
}
}
+
+#[cfg(not(stage0))]
+impl Hasher 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);
+ }
+ fn finish(&self) -> u64 { self.0 }
+}
use std::collections::HashMap;
use std::collections::hash_state::HashState;
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
+#[cfg(stage0)] use std::hash::Hasher;
use std::rc::Rc;
use syntax::abi;
use syntax::ast_map;
Some(def_id) => {
s.push_str(" {");
let path_str = ty::item_path_str(cx, def_id);
- s.push_str(&path_str[]);
+ s.push_str(&path_str[..]);
s.push_str("}");
}
None => { }
.iter()
.map(|elem| ty_to_string(cx, *elem))
.collect::<Vec<_>>();
- match &strs[] {
+ match &strs[..] {
[ref string] => format!("({},)", string),
strs => format!("({})", strs.connect(", "))
}
// avoid those ICEs.
let generics = get_generics();
+ let has_self = substs.self_ty().is_some();
let tps = substs.types.get_slice(subst::TypeSpace);
let ty_params = generics.types.get_slice(subst::TypeSpace);
let has_defaults = ty_params.last().map_or(false, |def| def.default.is_some());
let num_defaults = if has_defaults {
ty_params.iter().zip(tps.iter()).rev().take_while(|&(def, &actual)| {
match def.default {
- Some(default) => default.subst(cx, substs) == actual,
+ Some(default) => {
+ if !has_self && ty::type_has_self(default) {
+ // In an object type, there is no `Self`, and
+ // thus if the default value references Self,
+ // the user will be required to give an
+ // explicit value. We can't even do the
+ // substitution below to check without causing
+ // an ICE. (#18956).
+ false
+ } else {
+ default.subst(cx, substs) == actual
+ }
+ }
None => false
}
}).count()
impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for OwnedSlice<T> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
- repr_vec(tcx, &self[])
+ repr_vec(tcx, &self[..])
}
}
// autoderef cannot convert the &[T] handler
impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Vec<T> {
fn repr(&self, tcx: &ctxt<'tcx>) -> String {
- repr_vec(tcx, &self[])
+ repr_vec(tcx, &self[..])
}
}
&base,
trait_ref.substs,
trait_ref.def_id,
- &projection_bounds[],
+ &projection_bounds[..],
|| ty::lookup_trait_def(tcx, trait_ref.def_id).generics.clone())
}
}
}
})
});
- let names: Vec<_> = names.iter().map(|s| &s[]).collect();
+ let names: Vec<_> = names.iter().map(|s| &s[..]).collect();
let value_str = unbound_value.user_string(tcx);
if names.len() == 0 {
}
}
+#[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>,
}
}
+#[cfg(not(stage0))]
+impl<'tcx, S, K, V> Repr<'tcx> for HashMap<K, V, S>
+ where K: Hash + Eq + Repr<'tcx>,
+ V: Repr<'tcx>,
+ S: HashState,
+{
+ 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(", "))
+ }
+}
+
impl<'tcx, T, U> Repr<'tcx> for ty::OutlivesPredicate<T,U>
where T : Repr<'tcx> + TypeFoldable<'tcx>,
U : Repr<'tcx> + TypeFoldable<'tcx>,
args: &str, cwd: Option<&Path>,
paths: &[&Path]) -> ProcessOutput {
let ar = match *maybe_ar_prog {
- Some(ref ar) => &ar[],
+ Some(ref ar) => &ar[..],
None => "ar"
};
let mut cmd = Command::new(ar);
o
},
Err(e) => {
- handler.err(&format!("could not exec `{}`: {}", &ar[],
+ handler.err(&format!("could not exec `{}`: {}", &ar[..],
e)[]);
handler.abort_if_errors();
panic!("rustc::back::archive::run_ar() should not reach this point");
for path in search_paths {
debug!("looking for {} inside {:?}", name, path.display());
- let test = path.join(&oslibname[]);
+ let test = path.join(&oslibname[..]);
if test.exists() { return test }
if oslibname != unixlibname {
- let test = path.join(&unixlibname[]);
+ let test = path.join(&unixlibname[..]);
if test.exists() { return test }
}
}
// as simple comparison is not enough - there
// might be also an extra name suffix
let obj_start = format!("{}", name);
- let obj_start = &obj_start[];
+ let obj_start = &obj_start[..];
// Ignoring all bytecode files, no matter of
// name
let bc_ext = ".bytecode.deflate";
- self.add_archive(rlib, &name[], |fname: &str| {
+ self.add_archive(rlib, &name[..], |fname: &str| {
let skip_obj = lto && fname.starts_with(obj_start)
&& fname.ends_with(".o");
skip_obj || fname.ends_with(bc_ext) || fname == METADATA_FILENAME
// allow running `ar s file.a` to update symbols only.
if self.should_update_symbols {
run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
- "s", Some(self.work_dir.path()), &args[]);
+ "s", Some(self.work_dir.path()), &args[..]);
}
return self.archive;
}
// Add the archive members seen so far, without updating the
// symbol table (`S`).
run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
- "cruS", Some(self.work_dir.path()), &args[]);
+ "cruS", Some(self.work_dir.path()), &args[..]);
args.clear();
args.push(&abs_dst);
// necessary.
let flags = if self.should_update_symbols { "crus" } else { "cruS" };
run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
- flags, Some(self.work_dir.path()), &args[]);
+ flags, Some(self.work_dir.path()), &args[..]);
self.archive
}
} else {
filename
};
- let new_filename = self.work_dir.path().join(&filename[]);
+ let new_filename = self.work_dir.path().join(&filename[..]);
try!(fs::rename(file, &new_filename));
self.members.push(Path::new(filename));
}
debug!("preparing the RPATH!");
let libs = config.used_crates.clone();
- let libs = libs.into_iter().filter_map(|(_, l)| {
- l.map(|p| p.clone())
- }).collect::<Vec<_>>();
-
- let rpaths = get_rpaths(config, &libs[]);
- flags.push_all(&rpaths_to_flags(&rpaths[])[]);
+ let libs = libs.into_iter().filter_map(|(_, l)| l).collect::<Vec<_>>();
+ let rpaths = get_rpaths(config, &libs[..]);
+ flags.push_all(&rpaths_to_flags(&rpaths[..]));
flags
}
}
}
- log_rpaths("relative", &rel_rpaths[]);
- log_rpaths("fallback", &fallback_rpaths[]);
+ log_rpaths("relative", &rel_rpaths[..]);
+ log_rpaths("fallback", &fallback_rpaths[..]);
let mut rpaths = rel_rpaths;
- rpaths.push_all(&fallback_rpaths[]);
+ rpaths.push_all(&fallback_rpaths[..]);
// Remove duplicates
- let rpaths = minimize_rpaths(&rpaths[]);
+ let rpaths = minimize_rpaths(&rpaths[..]);
return rpaths;
}
let mut set = HashSet::new();
let mut minimized = Vec::new();
for rpath in rpaths {
- if set.insert(&rpath[]) {
+ if set.insert(&rpath[..]) {
minimized.push(rpath.clone());
}
}
macro_rules! key {
($key_name:ident) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[]).map(|o| o.as_string()
+ obj.find(&name[..]).map(|o| o.as_string()
.map(|s| base.options.$key_name = s.to_string()));
} );
($key_name:ident, bool) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[])
+ obj.find(&name[..])
.map(|o| o.as_boolean()
.map(|s| base.options.$key_name = s));
} );
($key_name:ident, list) => ( {
let name = (stringify!($key_name)).replace("_", "-");
- obj.find(&name[]).map(|o| o.as_array()
+ obj.find(&name[..]).map(|o| o.as_array()
.map(|v| base.options.$key_name = v.iter()
.map(|a| a.as_string().unwrap().to_string()).collect()
)
&self.bccx.loan_path_to_string(move_path)[])
};
- self.bccx.span_err(span, &err_message[]);
+ self.bccx.span_err(span, &err_message[..]);
self.bccx.span_note(
loan_span,
&format!("borrow of `{}` occurs here",
// This represents the collection of all but one of the elements
// from an array at the path described by the move path index.
// Note that attached MovePathIndex should have mem_categorization
- // of InteriorElement (i.e. array dereference `&foo[]`).
+ // of InteriorElement (i.e. array dereference `&foo[..]`).
AllButOneFrom(MovePathIndex),
}
// First, filter out duplicates
moved.sort();
moved.dedup();
- debug!("fragments 1 moved: {:?}", path_lps(&moved[]));
+ debug!("fragments 1 moved: {:?}", path_lps(&moved[..]));
assigned.sort();
assigned.dedup();
- debug!("fragments 1 assigned: {:?}", path_lps(&assigned[]));
+ debug!("fragments 1 assigned: {:?}", path_lps(&assigned[..]));
// Second, build parents from the moved and assigned.
for m in &moved {
parents.sort();
parents.dedup();
- debug!("fragments 2 parents: {:?}", path_lps(&parents[]));
+ debug!("fragments 2 parents: {:?}", path_lps(&parents[..]));
// Third, filter the moved and assigned fragments down to just the non-parents
- moved.retain(|f| non_member(*f, &parents[]));
- debug!("fragments 3 moved: {:?}", path_lps(&moved[]));
+ moved.retain(|f| non_member(*f, &parents[..]));
+ debug!("fragments 3 moved: {:?}", path_lps(&moved[..]));
- assigned.retain(|f| non_member(*f, &parents[]));
- debug!("fragments 3 assigned: {:?}", path_lps(&assigned[]));
+ assigned.retain(|f| non_member(*f, &parents[..]));
+ debug!("fragments 3 assigned: {:?}", path_lps(&assigned[..]));
// Fourth, build the leftover from the moved, assigned, and parents.
for m in &moved {
unmoved.sort();
unmoved.dedup();
- debug!("fragments 4 unmoved: {:?}", frag_lps(&unmoved[]));
+ debug!("fragments 4 unmoved: {:?}", frag_lps(&unmoved[..]));
// Fifth, filter the leftover fragments down to its core.
unmoved.retain(|f| match *f {
AllButOneFrom(_) => true,
- Just(mpi) => non_member(mpi, &parents[]) &&
- non_member(mpi, &moved[]) &&
- non_member(mpi, &assigned[])
+ Just(mpi) => non_member(mpi, &parents[..]) &&
+ non_member(mpi, &moved[..]) &&
+ non_member(mpi, &assigned[..])
});
- debug!("fragments 5 unmoved: {:?}", frag_lps(&unmoved[]));
+ debug!("fragments 5 unmoved: {:?}", frag_lps(&unmoved[..]));
// Swap contents back in.
fragments.unmoved_fragments = unmoved;
let msg = format!("type {} ({:?}) is not fragmentable",
parent_ty.repr(tcx), sty_and_variant_info);
let opt_span = origin_id.and_then(|id|tcx.map.opt_span(id));
- tcx.sess.opt_span_bug(opt_span, &msg[])
+ tcx.sess.opt_span_bug(opt_span, &msg[..])
}
}
}
check_loans::check_loans(this,
&loan_dfcx,
flowed_moves,
- &all_loans[],
+ &all_loans[..],
id,
decl,
body);
set.push_str(", ");
}
let loan_str = self.borrowck_ctxt.loan_path_to_string(&*lp);
- set.push_str(&loan_str[]);
+ set.push_str(&loan_str[..]);
saw_some = true;
true
});
#![allow(non_camel_case_types)]
#![feature(core)]
-#![feature(hash)]
#![feature(int_uint)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
let expanded_crate
= match phase_2_configure_and_expand(&sess,
krate,
- &id[],
+ &id[..],
addl_plugins) {
None => return,
Some(k) => k
&sess,
outdir,
&expanded_crate,
- &id[]));
+ &id[..]));
let mut forest = ast_map::Forest::new(expanded_crate);
let arenas = ty::CtxtArenas::new();
let ast_map = assign_node_ids_and_map(&sess, &mut forest);
- write_out_deps(&sess, input, &outputs, &id[]);
+ write_out_deps(&sess, input, &outputs, &id[..]);
controller_entry_point!(after_write_deps,
CompileState::state_after_write_deps(input,
&sess,
outdir,
&ast_map,
- &id[]));
+ &id[..]));
let analysis = phase_3_run_analysis_passes(sess,
ast_map,
-> Compilation {
match matches.opt_str("explain") {
Some(ref code) => {
- match descriptions.find_description(&code[]) {
+ match descriptions.find_description(&code[..]) {
Some(ref description) => {
println!("{}", description);
}
for lint in lints {
let name = lint.name_lower().replace("_", "-");
println!(" {} {:7.7} {}",
- padded(&name[]), lint.default_level.as_str(), lint.desc);
+ padded(&name[..]), lint.default_level.as_str(), lint.desc);
}
println!("\n");
};
let desc = to.into_iter().map(|x| x.as_str().replace("_", "-"))
.collect::<Vec<String>>().connect(", ");
println!(" {} {}",
- padded(&name[]), desc);
+ padded(&name[..]), desc);
}
println!("\n");
};
}
let matches =
- match getopts::getopts(&args[], &config::optgroups()[]) {
+ match getopts::getopts(&args[..], &config::optgroups()[]) {
Ok(m) => m,
Err(f_stable_attempt) => {
// redo option parsing, including unstable options this time,
"run with `RUST_BACKTRACE=1` for a backtrace".to_string(),
];
for note in &xs {
- emitter.emit(None, ¬e[], None, diagnostic::Note)
+ emitter.emit(None, ¬e[..], None, diagnostic::Note)
}
match r.read_to_string() {
ItemViaNode(node_id) =>
NodesMatchingDirect(Some(node_id).into_iter()),
ItemViaPath(ref parts) =>
- NodesMatchingSuffix(map.nodes_matching_suffix(&parts[])),
+ NodesMatchingSuffix(map.nodes_matching_suffix(&parts[..])),
}
}
user_option,
self.reconstructed_input(),
is_wrong_because);
- sess.fatal(&message[])
+ sess.fatal(&message[..])
};
let mut saw_node = ast::DUMMY_NODE_ID;
let is_expanded = needs_expansion(&ppm);
let compute_ast_map = needs_ast_map(&ppm, &opt_uii);
let krate = if compute_ast_map {
- match driver::phase_2_configure_and_expand(&sess, krate, &id[], None) {
+ match driver::phase_2_configure_and_expand(&sess, krate, &id[..], None) {
None => return,
Some(k) => k
}
};
let src_name = driver::source_name(input);
- let src = sess.codemap().get_filemap(&src_name[])
+ let src = sess.codemap().get_filemap(&src_name[..])
.src.as_bytes().to_vec();
let mut rdr = MemReader::new(src);
// point to what was found, if there's an
// accessible span.
match ast_map.opt_span(nodeid) {
- Some(sp) => sess.span_fatal(sp, &message[]),
- None => sess.fatal(&message[])
+ Some(sp) => sess.span_fatal(sp, &message[..]),
+ None => sess.fatal(&message[..])
}
}
}
output_ty: Ty<'tcx>)
-> Ty<'tcx>
{
- let input_args = input_tys.iter().map(|ty| *ty).collect();
+ let input_args = input_tys.iter().cloned().collect();
ty::mk_bare_fn(self.infcx.tcx,
None,
self.infcx.tcx.mk_bare_fn(ty::BareFnTy {
pub fn t_param(&self, space: subst::ParamSpace, index: u32) -> Ty<'tcx> {
let name = format!("T{}", index);
- ty::mk_param(self.infcx.tcx, space, index, token::intern(&name[]))
+ ty::mk_param(self.infcx.tcx, space, index, token::intern(&name[..]))
}
pub fn re_early_bound(&self,
/// raised.
pub fn open(dst: &Path) -> Option<ArchiveRO> {
unsafe {
- let s = CString::from_slice(dst.as_vec());
+ let s = CString::new(dst.as_vec()).unwrap();
let ar = ::LLVMRustOpenArchive(s.as_ptr());
if ar.is_null() {
None
pub fn read<'a>(&'a self, file: &str) -> Option<&'a [u8]> {
unsafe {
let mut size = 0 as libc::size_t;
- let file = CString::from_slice(file.as_bytes());
+ let file = CString::new(file).unwrap();
let ptr = ::LLVMRustArchiveReadSection(self.ptr, file.as_ptr(),
&mut size);
if ptr.is_null() {
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
-#![feature(hash)]
#![feature(int_uint)]
#![feature(libc)]
#![feature(link_args)]
}
pub fn mk_target_data(string_rep: &str) -> TargetData {
- let string_rep = CString::from_slice(string_rep.as_bytes());
+ let string_rep = CString::new(string_rep).unwrap();
TargetData {
lltd: unsafe { LLVMCreateTargetData(string_rep.as_ptr()) }
}
match result {
None => true,
Some((span, msg, note)) => {
- self.tcx.sess.span_err(span, &msg[]);
+ self.tcx.sess.span_err(span, &msg[..]);
match note {
Some((span, msg)) => {
- self.tcx.sess.span_note(span, &msg[])
+ self.tcx.sess.span_note(span, &msg[..])
}
None => {},
}
UnnamedField(idx) => format!("field #{} of {} is private",
idx + 1, struct_desc),
};
- self.tcx.sess.span_err(span, &msg[]);
+ self.tcx.sess.span_err(span, &msg[..]);
}
// Given the ID of a method, checks to ensure it's in scope.
#![feature(alloc)]
#![feature(collections)]
#![feature(core)]
-#![feature(hash)]
#![feature(int_uint)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
&import_directive.module_path[],
import_directive.subclass),
help);
- self.resolve_error(span, &msg[]);
+ self.resolve_error(span, &msg[..]);
}
Indeterminate => break, // Bail out. We'll come around next time.
Success(()) => () // Good. Continue.
.iter()
.map(|seg| seg.identifier.name)
.collect();
- self.names_to_string(&names[])
+ self.names_to_string(&names[..])
}
fn import_directive_subclass_to_string(&mut self,
let module_path = &import_directive.module_path;
debug!("(resolving import for module) resolving import `{}::...` in `{}`",
- self.names_to_string(&module_path[]),
+ self.names_to_string(&module_path[..]),
self.module_to_string(&*module_));
// First, resolve the module path for the directive, if necessary.
Some((self.graph_root.get_module(), LastMod(AllPublic)))
} else {
match self.resolve_module_path(module_.clone(),
- &module_path[],
+ &module_path[..],
DontUseLexicalScope,
import_directive.span,
ImportSearch) {
ValueNS => "value",
},
&token::get_name(name));
- span_err!(self.session, import_span, E0252, "{}", &msg[]);
+ span_err!(self.session, import_span, E0252, "{}", &msg[..]);
}
Some(_) | None => {}
}
if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) {
let msg = format!("`{}` is not directly importable",
token::get_name(name));
- span_err!(self.session, import_span, E0253, "{}", &msg[]);
+ span_err!(self.session, import_span, E0253, "{}", &msg[..]);
}
}
crate in this module \
(maybe you meant `use {0}::*`?)",
&token::get_name(name));
- span_err!(self.session, import_span, E0254, "{}", &msg[]);
+ span_err!(self.session, import_span, E0254, "{}", &msg[..]);
}
Some(_) | None => {}
}
let msg = format!("import `{}` conflicts with value \
in this module",
&token::get_name(name));
- span_err!(self.session, import_span, E0255, "{}", &msg[]);
+ span_err!(self.session, import_span, E0255, "{}", &msg[..]);
if let Some(span) = value.value_span {
self.session.span_note(span,
"conflicting value here");
let msg = format!("import `{}` conflicts with type in \
this module",
&token::get_name(name));
- span_err!(self.session, import_span, E0256, "{}", &msg[]);
+ span_err!(self.session, import_span, E0256, "{}", &msg[..]);
if let Some(span) = ty.type_span {
self.session.span_note(span,
"note conflicting type here")
let msg = format!("inherent implementations \
are only allowed on types \
defined in the current module");
- span_err!(self.session, span, E0257, "{}", &msg[]);
+ span_err!(self.session, span, E0257, "{}", &msg[..]);
self.session.span_note(import_span,
"import from other module here")
}
let msg = format!("import `{}` conflicts with existing \
submodule",
&token::get_name(name));
- span_err!(self.session, import_span, E0258, "{}", &msg[]);
+ span_err!(self.session, import_span, E0258, "{}", &msg[..]);
if let Some(span) = ty.type_span {
self.session.span_note(span,
"note conflicting module here")
-> ResolveResult<(Rc<Module>, LastPrivate)> {
fn search_parent_externals(needle: Name, module: &Rc<Module>)
-> Option<Rc<Module>> {
- module.external_module_children.borrow()
- .get(&needle).cloned()
- .map(|_| module.clone())
- .or_else(|| {
- match module.parent_link.clone() {
- ModuleParentLink(parent, _) => {
- search_parent_externals(needle,
- &parent.upgrade().unwrap())
+ match module.external_module_children.borrow().get(&needle) {
+ Some(_) => Some(module.clone()),
+ None => match module.parent_link {
+ ModuleParentLink(ref parent, _) => {
+ search_parent_externals(needle, &parent.upgrade().unwrap())
}
_ => None
}
- })
+ }
}
let mut search_module = module_;
let segment_name = token::get_name(name);
let module_name = self.module_to_string(&*search_module);
let mut span = span;
- let msg = if "???" == &module_name[] {
+ let msg = if "???" == &module_name[..] {
span.hi = span.lo + Pos::from_usize(segment_name.len());
match search_parent_externals(name,
match module_prefix_result {
Failed(None) => {
let mpath = self.names_to_string(module_path);
- let mpath = &mpath[];
+ let mpath = &mpath[..];
match mpath.rfind(':') {
Some(idx) => {
let msg = format!("Could not find `{}` in `{}`",
let mut containing_module;
let mut i;
let first_module_path_string = token::get_name(module_path[0]);
- if "self" == &first_module_path_string[] {
+ if "self" == &first_module_path_string[..] {
containing_module =
self.get_nearest_normal_module_parent_or_self(module_);
i = 1;
- } else if "super" == &first_module_path_string[] {
+ } else if "super" == &first_module_path_string[..] {
containing_module =
self.get_nearest_normal_module_parent_or_self(module_);
i = 0; // We'll handle `super` below.
// Now loop through all the `super`s we find.
while i < module_path.len() {
let string = token::get_name(module_path[i]);
- if "super" != &string[] {
+ if "super" != &string[..] {
break
}
debug!("(resolving module prefix) resolving `super` at {}",
} else {
let err = format!("unresolved import (maybe you meant `{}::*`?)",
sn);
- self.resolve_error((*imports)[index].span, &err[]);
+ self.resolve_error((*imports)[index].span, &err[..]);
}
}
generics,
implemented_traits,
&**self_type,
- &impl_items[]);
+ &impl_items[..]);
}
ItemTrait(_, ref generics, ref bounds, ref trait_items) => {
};
let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
- self.resolve_error(trait_reference.path.span, &msg[]);
+ self.resolve_error(trait_reference.path.span, &msg[..]);
}
Some(def) => {
match def {
None => {
let msg = format!("use of undeclared type name `{}`",
self.path_names_to_string(path));
- self.resolve_error(ty.span, &msg[]);
+ self.resolve_error(ty.span, &msg[..]);
}
}
}
def: {:?}", result);
let msg = format!("`{}` does not name a structure",
self.path_names_to_string(path));
- self.resolve_error(path.span, &msg[]);
+ self.resolve_error(path.span, &msg[..]);
}
}
}
let last_private;
let module = self.current_module.clone();
match self.resolve_module_path(module,
- &module_path[],
+ &module_path[..],
UseLexicalScope,
path.span,
PathSearch) {
let containing_module;
let last_private;
match self.resolve_module_path_from_root(root_module,
- &module_path[],
+ &module_path[..],
0,
path.span,
PathSearch,
Some((span, msg)) => (span, msg),
None => {
let msg = format!("Use of undeclared module `::{}`",
- self.names_to_string(&module_path[]));
+ self.names_to_string(&module_path[..]));
(path.span, msg)
}
};
}
} else {
match this.resolve_module_path(root,
- &name_path[],
+ &name_path[..],
UseLexicalScope,
span,
PathSearch) {
let name_path = path.segments.iter().map(|seg| seg.identifier.name).collect::<Vec<_>>();
// Look for a method in the current self type's impl module.
- match get_module(self, path.span, &name_path[]) {
+ match get_module(self, path.span, &name_path[..]) {
Some(module) => match module.children.borrow().get(&name) {
Some(binding) => {
let p_str = self.path_names_to_string(&path);
def: {:?}", result);
let msg = format!("`{}` does not name a structure",
self.path_names_to_string(path));
- self.resolve_error(path.span, &msg[]);
+ self.resolve_error(path.span, &msg[..]);
}
}
attrs: &[ast::Attribute],
input: &Input) -> String {
let validate = |s: String, span: Option<Span>| {
- creader::validate_crate_name(sess, &s[], span);
+ creader::validate_crate_name(sess, &s[..], span);
s
};
if let Some(sess) = sess {
if let Some(ref s) = sess.opts.crate_name {
if let Some((attr, ref name)) = attr_crate_name {
- if *s != &name[] {
+ if *s != &name[..] {
let msg = format!("--crate-name and #[crate_name] are \
required to match, but `{}` != `{}`",
s, name);
- sess.span_err(attr.span, &msg[]);
+ sess.span_err(attr.span, &msg[..]);
}
}
return validate(s.clone(), None);
symbol_hasher.input_str("-");
symbol_hasher.input_str(link_meta.crate_hash.as_str());
for meta in &*tcx.sess.crate_metadata.borrow() {
- symbol_hasher.input_str(&meta[]);
+ symbol_hasher.input_str(&meta[..]);
}
symbol_hasher.input_str("-");
symbol_hasher.input_str(&encoder::encoded_ty(tcx, t)[]);
if result.len() > 0 &&
result.as_bytes()[0] != '_' as u8 &&
! (result.as_bytes()[0] as char).is_xid_start() {
- return format!("_{}", &result[]);
+ return format!("_{}", &result[..]);
}
return result;
hash.push(EXTRA_CHARS.as_bytes()[extra2] as char);
hash.push(EXTRA_CHARS.as_bytes()[extra3] as char);
- exported_name(path, &hash[])
+ exported_name(path, &hash[..])
}
pub fn mangle_internal_name_by_type_and_seq<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
t: Ty<'tcx>,
name: &str) -> String {
let s = ppaux::ty_to_string(ccx.tcx(), t);
- let path = [PathName(token::intern(&s[])),
+ let path = [PathName(token::intern(&s[..])),
gensym_name(name)];
let hash = get_symbol_hash(ccx, t);
- mangle(path.iter().cloned(), Some(&hash[]))
+ mangle(path.iter().cloned(), Some(&hash[..]))
}
pub fn mangle_internal_name_by_path_and_seq(path: PathElems, flav: &str) -> String {
for &(ref l, kind) in &*sess.cstore.get_used_libraries().borrow() {
match kind {
cstore::NativeStatic => {
- ab.add_native_library(&l[]).unwrap();
+ ab.add_native_library(&l[..]).unwrap();
}
cstore::NativeFramework | cstore::NativeUnknown => {}
}
e)[])
};
- let bc_data_deflated = match flate::deflate_bytes(&bc_data[]) {
+ let bc_data_deflated = match flate::deflate_bytes(&bc_data[..]) {
Some(compressed) => compressed,
None => sess.fatal(&format!("failed to compress bytecode from {}",
bc_filename.display())[])
try! { writer.write_all(RLIB_BYTECODE_OBJECT_MAGIC) };
try! { writer.write_le_u32(1) };
try! { writer.write_le_u64(bc_data_deflated_size) };
- try! { writer.write_all(&bc_data_deflated[]) };
+ try! { writer.write_all(&bc_data_deflated[..]) };
let number_of_bytes_written_so_far =
RLIB_BYTECODE_OBJECT_MAGIC.len() + // magic id
continue
}
};
- ab.add_rlib(&p, &name[], sess.lto()).unwrap();
+ ab.add_rlib(&p, &name[..], sess.lto()).unwrap();
let native_libs = csearch::get_native_libraries(&sess.cstore, cnum);
all_native_libs.extend(native_libs.into_iter());
// The invocations of cc share some flags across platforms
let pname = get_cc_prog(sess);
- let mut cmd = Command::new(&pname[]);
+ let mut cmd = Command::new(&pname[..]);
cmd.args(&sess.target.target.options.pre_link_args[]);
link_args(&mut cmd, sess, dylib, tmpdir.path(),
sess.note(&format!("{:?}", &cmd)[]);
let mut output = prog.error.clone();
output.push_all(&prog.output[]);
- sess.note(str::from_utf8(&output[]).unwrap());
+ sess.note(str::from_utf8(&output[..]).unwrap());
sess.abort_if_errors();
}
debug!("linker stderr:\n{}", String::from_utf8(prog.error).unwrap());
let mut v = b"-Wl,-force_load,".to_vec();
v.push_all(morestack.as_vec());
- cmd.arg(&v[]);
+ cmd.arg(&v[..]);
} else {
cmd.args(&["-Wl,--whole-archive", "-lmorestack", "-Wl,--no-whole-archive"]);
}
if sess.opts.cg.rpath {
let mut v = "-Wl,-install_name,@rpath/".as_bytes().to_vec();
v.push_all(out_filename.filename().unwrap());
- cmd.arg(&v[]);
+ cmd.arg(&v[..]);
}
} else {
cmd.arg("-shared");
// with any #[link_args] attributes found inside the crate
let empty = Vec::new();
cmd.args(&sess.opts.cg.link_args.as_ref().unwrap_or(&empty)[]);
- cmd.args(&used_link_args[]);
+ cmd.args(&used_link_args[..]);
}
// # Native library linking
} else {
// -force_load is the OSX equivalent of --whole-archive, but it
// involves passing the full path to the library to link.
- let lib = archive::find_library(&l[],
+ let lib = archive::find_library(&l[..],
&sess.target.target.options.staticlib_prefix,
&sess.target.target.options.staticlib_suffix,
- &search_path[],
+ &search_path[..],
&sess.diagnostic().handler);
let mut v = b"-Wl,-force_load,".to_vec();
v.push_all(lib.as_vec());
- cmd.arg(&v[]);
+ cmd.arg(&v[..]);
}
}
if takes_hints {
cmd.arg(format!("-l{}", l));
}
cstore::NativeFramework => {
- cmd.arg("-framework").arg(&l[]);
+ cmd.arg("-framework").arg(&l[..]);
}
cstore::NativeStatic => unreachable!(),
}
let mut v = "-l".as_bytes().to_vec();
v.push_all(unlib(&sess.target, cratepath.filestem().unwrap()));
- cmd.arg(&v[]);
+ cmd.arg(&v[..]);
}
}
}
cstore::NativeFramework => {
cmd.arg("-framework");
- cmd.arg(&lib[]);
+ cmd.arg(&lib[..]);
}
cstore::NativeStatic => {
sess.bug("statics shouldn't be propagated");
bc_decoded.len() as libc::size_t) {
write::llvm_err(sess.diagnostic().handler(),
format!("failed to load bc of `{}`",
- &name[]));
+ &name[..]));
}
});
}
// Internalize everything but the reachable symbols of the current module
let cstrs: Vec<CString> = reachable.iter().map(|s| {
- CString::from_slice(s.as_bytes())
+ CString::new(s.clone()).unwrap()
}).collect();
let arr: Vec<*const libc::c_char> = cstrs.iter().map(|c| c.as_ptr()).collect();
let ptr = arr.as_ptr();
use syntax::diagnostic;
use syntax::diagnostic::{Emitter, Handler, Level, mk_handler};
-use std::ffi::{self, CString};
+use std::ffi::{CStr, CString};
use std::old_io::Command;
use std::old_io::fs;
use std::iter::Unfold;
unsafe {
let cstr = llvm::LLVMRustGetLastError();
if cstr == ptr::null() {
- handler.fatal(&msg[]);
+ handler.fatal(&msg[..]);
} else {
- let err = ffi::c_str_to_bytes(&cstr);
+ let err = CStr::from_ptr(cstr).to_bytes();
let err = String::from_utf8_lossy(err).to_string();
libc::free(cstr as *mut _);
handler.fatal(&format!("{}: {}",
- &msg[],
- &err[])[]);
+ &msg[..],
+ &err[..])[]);
}
}
}
output: &Path,
file_type: llvm::FileType) {
unsafe {
- let output_c = CString::from_slice(output.as_vec());
+ let output_c = CString::new(output.as_vec()).unwrap();
let result = llvm::LLVMRustWriteOutputFile(
target, pm, m, output_c.as_ptr(), file_type);
if !result {
Some(ref code) => {
handler.emit_with_code(None,
&diag.msg[],
- &code[],
+ &code[..],
diag.lvl);
},
None => {
fn create_target_machine(sess: &Session) -> TargetMachineRef {
let reloc_model_arg = match sess.opts.cg.relocation_model {
- Some(ref s) => &s[],
+ Some(ref s) => &s[..],
None => &sess.target.target.options.relocation_model[]
};
let reloc_model = match reloc_model_arg {
let fdata_sections = ffunction_sections;
let code_model_arg = match sess.opts.cg.code_model {
- Some(ref s) => &s[],
+ Some(ref s) => &s[..],
None => &sess.target.target.options.code_model[]
};
let triple = &sess.target.target.llvm_target[];
let tm = unsafe {
- let triple = CString::from_slice(triple.as_bytes());
+ let triple = CString::new(triple.as_bytes()).unwrap();
let cpu = match sess.opts.cg.target_cpu {
Some(ref s) => &**s,
None => &*sess.target.target.options.cpu
};
- let cpu = CString::from_slice(cpu.as_bytes());
- let features = CString::from_slice(target_feature(sess).as_bytes());
+ let cpu = CString::new(cpu.as_bytes()).unwrap();
+ let features = CString::new(target_feature(sess).as_bytes()).unwrap();
llvm::LLVMRustCreateTargetMachine(
triple.as_ptr(), cpu.as_ptr(), features.as_ptr(),
code_model,
let msg = llvm::build_string(|s| llvm::LLVMWriteSMDiagnosticToString(diag, s))
.expect("non-UTF8 SMDiagnostic");
- report_inline_asm(cgcx, &msg[], cookie);
+ report_inline_asm(cgcx, &msg[..], cookie);
}
unsafe extern "C" fn diagnostic_handler(info: DiagnosticInfoRef, user: *mut c_void) {
}
llvm::diagnostic::Optimization(opt) => {
- let pass_name = str::from_utf8(ffi::c_str_to_bytes(&opt.pass_name))
+ let pass_name = str::from_utf8(CStr::from_ptr(opt.pass_name).to_bytes())
.ok()
.expect("got a non-UTF8 pass name from LLVM");
let enabled = match cgcx.remark {
if config.emit_no_opt_bc {
let ext = format!("{}.no-opt.bc", name_extra);
let out = output_names.with_extension(&ext);
- let out = CString::from_slice(out.as_vec());
+ let out = CString::new(out.as_vec()).unwrap();
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
}
// If we're verifying or linting, add them to the function pass
// manager.
let addpass = |pass: &str| {
- let pass = CString::from_slice(pass.as_bytes());
+ let pass = CString::new(pass).unwrap();
llvm::LLVMRustAddPass(fpm, pass.as_ptr())
};
if !config.no_verify { assert!(addpass("verify")); }
}
for pass in &config.passes {
- let pass = CString::from_slice(pass.as_bytes());
+ let pass = CString::new(pass.clone()).unwrap();
if !llvm::LLVMRustAddPass(mpm, pass.as_ptr()) {
cgcx.handler.warn(&format!("unknown pass {:?}, ignoring", pass));
}
if config.emit_lto_bc {
let name = format!("{}.lto.bc", name_extra);
let out = output_names.with_extension(&name);
- let out = CString::from_slice(out.as_vec());
+ let out = CString::new(out.as_vec()).unwrap();
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
}
},
if config.emit_bc {
let ext = format!("{}.bc", name_extra);
let out = output_names.with_extension(&ext);
- let out = CString::from_slice(out.as_vec());
+ let out = CString::new(out.as_vec()).unwrap();
llvm::LLVMWriteBitcodeToFile(llmod, out.as_ptr());
}
if config.emit_ir {
let ext = format!("{}.ll", name_extra);
let out = output_names.with_extension(&ext);
- let out = CString::from_slice(out.as_vec());
+ let out = CString::new(out.as_vec()).unwrap();
with_codegen(tm, llmod, config.no_builtins, |cpm| {
llvm::LLVMRustPrintModule(cpm, llmod, out.as_ptr());
})
};
let pname = get_cc_prog(sess);
- let mut cmd = Command::new(&pname[]);
+ let mut cmd = Command::new(&pname[..]);
cmd.args(&sess.target.target.options.pre_link_args[]);
cmd.arg("-nostdlib");
for i in 0..trans.modules.len() {
if modules_config.emit_obj {
let ext = format!("{}.o", i);
- remove(sess, &crate_output.with_extension(&ext[]));
+ remove(sess, &crate_output.with_extension(&ext[..]));
}
if modules_config.emit_bc && !keep_numbered_bitcode {
let ext = format!("{}.bc", i);
- remove(sess, &crate_output.with_extension(&ext[]));
+ remove(sess, &crate_output.with_extension(&ext[..]));
}
}
pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) {
let pname = get_cc_prog(sess);
- let mut cmd = Command::new(&pname[]);
+ let mut cmd = Command::new(&pname[..]);
cmd.arg("-c").arg("-o").arg(outputs.path(config::OutputTypeObject))
.arg(outputs.temp_path(config::OutputTypeAssembly));
sess.note(&format!("{:?}", &cmd)[]);
let mut note = prog.error.clone();
note.push_all(&prog.output[]);
- sess.note(str::from_utf8(¬e[]).unwrap());
+ sess.note(str::from_utf8(¬e[..]).unwrap());
sess.abort_if_errors();
}
},
let mut llvm_args = Vec::new();
{
let mut add = |arg: &str| {
- let s = CString::from_slice(arg.as_bytes());
+ let s = CString::new(arg).unwrap();
llvm_args.push(s.as_ptr());
llvm_c_strs.push(s);
};
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
-#![feature(hash)]
#![feature(int_uint)]
#![feature(old_io)]
#![feature(env)]
};
self.fmt.sub_mod_ref_str(path.span,
*span,
- &qualname[],
+ &qualname[..],
self.cur_scope);
}
}
};
self.fmt.sub_mod_ref_str(path.span,
*span,
- &qualname[],
+ &qualname[..],
self.cur_scope);
}
}
let (ref span, ref qualname) = sub_paths[len-2];
self.fmt.sub_type_ref_str(path.span,
*span,
- &qualname[]);
+ &qualname[..]);
// write the other sub-paths
if len <= 2 {
for &(ref span, ref qualname) in sub_paths {
self.fmt.sub_mod_ref_str(path.span,
*span,
- &qualname[],
+ &qualname[..],
self.cur_scope);
}
}
id,
qualname,
&path_to_string(p)[],
- &typ[]);
+ &typ[..]);
}
self.collected_paths.clear();
}
};
let qualname = format!("{}::{}", qualname, &get_ident(method.pe_ident()));
- let qualname = &qualname[];
+ let qualname = &qualname[..];
// record the decl for this def (if it has one)
let decl_id = ty::trait_item_of_item(&self.analysis.ty_cx,
Some(sub_span) => self.fmt.field_str(field.span,
Some(sub_span),
field.node.id,
- &name[],
- &qualname[],
- &typ[],
+ &name[..],
+ &qualname[..],
+ &typ[..],
scope_id),
None => self.sess.span_bug(field.span,
&format!("Could not find sub-span for field {}",
self.fmt.typedef_str(full_span,
Some(*param_ss),
param.id,
- &name[],
+ &name[..],
"");
}
self.visit_generics(generics);
self.fmt.fn_str(item.span,
sub_span,
item.id,
- &qualname[],
+ &qualname[..],
self.cur_scope);
- self.process_formals(&decl.inputs, &qualname[]);
+ self.process_formals(&decl.inputs, &qualname[..]);
// walk arg and return types
for arg in &decl.inputs {
// walk the body
self.nest(item.id, |v| v.visit_block(&*body));
- self.process_generic_params(ty_params, item.span, &qualname[], item.id);
+ self.process_generic_params(ty_params, item.span, &qualname[..], item.id);
}
fn process_static(&mut self,
sub_span,
item.id,
&get_ident(item.ident),
- &qualname[],
- &value[],
+ &qualname[..],
+ &value[..],
&ty_to_string(&*typ)[],
self.cur_scope);
sub_span,
item.id,
&get_ident(item.ident),
- &qualname[],
+ &qualname[..],
"",
&ty_to_string(&*typ)[],
self.cur_scope);
sub_span,
item.id,
ctor_id,
- &qualname[],
+ &qualname[..],
self.cur_scope,
- &val[]);
+ &val[..]);
// fields
for field in &def.fields {
- self.process_struct_field_def(field, &qualname[], item.id);
+ self.process_struct_field_def(field, &qualname[..], item.id);
self.visit_ty(&*field.node.ty);
}
- self.process_generic_params(ty_params, item.span, &qualname[], item.id);
+ self.process_generic_params(ty_params, item.span, &qualname[..], item.id);
}
fn process_enum(&mut self,
Some(sub_span) => self.fmt.enum_str(item.span,
Some(sub_span),
item.id,
- &enum_name[],
+ &enum_name[..],
self.cur_scope,
- &val[]),
+ &val[..]),
None => self.sess.span_bug(item.span,
&format!("Could not find subspan for enum {}",
enum_name)[]),
self.span.span_for_first_ident(variant.span),
variant.node.id,
name,
- &qualname[],
- &enum_name[],
- &val[],
+ &qualname[..],
+ &enum_name[..],
+ &val[..],
item.id);
for arg in args {
self.visit_ty(&*arg.ty);
self.span.span_for_first_ident(variant.span),
variant.node.id,
ctor_id,
- &qualname[],
- &enum_name[],
- &val[],
+ &qualname[..],
+ &enum_name[..],
+ &val[..],
item.id);
for field in &struct_def.fields {
}
}
- self.process_generic_params(ty_params, item.span, &enum_name[], item.id);
+ self.process_generic_params(ty_params, item.span, &enum_name[..], item.id);
}
fn process_impl(&mut self,
self.fmt.trait_str(item.span,
sub_span,
item.id,
- &qualname[],
+ &qualname[..],
self.cur_scope,
- &val[]);
+ &val[..]);
// super-traits
for super_bound in &**trait_refs {
}
// walk generics and methods
- self.process_generic_params(generics, item.span, &qualname[], item.id);
+ self.process_generic_params(generics, item.span, &qualname[..], item.id);
for method in methods {
self.visit_trait_item(method)
}
self.fmt.mod_str(item.span,
sub_span,
item.id,
- &qualname[],
+ &qualname[..],
self.cur_scope,
- &filename[]);
+ &filename[..]);
self.nest(item.id, |v| visit::walk_mod(v, m));
}
self.cur_scope);
// walk receiver and args
- visit::walk_exprs(self, &args[]);
+ visit::walk_exprs(self, &args[..]);
}
fn process_pat(&mut self, p:&ast::Pat) {
item.id,
cnum,
name,
- &location[],
+ &location[..],
self.cur_scope);
}
ast::ItemFn(ref decl, _, _, ref ty_params, ref body) =>
self.fmt.typedef_str(item.span,
sub_span,
item.id,
- &qualname[],
- &value[]);
+ &qualname[..],
+ &value[..]);
self.visit_ty(&**ty);
self.process_generic_params(ty_params, item.span, &qualname, item.id);
};
qualname.push_str(&get_ident(method_type.ident));
- let qualname = &qualname[];
+ let qualname = &qualname[..];
let sub_span = self.span.sub_span_after_keyword(method_type.span, keywords::Fn);
self.fmt.method_decl_str(method_type.span,
let mut id = String::from_str("$");
id.push_str(&ex.id.to_string()[]);
- self.process_formals(&decl.inputs, &id[]);
+ self.process_formals(&decl.inputs, &id[..]);
// walk arg and return types
for arg in &decl.inputs {
Some(p.span),
id,
&path_to_string(p)[],
- &value[],
+ &value[..],
"")
}
def::DefVariant(..) | def::DefTy(..) | def::DefStruct(..) => {
sub_span,
id,
&path_to_string(p)[],
- &value[],
- &typ[]);
+ &value[..],
+ &typ[..]);
}
self.collected_paths.clear();
cur_scope: 0
};
- visitor.dump_crate_info(&cratename[], krate);
+ visitor.dump_crate_info(&cratename[..], krate);
visit::walk_crate(&mut visitor, krate);
}
assert!(self.dump_spans);
let result = format!("span,kind,{},{},text,\"{}\"\n",
kind, su.extent_str(span), escape(su.snippet(span)));
- self.record(&result[]);
+ self.record(&result[..]);
}
}
if s.len() > 1020 {
&s[..1020]
} else {
- &s[]
+ &s[..]
}
});
let pairs = fields.iter().zip(values);
let strs = pairs.map(|(f, v)| format!(",{},\"{}\"", f, escape(String::from_str(v))));
Some(strs.fold(String::new(), |mut s, ss| {
- s.push_str(&ss[]);
+ s.push_str(&ss[..]);
s
}))
}
};
let mut result = String::from_str(label);
- result.push_str(&values_str[]);
+ result.push_str(&values_str[..]);
result.push_str("\n");
- self.recorder.record(&result[]);
+ self.recorder.record(&result[..]);
}
pub fn record_with_span(&mut self,
None => return,
};
let result = format!("{},{}{}\n", label, self.span.extent_str(sub_span), values_str);
- self.recorder.record(&result[]);
+ self.recorder.record(&result[..]);
}
pub fn check_and_record(&mut self,
param_env: param_env,
};
enter_match(bcx, dm, m, col, val, |pats|
- check_match::specialize(&mcx, &pats[], &ctor, col, variant_size)
+ check_match::specialize(&mcx, &pats[..], &ctor, col, variant_size)
)
}
if has_nested_bindings(m, col) {
let expanded = expand_nested_bindings(bcx, m, col, val);
compile_submatch_continue(bcx,
- &expanded[],
+ &expanded[..],
vals,
chk,
col,
}
let opt_ms = enter_opt(opt_cx, pat_id, dm, m, opt, col, size, val);
let mut opt_vals = unpacked;
- opt_vals.push_all(&vals_left[]);
+ opt_vals.push_all(&vals_left[..]);
compile_submatch(opt_cx,
- &opt_ms[],
- &opt_vals[],
+ &opt_ms[..],
+ &opt_vals[..],
branch_chk.as_ref().unwrap_or(chk),
has_genuine_default);
}
}
_ => {
compile_submatch(else_cx,
- &defaults[],
- &vals_left[],
+ &defaults[..],
+ &vals_left[..],
chk,
has_genuine_default);
}
&& arm.pats.last().unwrap().node == ast::PatWild(ast::PatWildSingle)
});
- compile_submatch(bcx, &matches[], &[discr_datum.val], &chk, has_default);
+ compile_submatch(bcx, &matches[..], &[discr_datum.val], &chk, has_default);
let mut arm_cxs = Vec::new();
for arm_data in &arm_datas {
arm_cxs.push(bcx);
}
- bcx = scope_cx.fcx.join_blocks(match_id, &arm_cxs[]);
+ bcx = scope_cx.fcx.join_blocks(match_id, &arm_cxs[..]);
return bcx;
}
t: Ty<'tcx>) -> Repr<'tcx> {
match t.sty {
ty::ty_tup(ref elems) => {
- Univariant(mk_struct(cx, &elems[], false, t), false)
+ Univariant(mk_struct(cx, &elems[..], false, t), false)
}
ty::ty_struct(def_id, substs) => {
let fields = ty::lookup_struct_fields(cx.tcx(), def_id);
let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag();
if dtor { ftys.push(cx.tcx().types.bool); }
- Univariant(mk_struct(cx, &ftys[], packed, t), dtor)
+ Univariant(mk_struct(cx, &ftys[..], packed, t), dtor)
}
ty::ty_closure(def_id, _, substs) => {
let typer = NormalizingClosureTyper::new(cx.tcx());
let upvars = typer.closure_upvars(def_id, substs).unwrap();
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
- Univariant(mk_struct(cx, &upvar_types[], false, t), false)
+ Univariant(mk_struct(cx, &upvar_types[..], false, t), false)
}
ty::ty_enum(def_id, substs) => {
let cases = get_cases(cx.tcx(), def_id, substs);
// (Typechecking will reject discriminant-sizing attrs.)
assert_eq!(hint, attr::ReprAny);
let ftys = if dtor { vec!(cx.tcx().types.bool) } else { vec!() };
- return Univariant(mk_struct(cx, &ftys[], false, t),
+ return Univariant(mk_struct(cx, &ftys[..], false, t),
dtor);
}
assert_eq!(hint, attr::ReprAny);
let mut ftys = cases[0].tys.clone();
if dtor { ftys.push(cx.tcx().types.bool); }
- return Univariant(mk_struct(cx, &ftys[], false, t),
+ return Univariant(mk_struct(cx, &ftys[..], false, t),
dtor);
}
let mut ftys = vec!(ty_of_inttype(cx.tcx(), ity));
ftys.push_all(&c.tys[]);
if dtor { ftys.push(cx.tcx().types.bool); }
- mk_struct(cx, &ftys[], false, t)
+ mk_struct(cx, &ftys[..], false, t)
}).collect();
- ensure_enum_fits_in_address_space(cx, &fields[], t);
+ ensure_enum_fits_in_address_space(cx, &fields[..], t);
General(ity, fields, dtor)
}
.map(|&ty| type_of::sizing_type_of(cx, ty)).collect()
};
- ensure_struct_fits_in_address_space(cx, &lltys[], packed, scapegoat);
+ ensure_struct_fits_in_address_space(cx, &lltys[..], packed, scapegoat);
- let llty_rec = Type::struct_(cx, &lltys[], packed);
+ let llty_rec = Type::struct_(cx, &lltys[..], packed);
Struct {
size: machine::llsize_of_alloc(cx, llty_rec),
align: machine::llalign_of_min(cx, llty_rec),
// of the size.
//
// FIXME #10604: this breaks when vector types are present.
- let (size, align) = union_size_and_align(&sts[]);
+ let (size, align) = union_size_and_align(&sts[..]);
let align_s = align as u64;
assert_eq!(size % align_s, 0);
let align_units = size / align_s - 1;
Type::array(&discr_ty, align_s / discr_size - 1),
fill_ty];
match name {
- None => Type::struct_(cx, &fields[], false),
+ None => Type::struct_(cx, &fields[..], false),
Some(name) => {
let mut llty = Type::named_struct(cx, name);
- llty.set_struct_body(&fields[], false);
+ llty.set_struct_body(&fields[..], false);
llty
}
}
fn struct_wrapped_nullable_bitdiscr(bcx: Block, nndiscr: Disr, discrfield: &DiscrField,
scrutinee: ValueRef) -> ValueRef {
- let llptrptr = GEPi(bcx, scrutinee, &discrfield[]);
+ let llptrptr = GEPi(bcx, scrutinee, &discrfield[..]);
let llptr = Load(bcx, llptrptr);
let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
ICmp(bcx, cmp, llptr, C_null(val_ty(llptr)), DebugLoc::None)
}
StructWrappedNullablePointer { nndiscr, ref discrfield, .. } => {
if discr != nndiscr {
- let llptrptr = GEPi(bcx, val, &discrfield[]);
+ let llptrptr = GEPi(bcx, val, &discrfield[..]);
let llptrty = val_ty(llptrptr).element_type();
Store(bcx, C_null(llptrty), llptrptr)
}
let val = if needs_cast {
let ccx = bcx.ccx();
let fields = st.fields.iter().map(|&ty| type_of::type_of(ccx, ty)).collect::<Vec<_>>();
- let real_ty = Type::struct_(ccx, &fields[], st.packed);
+ let real_ty = Type::struct_(ccx, &fields[..], st.packed);
PointerCast(bcx, val, real_ty.ptr_to())
} else {
val
let fields = case.fields.iter().map(|&ty|
type_of::type_of(bcx.ccx(), ty)).collect::<Vec<_>>();
- let real_ty = Type::struct_(ccx, &fields[], case.packed);
+ let real_ty = Type::struct_(ccx, &fields[..], case.packed);
let variant_value = PointerCast(variant_cx, value, real_ty.ptr_to());
variant_cx = f(variant_cx, case, variant_value);
}
General(ity, ref cases, _) => {
let case = &cases[discr as uint];
- let (max_sz, _) = union_size_and_align(&cases[]);
+ let (max_sz, _) = union_size_and_align(&cases[..]);
let lldiscr = C_integral(ll_inttype(ccx, ity), discr as u64, true);
let mut f = vec![lldiscr];
f.push_all(vals);
- let mut contents = build_const_struct(ccx, case, &f[]);
+ let mut contents = build_const_struct(ccx, case, &f[..]);
contents.push_all(&[padding(ccx, max_sz - case.size)]);
- C_struct(ccx, &contents[], false)
+ C_struct(ccx, &contents[..], false)
}
Univariant(ref st, _dro) => {
assert!(discr == 0);
let contents = build_const_struct(ccx, st, vals);
- C_struct(ccx, &contents[], st.packed)
+ C_struct(ccx, &contents[..], st.packed)
}
RawNullablePointer { nndiscr, nnty, .. } => {
if discr == nndiscr {
}).collect::<Vec<ValueRef>>();
C_struct(ccx, &build_const_struct(ccx,
nonnull,
- &vals[])[],
+ &vals[..])[],
false)
}
}
callee::DontAutorefArg)
})
}).collect::<Vec<_>>();
- inputs.push_all(&ext_inputs[]);
+ inputs.push_all(&ext_inputs[..]);
// no failure occurred preparing operands, no need to cleanup
fcx.pop_custom_cleanup_scope(temp_scope);
if !clobbers.is_empty() {
clobbers.push(',');
}
- clobbers.push_str(&more_clobbers[]);
+ clobbers.push_str(&more_clobbers[..]);
}
// Add the clobbers to our constraints list
if clobbers.len() != 0 && constraints.len() != 0 {
constraints.push(',');
- constraints.push_str(&clobbers[]);
+ constraints.push_str(&clobbers[..]);
} else {
- constraints.push_str(&clobbers[]);
+ constraints.push_str(&clobbers[..]);
}
- debug!("Asm Constraints: {}", &constraints[]);
+ debug!("Asm Constraints: {}", &constraints[..]);
let num_outputs = outputs.len();
} else if num_outputs == 1 {
output_types[0]
} else {
- Type::struct_(bcx.ccx(), &output_types[], false)
+ Type::struct_(bcx.ccx(), &output_types[..], false)
};
let dialect = match ia.dialect {
ast::AsmIntel => llvm::AD_Intel
};
- let asm = CString::from_slice(ia.asm.as_bytes());
- let constraints = CString::from_slice(constraints.as_bytes());
+ let asm = CString::new(ia.asm.as_bytes()).unwrap();
+ let constraints = CString::new(constraints).unwrap();
let r = InlineAsmCall(bcx,
asm.as_ptr(),
constraints.as_ptr(),
use arena::TypedArena;
use libc::{c_uint, uint64_t};
-use std::ffi::{self, CString};
+use std::ffi::{CStr, CString};
use std::cell::{Cell, RefCell};
use std::collections::HashSet;
use std::mem;
pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
ty: Type, output: ty::FnOutput) -> ValueRef {
- let buf = CString::from_slice(name.as_bytes());
+ let buf = CString::new(name).unwrap();
let llfn: ValueRef = unsafe {
llvm::LLVMGetOrInsertFunction(ccx.llmod(), buf.as_ptr(), ty.to_ref())
};
let f = decl_rust_fn(ccx, fn_ty, name);
let attrs = csearch::get_item_attrs(&ccx.sess().cstore, did);
- set_llvm_fn_attrs(ccx, &attrs[], f);
+ set_llvm_fn_attrs(ccx, &attrs[..], f);
ccx.externs().borrow_mut().insert(name.to_string(), f);
f
None => ()
}
unsafe {
- let buf = CString::from_slice(name.as_bytes());
+ let buf = CString::new(name.clone()).unwrap();
let c = llvm::LLVMAddGlobal(ccx.llmod(), ty.to_ref(), buf.as_ptr());
// Thread-local statics in some other crate need to *always* be linked
// against in a thread-local fashion, so we need to be sure to apply the
ty::mk_nil(ccx.tcx()));
get_extern_fn(ccx,
&mut *ccx.externs().borrow_mut(),
- &name[],
+ &name[..],
llvm::CCallConv,
llty,
dtor_ty)
ty::ty_bare_fn(_, ref fn_ty) => {
match ccx.sess().target.target.adjust_abi(fn_ty.abi) {
Rust | RustCall => {
- get_extern_rust_fn(ccx, t, &name[], did)
+ get_extern_rust_fn(ccx, t, &name[..], did)
}
RustIntrinsic => {
ccx.sess().bug("unexpected intrinsic in trans_external_path")
}
_ => {
foreign::register_foreign_item_fn(ccx, fn_ty.abi, t,
- &name[])
+ &name[..])
}
}
}
let llresult = Invoke(bcx,
llfn,
- &llargs[],
+ &llargs[..],
normal_bcx.llbb,
landing_pad,
Some(attributes),
let llresult = Call(bcx,
llfn,
- &llargs[],
+ &llargs[..],
Some(attributes),
debug_loc);
return (llresult, bcx);
p
}
-pub fn arrayalloca(cx: Block, ty: Type, v: ValueRef) -> ValueRef {
- let _icx = push_ctxt("arrayalloca");
- if cx.unreachable.get() {
- unsafe {
- return llvm::LLVMGetUndef(ty.to_ref());
- }
- }
- debuginfo::clear_source_location(cx.fcx);
- let p = ArrayAlloca(cx, ty, v);
- call_lifetime_start(cx, p);
- p
-}
-
// Creates the alloca slot which holds the pointer to the slot for the final return value
pub fn make_return_slot_pointer<'a, 'tcx>(fcx: &FunctionContext<'a, 'tcx>,
output_type: Ty<'tcx>) -> ValueRef {
"argtuple",
arg_scope_id));
let untupled_arg_types = match monomorphized_arg_types[0].sty {
- ty::ty_tup(ref types) => &types[],
+ ty::ty_tup(ref types) => &types[..],
_ => {
bcx.tcx().sess.span_bug(args[0].pat.span,
"first arg to `rust-call` ABI function \
let arg_datums = if abi != RustCall {
create_datums_for_fn_args(&fcx,
- &monomorphized_arg_types[])
+ &monomorphized_arg_types[..])
} else {
create_datums_for_fn_args_under_call_abi(
bcx,
arg_scope,
- &monomorphized_arg_types[])
+ &monomorphized_arg_types[..])
};
bcx = match closure_env {
arg_scope,
&decl.inputs[],
arg_datums,
- &monomorphized_arg_types[])
+ &monomorphized_arg_types[..])
}
};
bcx = expr::trans_adt(bcx,
result_ty,
disr,
- &fields[],
+ &fields[..],
None,
expr::SaveIn(llresult),
debug_loc);
ty::erase_late_bound_regions(
ccx.tcx(), &ty::ty_fn_args(ctor_ty));
- let arg_datums = create_datums_for_fn_args(&fcx, &arg_tys[]);
+ let arg_datums = create_datums_for_fn_args(&fcx, &arg_tys[..]);
if !type_is_zero_size(fcx.ccx, result_ty.unwrap()) {
let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot");
ast::ItemImpl(_, _, ref generics, _, _, ref impl_items) => {
meth::trans_impl(ccx,
item.ident,
- &impl_items[],
+ &impl_items[..],
generics,
item.id);
}
_ => panic!("expected bare rust fn")
};
- let llfn = decl_rust_fn(ccx, node_type, &sym[]);
+ let llfn = decl_rust_fn(ccx, node_type, &sym[..]);
finish_register_fn(ccx, sp, sym, node_id, llfn);
llfn
}
match fn_sig.inputs[1].sty {
ty::ty_tup(ref t_in) => {
- inputs.push_all(&t_in[]);
+ inputs.push_all(&t_in[..]);
inputs
}
_ => ccx.sess().bug("expected tuple'd inputs")
debug!("register_fn_llvmty id={} sym={}", node_id, sym);
let llfn = decl_fn(ccx,
- &sym[],
+ &sym[..],
cc,
llfty,
ty::FnConverging(ty::mk_nil(ccx.tcx())));
let (start_fn, args) = if use_start_lang_item {
let start_def_id = match ccx.tcx().lang_items.require(StartFnLangItem) {
Ok(id) => id,
- Err(s) => { ccx.sess().fatal(&s[]); }
+ Err(s) => { ccx.sess().fatal(&s[..]); }
};
let start_fn = if start_def_id.krate == ast::LOCAL_CRATE {
get_item_val(ccx, start_def_id.node)
} else {
llvm::LLVMTypeOf(v)
};
- if contains_null(&sym[]) {
+ if contains_null(&sym[..]) {
ccx.sess().fatal(
&format!("Illegal null byte in export_name \
value: `{}`", sym)[]);
}
- let buf = CString::from_slice(sym.as_bytes());
+ let buf = CString::new(sym.clone()).unwrap();
let g = llvm::LLVMAddGlobal(ccx.llmod(), llty,
buf.as_ptr());
§)[]);
}
unsafe {
- let buf = CString::from_slice(sect.as_bytes());
+ let buf = CString::new(sect.as_bytes()).unwrap();
llvm::LLVMSetSection(v, buf.as_ptr());
}
},
Some(compressed) => compressed,
None => cx.sess().fatal("failed to compress metadata"),
});
- let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[]);
+ let llmeta = C_bytes_in_context(cx.metadata_llcx(), &compressed[..]);
let llconst = C_struct_in_context(cx.metadata_llcx(), &[llmeta], false);
let name = format!("rust_metadata_{}_{}",
cx.link_meta().crate_name,
cx.link_meta().crate_hash);
- let buf = CString::from_vec(name.into_bytes());
+ let buf = CString::new(name).unwrap();
let llglobal = unsafe {
llvm::LLVMAddGlobal(cx.metadata_llmod(), val_ty(llconst).to_ref(),
buf.as_ptr())
unsafe {
llvm::LLVMSetInitializer(llglobal, llconst);
let name = loader::meta_section_name(cx.sess().target.target.options.is_like_osx);
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name).unwrap();
llvm::LLVMSetSection(llglobal, name.as_ptr())
}
return metadata;
continue
}
- let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val))
- .to_vec();
+ let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
+ .to_bytes().to_vec();
declared.insert(name);
}
}
continue
}
- let name = ffi::c_str_to_bytes(&llvm::LLVMGetValueName(val))
- .to_vec();
+ let name = CStr::from_ptr(llvm::LLVMGetValueName(val))
+ .to_bytes().to_vec();
if !declared.contains(&name) &&
!reachable.contains(str::from_utf8(&name).unwrap()) {
llvm::SetLinkage(val, llvm::InternalLinkage);
reachable.push("rust_eh_personality_catch".to_string());
if codegen_units > 1 {
- internalize_symbols(&shared_ccx, &reachable.iter().map(|x| x.clone()).collect());
+ internalize_symbols(&shared_ccx, &reachable.iter().cloned().collect());
}
let metadata_module = ModuleTranslation {
if name.is_empty() {
llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(), noname())
} else {
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name).unwrap();
llvm::LLVMBuildAlloca(self.llbuilder, ty.to_ref(),
name.as_ptr())
}
} else {
let v = ixs.iter().map(|i| C_i32(self.ccx, *i as i32)).collect::<Vec<ValueRef>>();
self.count_insn("gepi");
- self.inbounds_gep(base, &v[])
+ self.inbounds_gep(base, &v[..])
}
}
let s = format!("{} ({})",
text,
self.ccx.sess().codemap().span_to_string(sp));
- debug!("{}", &s[]);
- self.add_comment(&s[]);
+ debug!("{}", &s[..]);
+ self.add_comment(&s[..]);
}
}
let comment_text = format!("{} {}", "#",
sanitized.replace("\n", "\n\t# "));
self.count_insn("inlineasm");
- let comment_text = CString::from_vec(comment_text.into_bytes());
+ let comment_text = CString::new(comment_text).unwrap();
let asm = unsafe {
llvm::LLVMConstInlineAsm(Type::func(&[], &Type::void(self.ccx)).to_ref(),
comment_text.as_ptr(), noname(), False,
}).collect::<Vec<_>>();
debug!("Asm Output Type: {}", self.ccx.tn().type_to_string(output));
- let fty = Type::func(&argtys[], &output);
+ let fty = Type::func(&argtys[..], &output);
unsafe {
let v = llvm::LLVMInlineAsm(
fty.to_ref(), asm, cons, volatile, alignstack, dia as c_uint);
let llfn =
decl_internal_rust_fn(ccx,
tuple_fn_ty,
- &function_name[]);
+ &function_name[..]);
//
let empty_substs = tcx.mk_substs(Substs::trans_empty());
DebugLoc::None,
bare_fn_ty,
|bcx, _| Callee { bcx: bcx, data: Fn(llfnpointer) },
- ArgVals(&llargs[]),
+ ArgVals(&llargs[..]),
dest).bcx;
finish_fn(&fcx, bcx, sig.output, DebugLoc::None);
// Invoke the actual rust fn and update bcx/llresult.
let (llret, b) = base::invoke(bcx,
llfn,
- &llargs[],
+ &llargs[..],
callee_ty,
debug_loc);
bcx = b;
callee_ty,
llfn,
opt_llretslot.unwrap(),
- &llargs[],
+ &llargs[..],
arg_tys,
debug_loc);
}
let name = scope.block_name("clean");
debug!("generating cleanups for {}", name);
let bcx_in = self.new_block(label.is_unwind(),
- &name[],
+ &name[..],
None);
let mut bcx_out = bcx_in;
for cleanup in scope.cleanups.iter().rev() {
Some(llbb) => { return llbb; }
None => {
let name = last_scope.block_name("unwind");
- pad_bcx = self.new_block(true, &name[], None);
+ pad_bcx = self.new_block(true, &name[..], None);
last_scope.cached_landing_pad = Some(pad_bcx.llbb);
}
}
mangle_internal_name_by_path_and_seq(path, "closure")
});
- let llfn = decl_internal_rust_fn(ccx, function_type, &symbol[]);
+ let llfn = decl_internal_rust_fn(ccx, function_type, &symbol[..]);
// set an inline hint for all closures
set_inline_hint(llfn);
let function_type = typer.closure_type(closure_id, param_substs);
let freevars: Vec<ty::Freevar> =
- ty::with_freevars(tcx, id, |fv| fv.iter().map(|&fv| fv).collect());
+ ty::with_freevars(tcx, id, |fv| fv.iter().cloned().collect());
let sig = ty::erase_late_bound_regions(tcx, &function_type.sig);
&[],
sig.output,
function_type.abi,
- ClosureEnv::Closure(&freevars[]));
+ ClosureEnv::Closure(&freevars[..]));
// Don't hoist this to the top of the function. It's perfectly legitimate
// to have a zero-size closure (in which case dest will be `Ignore`) and
opt_node_id: Option<ast::NodeId>)
-> Block<'a, 'tcx> {
unsafe {
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name).unwrap();
let llbb = llvm::LLVMAppendBasicBlockInContext(self.ccx.llcx(),
self.llfn,
name.as_ptr());
pub fn C_floating(s: &str, t: Type) -> ValueRef {
unsafe {
- let s = CString::from_slice(s.as_bytes());
+ let s = CString::new(s).unwrap();
llvm::LLVMConstRealOfString(t.to_ref(), s.as_ptr())
}
}
!null_terminated as Bool);
let gsym = token::gensym("str");
- let buf = CString::from_vec(format!("str{}", gsym.usize()).into_bytes());
+ let buf = CString::new(format!("str{}", gsym.usize()));
+ let buf = buf.unwrap();
let g = llvm::LLVMAddGlobal(cx.llmod(), val_ty(sc).to_ref(), buf.as_ptr());
llvm::LLVMSetInitializer(g, sc);
llvm::LLVMSetGlobalConstant(g, True);
Err(s) => {
let msg = format!("{} {}", msg, s);
match span {
- Some(span) => bcx.tcx().sess.span_fatal(span, &msg[]),
- None => bcx.tcx().sess.fatal(&msg[]),
+ Some(span) => bcx.tcx().sess.span_fatal(span, &msg[..]),
+ None => bcx.tcx().sess.fatal(&msg[..]),
}
}
}
ast::LitBool(b) => C_bool(cx, b),
ast::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()),
ast::LitBinary(ref data) => {
- let g = addr_of(cx, C_bytes(cx, &data[]), "binary", e.id);
+ let g = addr_of(cx, C_bytes(cx, &data[..]), "binary", e.id);
let base = ptrcast(g, Type::i8p(cx));
let prev_const = cx.const_unsized().borrow_mut()
.insert(base, g);
}
ast::ExprTup(ref es) => {
let repr = adt::represent_type(cx, ety);
- let vals = map_list(&es[]);
- adt::trans_const(cx, &*repr, 0, &vals[])
+ let vals = map_list(&es[..]);
+ adt::trans_const(cx, &*repr, 0, &vals[..])
}
ast::ExprStruct(_, ref fs, ref base_opt) => {
let repr = adt::represent_type(cx, ety);
}
}).collect::<Vec<_>>();
if ty::type_is_simd(cx.tcx(), ety) {
- C_vector(&cs[])
+ C_vector(&cs[..])
} else {
- adt::trans_const(cx, &*repr, discr, &cs[])
+ adt::trans_const(cx, &*repr, discr, &cs[..])
}
})
}
.collect::<Vec<_>>();
// If the vector contains enums, an LLVM array won't work.
if vs.iter().any(|vi| val_ty(*vi) != llunitty) {
- C_struct(cx, &vs[], false)
+ C_struct(cx, &vs[..], false)
} else {
- C_array(llunitty, &vs[])
+ C_array(llunitty, &vs[..])
}
}
ast::ExprRepeat(ref elem, ref count) => {
let unit_val = const_expr(cx, &**elem, param_substs).0;
let vs: Vec<_> = repeat(unit_val).take(n).collect();
if val_ty(unit_val) != llunitty {
- C_struct(cx, &vs[], false)
+ C_struct(cx, &vs[..], false)
} else {
- C_array(llunitty, &vs[])
+ C_array(llunitty, &vs[..])
}
}
ast::ExprPath(_) | ast::ExprQPath(_) => {
}
ast::ExprCall(ref callee, ref args) => {
let opt_def = cx.tcx().def_map.borrow().get(&callee.id).cloned();
- let arg_vals = map_list(&args[]);
+ let arg_vals = map_list(&args[..]);
match opt_def {
Some(def::DefStruct(_)) => {
if ty::type_is_simd(cx.tcx(), ety) {
- C_vector(&arg_vals[])
+ C_vector(&arg_vals[..])
} else {
let repr = adt::represent_type(cx, ety);
- adt::trans_const(cx, &*repr, 0, &arg_vals[])
+ adt::trans_const(cx, &*repr, 0, &arg_vals[..])
}
}
Some(def::DefVariant(enum_did, variant_did, _)) => {
adt::trans_const(cx,
&*repr,
vinfo.disr_val,
- &arg_vals[])
+ &arg_vals[..])
}
_ => cx.sess().span_bug(e.span, "expected a struct or variant def")
}
unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextRef, ModuleRef) {
let llcx = llvm::LLVMContextCreate();
- let mod_name = CString::from_slice(mod_name.as_bytes());
+ let mod_name = CString::new(mod_name).unwrap();
let llmod = llvm::LLVMModuleCreateWithNameInContext(mod_name.as_ptr(), llcx);
- let data_layout = &*sess.target.target.data_layout;
- let data_layout = CString::from_slice(data_layout.as_bytes());
+ let data_layout = sess.target.target.data_layout.as_bytes();
+ let data_layout = CString::new(data_layout).unwrap();
llvm::LLVMSetDataLayout(llmod, data_layout.as_ptr());
- let llvm_target = &*sess.target.target.llvm_target;
- let llvm_target = CString::from_slice(llvm_target.as_bytes());
+ let llvm_target = sess.target.target.llvm_target.as_bytes();
+ let llvm_target = CString::new(llvm_target).unwrap();
llvm::LLVMRustSetNormalizedTarget(llmod, llvm_target.as_ptr());
(llcx, llmod)
}
// such as a function name in the module.
// 1. http://llvm.org/bugs/show_bug.cgi?id=11479
let llmod_id = format!("{}.{}.rs", crate_name, i);
- let local_ccx = LocalCrateContext::new(&shared_ccx, &llmod_id[]);
+ let local_ccx = LocalCrateContext::new(&shared_ccx, &llmod_id[..]);
shared_ccx.local_ccxs.push(local_ccx);
}
}
let name = format!("then-block-{}-", thn.id);
- let then_bcx_in = bcx.fcx.new_id_block(&name[], thn.id);
+ let then_bcx_in = bcx.fcx.new_id_block(&name[..], thn.id);
let then_bcx_out = trans_block(then_bcx_in, &*thn, dest);
trans::debuginfo::clear_source_location(bcx.fcx);
let did = langcall(bcx, Some(call_info.span), "", PanicFnLangItem);
let bcx = callee::trans_lang_call(bcx,
did,
- &args[],
+ &args[..],
Some(expr::Ignore),
call_info.debug_loc()).bcx;
Unreachable(bcx);
let did = langcall(bcx, Some(call_info.span), "", PanicBoundsCheckFnLangItem);
let bcx = callee::trans_lang_call(bcx,
did,
- &args[],
+ &args[..],
Some(expr::Ignore),
call_info.debug_loc()).bcx;
Unreachable(bcx);
if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
let unique_type_id_str = self.get_unique_type_id_as_string(unique_type_id);
cx.sess().bug(&format!("Type metadata for unique id '{}' is already in the TypeMap!",
- &unique_type_id_str[])[]);
+ &unique_type_id_str[..])[]);
}
}
self.get_unique_type_id_of_type(cx, component_type);
let component_type_id =
self.get_unique_type_id_as_string(component_type_id);
- unique_type_id.push_str(&component_type_id[]);
+ unique_type_id.push_str(&component_type_id[..]);
}
},
ty::ty_uniq(inner_type) => {
unique_type_id.push('~');
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
- unique_type_id.push_str(&inner_type_id[]);
+ unique_type_id.push_str(&inner_type_id[..]);
},
ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => {
unique_type_id.push('*');
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
- unique_type_id.push_str(&inner_type_id[]);
+ unique_type_id.push_str(&inner_type_id[..]);
},
ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => {
unique_type_id.push('&');
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
- unique_type_id.push_str(&inner_type_id[]);
+ unique_type_id.push_str(&inner_type_id[..]);
},
ty::ty_vec(inner_type, optional_length) => {
match optional_length {
let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
- unique_type_id.push_str(&inner_type_id[]);
+ unique_type_id.push_str(&inner_type_id[..]);
},
ty::ty_trait(ref trait_data) => {
unique_type_id.push_str("trait ");
self.get_unique_type_id_of_type(cx, parameter_type);
let parameter_type_id =
self.get_unique_type_id_as_string(parameter_type_id);
- unique_type_id.push_str(¶meter_type_id[]);
+ unique_type_id.push_str(¶meter_type_id[..]);
unique_type_id.push(',');
}
ty::FnConverging(ret_ty) => {
let return_type_id = self.get_unique_type_id_of_type(cx, ret_ty);
let return_type_id = self.get_unique_type_id_as_string(return_type_id);
- unique_type_id.push_str(&return_type_id[]);
+ unique_type_id.push_str(&return_type_id[..]);
}
ty::FnDiverging => {
unique_type_id.push_str("!");
type_map.get_unique_type_id_of_type(cx, type_parameter);
let param_type_id =
type_map.get_unique_type_id_as_string(param_type_id);
- output.push_str(¶m_type_id[]);
+ output.push_str(¶m_type_id[..]);
output.push(',');
}
self.get_unique_type_id_of_type(cx, parameter_type);
let parameter_type_id =
self.get_unique_type_id_as_string(parameter_type_id);
- unique_type_id.push_str(¶meter_type_id[]);
+ unique_type_id.push_str(¶meter_type_id[..]);
unique_type_id.push(',');
}
ty::FnConverging(ret_ty) => {
let return_type_id = self.get_unique_type_id_of_type(cx, ret_ty);
let return_type_id = self.get_unique_type_id_as_string(return_type_id);
- unique_type_id.push_str(&return_type_id[]);
+ unique_type_id.push_str(&return_type_id[..]);
}
ty::FnDiverging => {
unique_type_id.push_str("!");
let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id));
let var_name = token::get_ident(ident).to_string();
let linkage_name =
- namespace_node.mangled_name_of_contained_item(&var_name[]);
+ namespace_node.mangled_name_of_contained_item(&var_name[..]);
let var_scope = namespace_node.scope;
- let var_name = CString::from_slice(var_name.as_bytes());
- let linkage_name = CString::from_slice(linkage_name.as_bytes());
+ let var_name = CString::new(var_name).unwrap();
+ let linkage_name = CString::new(linkage_name).unwrap();
unsafe {
llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
var_scope,
match expr.node {
ast::ExprClosure(_, ref fn_decl, ref top_level_block) => {
let name = format!("fn{}", token::gensym("fn"));
- let name = token::str_to_ident(&name[]);
+ let name = token::str_to_ident(&name[..]);
(name, &**fn_decl,
// This is not quite right. It should actually inherit
// the generics of the enclosing function.
let (linkage_name, containing_scope) = if has_path {
let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id));
let linkage_name = namespace_node.mangled_name_of_contained_item(
- &function_name[]);
+ &function_name[..]);
let containing_scope = namespace_node.scope;
(linkage_name, containing_scope)
} else {
let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
- let function_name = CString::from_slice(function_name.as_bytes());
- let linkage_name = CString::from_slice(linkage_name.as_bytes());
+ let function_name = CString::new(function_name).unwrap();
+ let linkage_name = CString::new(linkage_name).unwrap();
let fn_metadata = unsafe {
llvm::LLVMDIBuilderCreateFunction(
DIB(cx),
signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
}
- return create_DIArray(DIB(cx), &signature[]);
+ return create_DIArray(DIB(cx), &signature[..]);
}
fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
actual_self_type,
true);
- name_to_append_suffix_to.push_str(&actual_self_type_name[]);
+ name_to_append_suffix_to.push_str(&actual_self_type_name[..]);
if generics.is_type_parameterized() {
name_to_append_suffix_to.push_str(",");
let ident = special_idents::type_self;
let ident = token::get_ident(ident);
- let name = CString::from_slice(ident.as_bytes());
+ let name = CString::new(ident.as_bytes()).unwrap();
let param_metadata = unsafe {
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
DIB(cx),
let actual_type_name = compute_debuginfo_type_name(cx,
actual_type,
true);
- name_to_append_suffix_to.push_str(&actual_type_name[]);
+ name_to_append_suffix_to.push_str(&actual_type_name[..]);
if index != generics.ty_params.len() - 1 {
name_to_append_suffix_to.push_str(",");
if cx.sess().opts.debuginfo == FullDebugInfo {
let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
let ident = token::get_ident(ident);
- let name = CString::from_slice(ident.as_bytes());
+ let name = CString::new(ident.as_bytes()).unwrap();
let param_metadata = unsafe {
llvm::LLVMDIBuilderCreateTemplateTypeParameter(
DIB(cx),
name_to_append_suffix_to.push('>');
- return create_DIArray(DIB(cx), &template_params[]);
+ return create_DIArray(DIB(cx), &template_params[..]);
}
}
path_bytes.insert(1, prefix[1]);
}
- CString::from_vec(path_bytes)
+ CString::new(path_bytes).unwrap()
}
_ => fallback_path(cx)
}
(option_env!("CFG_VERSION")).expect("CFG_VERSION"));
let compile_unit_name = compile_unit_name.as_ptr();
- let work_dir = CString::from_slice(work_dir.as_vec());
- let producer = CString::from_slice(producer.as_bytes());
+ let work_dir = CString::new(work_dir.as_vec()).unwrap();
+ let producer = CString::new(producer).unwrap();
let flags = "\0";
let split_name = "\0";
return unsafe {
};
fn fallback_path(cx: &CrateContext) -> CString {
- CString::from_slice(cx.link_meta().crate_name.as_bytes())
+ CString::new(cx.link_meta().crate_name.clone()).unwrap()
}
}
let cx: &CrateContext = bcx.ccx();
let filename = span_start(cx, span).file.name.clone();
- let file_metadata = file_metadata(cx, &filename[]);
+ let file_metadata = file_metadata(cx, &filename[..]);
let name = token::get_ident(variable_ident);
let loc = span_start(cx, span);
CapturedVariable => (0, DW_TAG_auto_variable)
};
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name.as_bytes()).unwrap();
match (variable_access, [].as_slice()) {
(DirectVariable { alloca }, address_operations) |
(IndirectVariable {alloca, address_operations}, _) => {
full_path
};
- let file_name = CString::from_slice(file_name.as_bytes());
- let work_dir = CString::from_slice(work_dir.as_bytes());
+ let file_name = CString::new(file_name).unwrap();
+ let work_dir = CString::new(work_dir).unwrap();
let file_metadata = unsafe {
llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
work_dir.as_ptr())
let llvm_type = type_of::type_of(cx, t);
let (size, align) = size_and_align_of(cx, llvm_type);
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name).unwrap();
let ty_metadata = unsafe {
llvm::LLVMDIBuilderCreateBasicType(
DIB(cx),
let pointer_llvm_type = type_of::type_of(cx, pointer_type);
let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
let name = compute_debuginfo_type_name(cx, pointer_type, false);
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name).unwrap();
let ptr_metadata = unsafe {
llvm::LLVMDIBuilderCreatePointerType(
DIB(cx),
set_members_of_composite_type(cx,
metadata_stub,
llvm_type,
- &member_descriptions[]);
+ &member_descriptions[..]);
return MetadataCreationResult::new(metadata_stub, true);
}
}
let struct_metadata_stub = create_struct_stub(cx,
struct_llvm_type,
- &struct_name[],
+ &struct_name[..],
unique_type_id,
containing_scope);
unique_type_id,
create_struct_stub(cx,
tuple_llvm_type,
- &tuple_name[],
+ &tuple_name[..],
unique_type_id,
UNKNOWN_SCOPE_METADATA),
tuple_llvm_type,
set_members_of_composite_type(cx,
variant_type_metadata,
variant_llvm_type,
- &member_descriptions[]);
+ &member_descriptions[..]);
MemberDescription {
name: "".to_string(),
llvm_type: variant_llvm_type,
set_members_of_composite_type(cx,
variant_type_metadata,
variant_llvm_type,
- &member_descriptions[]);
+ &member_descriptions[..]);
vec![
MemberDescription {
name: "".to_string(),
set_members_of_composite_type(cx,
variant_type_metadata,
variant_llvm_type,
- &variant_member_descriptions[]);
+ &variant_member_descriptions[..]);
// Encode the information about the null variant in the union
// member's name.
.iter()
.map(|v| {
let token = token::get_name(v.name);
- let name = CString::from_slice(token.as_bytes());
+ let name = CString::new(token.as_bytes()).unwrap();
unsafe {
llvm::LLVMDIBuilderCreateEnumerator(
DIB(cx),
codemap::DUMMY_SP);
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
- let name = CString::from_slice(discriminant_name.as_bytes());
+ let name = CString::new(discriminant_name.as_bytes()).unwrap();
let discriminant_type_metadata = unsafe {
llvm::LLVMDIBuilderCreateEnumerationType(
DIB(cx),
.borrow()
.get_unique_type_id_as_string(unique_type_id);
- let enum_name = CString::from_slice(enum_name.as_bytes());
- let unique_type_id_str = CString::from_slice(unique_type_id_str.as_bytes());
+ let enum_name = CString::new(enum_name).unwrap();
+ let unique_type_id_str = CString::new(unique_type_id_str.as_bytes()).unwrap();
let enum_metadata = unsafe {
llvm::LLVMDIBuilderCreateUnionType(
DIB(cx),
ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
};
- let member_name = CString::from_slice(member_description.name.as_bytes());
+ let member_name = member_description.name.as_bytes();
+ let member_name = CString::new(member_name).unwrap();
unsafe {
llvm::LLVMDIBuilderCreateMemberType(
DIB(cx),
.collect();
unsafe {
- let type_array = create_DIArray(DIB(cx), &member_metadata[]);
+ let type_array = create_DIArray(DIB(cx), &member_metadata[..]);
llvm::LLVMDICompositeTypeSetTypeArray(DIB(cx), composite_type_metadata, type_array);
}
}
let unique_type_id_str = debug_context(cx).type_map
.borrow()
.get_unique_type_id_as_string(unique_type_id);
- let name = CString::from_slice(struct_type_name.as_bytes());
- let unique_type_id = CString::from_slice(unique_type_id_str.as_bytes());
+ let name = CString::new(struct_type_name).unwrap();
+ let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap();
let metadata_stub = unsafe {
// LLVMDIBuilderCreateStructType() wants an empty array. A null
// pointer will lead to hard to trace and debug LLVM assertions
let member_llvm_types = slice_llvm_type.field_types();
assert!(slice_layout_is_correct(cx,
- &member_llvm_types[],
+ &member_llvm_types[..],
element_type));
let member_descriptions = [
MemberDescription {
let metadata = composite_type_metadata(cx,
slice_llvm_type,
- &slice_type_name[],
+ &slice_type_name[..],
unique_type_id,
&member_descriptions,
UNKNOWN_SCOPE_METADATA,
llvm::LLVMDIBuilderCreateSubroutineType(
DIB(cx),
UNKNOWN_FILE_METADATA,
- create_DIArray(DIB(cx), &signature_metadata[]))
+ create_DIArray(DIB(cx), &signature_metadata[..]))
},
false);
}
let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_type);
cx.sess().bug(&format!("debuginfo: Unexpected trait-object type in \
trait_pointer_metadata(): {}",
- &pp_type_name[])[]);
+ &pp_type_name[..])[]);
}
};
composite_type_metadata(cx,
trait_llvm_type,
- &trait_type_name[],
+ &trait_type_name[..],
unique_type_id,
&[],
containing_scope,
ty::ty_tup(ref elements) => {
prepare_tuple_metadata(cx,
t,
- &elements[],
+ &elements[..],
unique_type_id,
usage_site_span).finalize(cx)
}
type id '{}' to already be in \
the debuginfo::TypeMap but it \
was not. (Ty = {})",
- &unique_type_id_str[],
+ &unique_type_id_str[..],
ppaux::ty_to_string(cx.tcx(), t));
- cx.sess().span_bug(usage_site_span, &error_message[]);
+ cx.sess().span_bug(usage_site_span, &error_message[..]);
}
};
UniqueTypeId maps in \
debuginfo::TypeMap. \
UniqueTypeId={}, Ty={}",
- &unique_type_id_str[],
+ &unique_type_id_str[..],
ppaux::ty_to_string(cx.tcx(), t));
- cx.sess().span_bug(usage_site_span, &error_message[]);
+ cx.sess().span_bug(usage_site_span, &error_message[..]);
}
}
None => {
attributes.iter().any(|attr| {
let meta_item: &ast::MetaItem = &*attr.node.value;
match meta_item.node {
- ast::MetaWord(ref value) => &value[] == "no_debug",
+ ast::MetaWord(ref value) => &value[..] == "no_debug",
_ => false
}
})
None => ptr::null_mut()
};
let namespace_name = token::get_name(name);
- let namespace_name = CString::from_slice(namespace_name
- .as_bytes());
+ let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
let scope = unsafe {
llvm::LLVMDIBuilderCreateNameSpace(
DIB(cx),
/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) {
if needs_gdb_debug_scripts_section(ccx) {
- let empty = CString::from_slice(b"");
+ let empty = CString::new(b"").unwrap();
let gdb_debug_scripts_section_global =
get_or_insert_gdb_debug_scripts_section_global(ccx);
unsafe {
controlflow::trans_if(bcx, expr.id, &**cond, &**thn, els.as_ref().map(|e| &**e), dest)
}
ast::ExprMatch(ref discr, ref arms, _) => {
- _match::trans_match(bcx, expr, &**discr, &arms[], dest)
+ _match::trans_match(bcx, expr, &**discr, &arms[..], dest)
}
ast::ExprBlock(ref blk) => {
controlflow::trans_block(bcx, &**blk, dest)
}
ast::ExprStruct(_, ref fields, ref base) => {
trans_struct(bcx,
- &fields[],
+ &fields[..],
base.as_ref().map(|e| &**e),
expr.span,
expr.id,
trans_adt(bcx,
expr_ty(bcx, expr),
0,
- &numbered_fields[],
+ &numbered_fields[..],
None,
dest,
expr.debug_loc())
trans_overloaded_call(bcx,
expr,
&**f,
- &args[],
+ &args[..],
Some(dest))
} else {
callee::trans_call(bcx,
expr,
&**f,
- callee::ArgExprs(&args[]),
+ callee::ArgExprs(&args[..]),
dest)
}
}
callee::trans_method_call(bcx,
expr,
&*args[0],
- callee::ArgExprs(&args[]),
+ callee::ArgExprs(&args[..]),
dest)
}
ast::ExprBinary(op, ref lhs, ref rhs) => {
let trait_ref =
bcx.tcx().object_cast_map.borrow()
.get(&expr.id)
- .map(|t| (*t).clone())
+ .cloned()
.unwrap();
let trait_ref = bcx.monomorphize(&trait_ref);
let datum = unpack_datum!(bcx, trans(bcx, &**val));
ty::ty_struct(did, substs) => {
let fields = struct_fields(tcx, did, substs);
let fields = monomorphize::normalize_associated_type(tcx, &fields);
- op(0, &fields[])
+ op(0, &fields[..])
}
ty::ty_tup(ref v) => {
- op(0, &tup_fields(&v[])[])
+ op(0, &tup_fields(&v[..])[])
}
ty::ty_enum(_, substs) => {
tcx, enum_id, variant_id);
let fields = struct_fields(tcx, variant_id, substs);
let fields = monomorphize::normalize_associated_type(tcx, &fields);
- op(variant_info.disr_val, &fields[])
+ op(variant_info.disr_val, &fields[..])
}
_ => {
tcx.sess.bug("resolve didn't map this expr to a \
};
unsafe {
// Declare a symbol `foo` with the desired linkage.
- let buf = CString::from_slice(ident.as_bytes());
+ let buf = CString::new(ident.as_bytes()).unwrap();
let g1 = llvm::LLVMAddGlobal(ccx.llmod(), llty2.to_ref(),
buf.as_ptr());
llvm::SetLinkage(g1, linkage);
// zero.
let mut real_name = "_rust_extern_with_linkage_".to_string();
real_name.push_str(&ident);
- let real_name = CString::from_vec(real_name.into_bytes());
+ let real_name = CString::new(real_name).unwrap();
let g2 = llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(),
real_name.as_ptr());
llvm::SetLinkage(g2, llvm::InternalLinkage);
}
None => unsafe {
// Generate an external declaration.
- let buf = CString::from_slice(ident.as_bytes());
+ let buf = CString::new(ident.as_bytes()).unwrap();
llvm::LLVMAddGlobal(ccx.llmod(), llty.to_ref(), buf.as_ptr())
}
}
_ => ccx.sess().bug("trans_native_call called on non-function type")
};
let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig);
- let llsig = foreign_signature(ccx, &fn_sig, &passed_arg_tys[]);
+ let llsig = foreign_signature(ccx, &fn_sig, &passed_arg_tys[..]);
let fn_type = cabi::compute_abi_info(ccx,
&llsig.llarg_tys[],
llsig.llret_ty,
let llforeign_retval = CallWithConv(bcx,
llfn,
- &llargs_foreign[],
+ &llargs_foreign[..],
cc,
Some(attrs),
call_debug_loc);
ccx.tcx().map.path_to_string(id),
id, t.repr(tcx));
- let llfn = base::decl_internal_rust_fn(ccx, t, &ps[]);
+ let llfn = base::decl_internal_rust_fn(ccx, t, &ps[..]);
base::set_llvm_fn_attrs(ccx, attrs, llfn);
base::trans_fn(ccx, decl, body, llfn, param_substs, id, &[]);
llfn
if tys.fn_sig.variadic {
Type::variadic_func(&llargument_tys, &llreturn_ty)
} else {
- Type::func(&llargument_tys[], &llreturn_ty)
+ Type::func(&llargument_tys[..], &llreturn_ty)
}
}
let (glue, new_sym) = match ccx.available_drop_glues().borrow().get(&t) {
Some(old_sym) => {
- let glue = decl_cdecl_fn(ccx, &old_sym[], llfnty, ty::mk_nil(ccx.tcx()));
+ let glue = decl_cdecl_fn(ccx, &old_sym[..], llfnty, ty::mk_nil(ccx.tcx()));
(glue, None)
},
None => {
class_did,
&[get_drop_glue_type(bcx.ccx(), t)],
ty::mk_nil(bcx.tcx()));
- let (_, variant_cx) = invoke(variant_cx, dtor_addr, &args[], dtor_ty, DebugLoc::None);
+ let (_, variant_cx) = invoke(variant_cx, dtor_addr, &args[..], dtor_ty, DebugLoc::None);
variant_cx.fcx.pop_and_trans_custom_cleanup_scope(variant_cx, field_scope);
variant_cx
let llalign = llalign_of(ccx, llty);
let name = mangle_internal_name_by_type_and_seq(ccx, t, "tydesc");
debug!("+++ declare_tydesc {} {}", ppaux::ty_to_string(ccx.tcx(), t), name);
- let buf = CString::from_slice(name.as_bytes());
+ let buf = CString::new(name.clone()).unwrap();
let gvar = unsafe {
llvm::LLVMAddGlobal(ccx.llmod(), ccx.tydesc_type().to_ref(),
buf.as_ptr())
ccx,
t,
&format!("glue_{}", name)[]);
- let llfn = decl_cdecl_fn(ccx, &fn_nm[], llfnty, ty::mk_nil(ccx.tcx()));
+ let llfn = decl_cdecl_fn(ccx, &fn_nm[..], llfnty, ty::mk_nil(ccx.tcx()));
note_unique_llvm_symbol(ccx, fn_nm.clone());
return (fn_nm, llfn);
}
let name = token::get_ident(foreign_item.ident);
// For `transmute` we can just trans the input expr directly into dest
- if &name[] == "transmute" {
+ if &name[..] == "transmute" {
let llret_ty = type_of::type_of(ccx, ret_ty.unwrap());
match args {
callee::ArgExprs(arg_exprs) => {
let call_debug_location = DebugLoc::At(call_info.id, call_info.span);
// These are the only intrinsic functions that diverge.
- if &name[] == "abort" {
+ if &name[..] == "abort" {
let llfn = ccx.get_intrinsic(&("llvm.trap"));
Call(bcx, llfn, &[], None, call_debug_location);
fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope);
Unreachable(bcx);
return Result::new(bcx, C_undef(Type::nil(ccx).ptr_to()));
- } else if &name[] == "unreachable" {
+ } else if &name[..] == "unreachable" {
fcx.pop_and_trans_custom_cleanup_scope(bcx, cleanup_scope);
Unreachable(bcx);
return Result::new(bcx, C_nil(ccx));
};
let simple = get_simple_intrinsic(ccx, &*foreign_item);
- let llval = match (simple, &name[]) {
+ let llval = match (simple, &name[..]) {
(Some(llfn), _) => {
Call(bcx, llfn, &llargs, None, call_debug_location)
}
hash = format!("h{}", state.finish());
ccx.tcx().map.with_path(fn_id.node, |path| {
- exported_name(path, &hash[])
+ exported_name(path, &hash[..])
})
};
let mut hash_id = Some(hash_id);
let mut mk_lldecl = |abi: abi::Abi| {
let lldecl = if abi != abi::Rust {
- foreign::decl_rust_fn_with_foreign_abi(ccx, mono_ty, &s[])
+ foreign::decl_rust_fn_with_foreign_abi(ccx, mono_ty, &s[..])
} else {
- decl_internal_rust_fn(ccx, mono_ty, &s[])
+ decl_internal_rust_fn(ccx, mono_ty, &s[..])
};
ccx.monomorphized().borrow_mut().insert(hash_id.take().unwrap(), lldecl);
if abi != abi::Rust {
foreign::trans_rust_fn_with_foreign_abi(
ccx, &**decl, &**body, &[], d, psubsts, fn_id.node,
- Some(&hash[]));
+ Some(&hash[..]));
} else {
trans_fn(ccx, &**decl, &**body, d, psubsts, fn_id.node, &[]);
}
trans_enum_variant(ccx,
parent,
&*v,
- &args[],
+ &args[..],
this_tv.disr_val,
psubsts,
d);
let vt = vec_types_from_expr(bcx, content_expr);
let count = elements_required(bcx, content_expr);
debug!(" vt={}, count={}", vt.to_string(ccx), count);
- let llcount = C_uint(ccx, count);
let fixed_ty = ty::mk_vec(bcx.tcx(),
vt.unit_ty,
Some(count));
- let llfixed_ty = type_of::type_of(bcx.ccx(), fixed_ty).ptr_to();
+ let llfixed_ty = type_of::type_of(bcx.ccx(), fixed_ty);
- let llfixed = if count == 0 {
- // Just create a zero-sized alloca to preserve
- // the non-null invariant of the inner slice ptr
- let llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
- BitCast(bcx, llfixed, llfixed_ty)
- } else {
- // Make a fixed-length backing array and allocate it on the stack.
- let llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount);
+ // Always create an alloca even if zero-sized, to preserve
+ // the non-null invariant of the inner slice ptr
+ let llfixed = base::alloca(bcx, llfixed_ty, "");
+ if count > 0 {
// Arrange for the backing array to be cleaned up.
- let llfixed_casted = BitCast(bcx, llfixed, llfixed_ty);
let cleanup_scope = cleanup::temporary_scope(bcx.tcx(), content_expr.id);
- fcx.schedule_lifetime_end(cleanup_scope, llfixed_casted);
- fcx.schedule_drop_mem(cleanup_scope, llfixed_casted, fixed_ty);
+ fcx.schedule_lifetime_end(cleanup_scope, llfixed);
+ fcx.schedule_drop_mem(cleanup_scope, llfixed, fixed_ty);
// Generate the content into the backing array.
- bcx = write_content(bcx, &vt, slice_expr,
- content_expr, SaveIn(llfixed));
-
- llfixed_casted
+ // llfixed has type *[T x N], but we want the type *T,
+ // so use GEP to convert
+ bcx = write_content(bcx, &vt, slice_expr, content_expr,
+ SaveIn(GEPi(bcx, llfixed, &[0, 0])));
};
immediate_rvalue_bcx(bcx, llfixed, vec_ty).to_expr_datumblock()
let _icx = push_ctxt("tvec::iter_vec_loop");
let fcx = bcx.fcx;
- let next_bcx = fcx.new_temp_block("expr_repeat: while next");
let loop_bcx = fcx.new_temp_block("expr_repeat");
- let cond_bcx = fcx.new_temp_block("expr_repeat: loop cond");
- let body_bcx = fcx.new_temp_block("expr_repeat: body: set");
- let inc_bcx = fcx.new_temp_block("expr_repeat: body: inc");
- Br(bcx, loop_bcx.llbb, DebugLoc::None);
-
- let loop_counter = {
- // i = 0
- let i = alloca(loop_bcx, bcx.ccx().int_type(), "__i");
- Store(loop_bcx, C_uint(bcx.ccx(), 0_u32), i);
+ let next_bcx = fcx.new_temp_block("expr_repeat: next");
- Br(loop_bcx, cond_bcx.llbb, DebugLoc::None);
- i
- };
-
- { // i < count
- let lhs = Load(cond_bcx, loop_counter);
- let rhs = count;
- let cond_val = ICmp(cond_bcx, llvm::IntULT, lhs, rhs, DebugLoc::None);
-
- CondBr(cond_bcx, cond_val, body_bcx.llbb, next_bcx.llbb, DebugLoc::None);
- }
+ Br(bcx, loop_bcx.llbb, DebugLoc::None);
- { // loop body
- let i = Load(body_bcx, loop_counter);
- let lleltptr = if vt.llunit_alloc_size == 0 {
- data_ptr
- } else {
- InBoundsGEP(body_bcx, data_ptr, &[i])
- };
- let body_bcx = f(body_bcx, lleltptr, vt.unit_ty);
+ let loop_counter = Phi(loop_bcx, bcx.ccx().int_type(),
+ &[C_uint(bcx.ccx(), 0 as usize)], &[bcx.llbb]);
- Br(body_bcx, inc_bcx.llbb, DebugLoc::None);
- }
+ let bcx = loop_bcx;
- { // i += 1
- let i = Load(inc_bcx, loop_counter);
- let plusone = Add(inc_bcx, i, C_uint(bcx.ccx(), 1_u32), DebugLoc::None);
- Store(inc_bcx, plusone, loop_counter);
+ let lleltptr = if vt.llunit_alloc_size == 0 {
+ data_ptr
+ } else {
+ InBoundsGEP(bcx, data_ptr, &[loop_counter])
+ };
+ let bcx = f(bcx, lleltptr, vt.unit_ty);
+ let plusone = Add(bcx, loop_counter, C_uint(bcx.ccx(), 1us), DebugLoc::None);
+ AddIncomingToPhi(loop_counter, plusone, bcx.llbb);
- Br(inc_bcx, cond_bcx.llbb, DebugLoc::None);
- }
+ let cond_val = ICmp(bcx, llvm::IntULT, plusone, count, DebugLoc::None);
+ CondBr(bcx, cond_val, loop_bcx.llbb, next_bcx.llbb, DebugLoc::None);
next_bcx
}
}
pub fn named_struct(ccx: &CrateContext, name: &str) -> Type {
- let name = CString::from_slice(name.as_bytes());
+ let name = CString::new(name).unwrap();
ty!(llvm::LLVMStructCreateNamed(ccx.llcx(), name.as_ptr()))
}
abi: abi::Abi)
-> Vec<Ty<'tcx>> {
if abi != abi::RustCall {
- return inputs.iter().map(|x| (*x).clone()).collect()
+ return inputs.iter().cloned().collect()
}
if inputs.len() == 0 {
let input_tys = inputs.iter().map(|&arg_ty| type_of_explicit_arg(cx, arg_ty));
atys.extend(input_tys);
- Type::func(&atys[], &lloutputtype)
+ Type::func(&atys[..], &lloutputtype)
}
// Given a function type and a count of ty params, construct an llvm type
let repr = adt::represent_type(cx, t);
let tps = substs.types.get_slice(subst::TypeSpace);
let name = llvm_type_name(cx, an_enum, did, tps);
- adt::incomplete_type_of(cx, &*repr, &name[])
+ adt::incomplete_type_of(cx, &*repr, &name[..])
}
ty::ty_closure(did, _, ref substs) => {
// Only create the named struct, but don't fill it in. We
// contents of the VecPerParamSpace to to construct the llvm
// name
let name = llvm_type_name(cx, a_closure, did, substs.types.as_slice());
- adt::incomplete_type_of(cx, &*repr, &name[])
+ adt::incomplete_type_of(cx, &*repr, &name[..])
}
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
let repr = adt::represent_type(cx, t);
let tps = substs.types.get_slice(subst::TypeSpace);
let name = llvm_type_name(cx, a_struct, did, tps);
- adt::incomplete_type_of(cx, &*repr, &name[])
+ adt::incomplete_type_of(cx, &*repr, &name[..])
}
}
let actual_supplied_ty_param_count = substs.types.len(TypeSpace);
for param in &ty_param_defs[actual_supplied_ty_param_count..] {
- match param.default {
- Some(default) => {
+ if let Some(default) = param.default {
+ // If we are converting an object type, then the
+ // `Self` parameter is unknown. However, some of the
+ // other type parameters may reference `Self` in their
+ // defaults. This will lead to an ICE if we are not
+ // careful!
+ if self_ty.is_none() && ty::type_has_self(default) {
+ tcx.sess.span_err(
+ span,
+ &format!("the type parameter `{}` must be explicitly specified \
+ in an object type because its default value `{}` references \
+ the type `Self`",
+ param.name.user_string(tcx),
+ default.user_string(tcx)));
+ substs.types.push(TypeSpace, tcx.types.err);
+ } else {
// This is a default type parameter.
let default = default.subst_spanned(tcx,
&substs,
Some(span));
substs.types.push(TypeSpace, default);
}
- None => {
- tcx.sess.span_bug(span, "extra parameter without default");
- }
+ } else {
+ tcx.sess.span_bug(span, "extra parameter without default");
}
}
ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
}
ast::TyObjectSum(ref ty, ref bounds) => {
- match ast_ty_to_trait_ref(this, rscope, &**ty, &bounds[]) {
+ match ast_ty_to_trait_ref(this, rscope, &**ty, &bounds[..]) {
Ok((trait_ref, projection_bounds)) => {
trait_ref_to_object_type(this,
rscope,
ast_ty.span,
trait_ref,
projection_bounds,
- &bounds[])
+ &bounds[..])
}
Err(ErrorReported) => {
this.tcx().types.err
ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn))
}
ast::TyPolyTraitRef(ref bounds) => {
- conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[])
+ conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[..])
}
ast::TyPath(ref path, id) => {
let a_def = match tcx.def_map.borrow().get(&id) {
// Skip the first argument if `self` is present.
&self_and_input_tys[1..]
} else {
- &self_and_input_tys[]
+ &self_and_input_tys[..]
};
let (ior, lfp) = find_implied_output_region(input_tys, input_pats);
ast_bounds: &[ast::TyParamBound])
-> Ty<'tcx>
{
- let mut partitioned_bounds = partition_bounds(this.tcx(), span, &ast_bounds[]);
+ let mut partitioned_bounds = partition_bounds(this.tcx(), span, &ast_bounds[..]);
let mut projection_bounds = Vec::new();
let main_trait_bound = if !partitioned_bounds.trait_bounds.is_empty() {
check_pat_enum(pcx, pat, &path, Some(&[]), expected);
}
ast::PatEnum(ref path, ref subpats) => {
- let subpats = subpats.as_ref().map(|v| &v[]);
+ let subpats = subpats.as_ref().map(|v| &v[..]);
check_pat_enum(pcx, pat, path, subpats, expected);
}
ast::PatStruct(ref path, ref fields, etc) => {
check_argument_types(fcx,
call_expr.span,
&fn_sig.inputs,
- &expected_arg_tys[],
+ &expected_arg_tys[..],
arg_exprs,
AutorefArgs::No,
fn_sig.variadic,
fn accumulate_from_assoc_types_transitive(&mut self,
data: &ty::PolyTraitPredicate<'tcx>)
{
+ debug!("accumulate_from_assoc_types_transitive({})",
+ data.repr(self.tcx()));
+
for poly_trait_ref in traits::supertraits(self.tcx(), data.to_poly_trait_ref()) {
match ty::no_late_bound_regions(self.tcx(), &poly_trait_ref) {
Some(trait_ref) => { self.accumulate_from_assoc_types(trait_ref); }
fn accumulate_from_assoc_types(&mut self,
trait_ref: Rc<ty::TraitRef<'tcx>>)
{
+ debug!("accumulate_from_assoc_types({})",
+ trait_ref.repr(self.tcx()));
+
let trait_def_id = trait_ref.def_id;
let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
let assoc_type_projections: Vec<_> =
.iter()
.map(|&name| ty::mk_projection(self.tcx(), trait_ref.clone(), name))
.collect();
+ debug!("accumulate_from_assoc_types: assoc_type_projections={}",
+ assoc_type_projections.repr(self.tcx()));
let tys = match self.fully_normalize(&assoc_type_projections) {
Ok(tys) => { tys }
Err(ErrorReported) => { return; }
debug!("applicable_candidates: {}", applicable_candidates.repr(self.tcx()));
if applicable_candidates.len() > 1 {
- match self.collapse_candidates_to_trait_pick(&applicable_candidates[]) {
+ match self.collapse_candidates_to_trait_pick(&applicable_candidates[..]) {
Some(pick) => { return Some(Ok(pick)); }
None => { }
}
traits_are = if candidates.len() == 1 {"trait is"} else {"traits are"},
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"});
- fcx.sess().fileline_help(span, &msg[]);
+ fcx.sess().fileline_help(span, &msg[..]);
for (i, trait_did) in candidates.iter().enumerate() {
fcx.sess().fileline_help(span,
one_of_them = if candidates.len() == 1 {"it"} else {"one of them"},
name = method_ustring);
- fcx.sess().fileline_help(span, &msg[]);
+ fcx.sess().fileline_help(span, &msg[..]);
for (i, trait_info) in candidates.iter().enumerate() {
fcx.sess().fileline_help(span,
// Crate-local:
//
// meh.
- struct Visitor<'a, 'b: 'a, 'tcx: 'a + 'b> {
+ struct Visitor<'a> {
traits: &'a mut AllTraitsVec,
}
- impl<'v,'a, 'b, 'tcx> visit::Visitor<'v> for Visitor<'a, 'b, 'tcx> {
+ impl<'v, 'a> visit::Visitor<'v> for Visitor<'a> {
fn visit_item(&mut self, i: &'v ast::Item) {
match i.node {
ast::ItemTrait(..) => {
// Remember return type so that regionck can access it later.
let mut fn_sig_tys: Vec<Ty> =
arg_tys.iter()
- .map(|&ty| ty)
+ .cloned()
.collect();
if let ty::FnConverging(ret_ty) = ret_ty {
check_argument_types(fcx,
sp,
- &err_inputs[],
+ &err_inputs[..],
&[],
args_no_rcvr,
autoref_args,
check_argument_types(fcx,
sp,
&fty.sig.0.inputs[1..],
- &expected_arg_tys[],
+ &expected_arg_tys[..],
args_no_rcvr,
autoref_args,
fty.sig.0.variadic,
ty::ty_struct(base_id, substs) => {
debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
let fields = ty::lookup_struct_fields(tcx, base_id);
- fcx.lookup_field_ty(expr.span, base_id, &fields[],
+ fcx.lookup_field_ty(expr.span, base_id, &fields[..],
field.node.name, &(*substs))
}
_ => None
if tuple_like {
debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
let fields = ty::lookup_struct_fields(tcx, base_id);
- fcx.lookup_tup_field_ty(expr.span, base_id, &fields[],
+ fcx.lookup_tup_field_ty(expr.span, base_id, &fields[..],
idx.node, &(*substs))
} else {
None
for field in ast_fields {
let mut expected_field_type = tcx.types.err;
- let pair = class_field_map.get(&field.ident.node.name).map(|x| *x);
+ let pair = class_field_map.get(&field.ident.node.name).cloned();
match pair {
None => {
fcx.type_error_message(
class_id,
id,
fcx.ccx.tcx.mk_substs(struct_substs),
- &class_fields[],
+ &class_fields[..],
fields,
base_expr.is_none(),
None);
variant_id,
id,
fcx.ccx.tcx.mk_substs(substitutions),
- &variant_fields[],
+ &variant_fields[..],
fields,
true,
Some(enum_id));
fcx.write_ty(id, fcx.node_ty(b.id));
}
ast::ExprCall(ref callee, ref args) => {
- callee::check_call(fcx, expr, &**callee, &args[], expected);
+ callee::check_call(fcx, expr, &**callee, &args[..], expected);
}
ast::ExprMethodCall(ident, ref tps, ref args) => {
- check_method_call(fcx, expr, ident, &args[], &tps[], expected, lvalue_pref);
+ check_method_call(fcx, expr, ident, &args[..], &tps[..], expected, lvalue_pref);
let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
let args_err = arg_tys.fold(false,
|rest_err, a| {
ast::ExprTup(ref elts) => {
let flds = expected.only_has_type(fcx).and_then(|ty| {
match ty.sty {
- ty::ty_tup(ref flds) => Some(&flds[]),
+ ty::ty_tup(ref flds) => Some(&flds[..]),
_ => None
}
});
}
ast::ExprStruct(ref path, ref fields, ref base_expr) => {
// Resolve the path.
- let def = tcx.def_map.borrow().get(&id).map(|i| *i);
+ let def = tcx.def_map.borrow().get(&id).cloned();
let struct_id = match def {
Some(def::DefVariant(enum_id, variant_id, true)) => {
check_struct_enum_variant(fcx, id, expr.span, enum_id,
- variant_id, &fields[]);
+ variant_id, &fields[..]);
enum_id
}
Some(def::DefTrait(def_id)) => {
pprust::path_to_string(path));
check_struct_fields_on_error(fcx,
id,
- &fields[],
+ &fields[..],
base_expr);
def_id
},
id,
expr.span,
struct_did,
- &fields[],
+ &fields[..],
base_expr.as_ref().map(|e| &**e));
}
_ => {
pprust::path_to_string(path));
check_struct_fields_on_error(fcx,
id,
- &fields[],
+ &fields[..],
base_expr);
}
}
}
};
(n_tps, inputs, ty::FnConverging(output))
- } else if &name[] == "abort" || &name[] == "unreachable" {
+ } else if &name[..] == "abort" || &name[..] == "unreachable" {
(0, Vec::new(), ty::FnDiverging)
} else {
- let (n_tps, inputs, output) = match &name[] {
+ let (n_tps, inputs, output) = match &name[..] {
"breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
"size_of" |
"pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.uint),
"get_tydesc" => {
let tydesc_ty = match ty::get_tydesc_ty(ccx.tcx) {
Ok(t) => t,
- Err(s) => { span_fatal!(tcx.sess, it.span, E0240, "{}", &s[]); }
+ Err(s) => { span_fatal!(tcx.sess, it.span, E0240, "{}", &s[..]); }
};
let td_ptr = ty::mk_ptr(ccx.tcx, ty::mt {
ty: tydesc_ty,
let len = self.region_bound_pairs.len();
let old_body_id = self.set_body_id(body.id);
- self.relate_free_regions(&fn_sig[], body.id, span);
- link_fn_args(self, CodeExtent::from_node_id(body.id), &fn_decl.inputs[]);
+ self.relate_free_regions(&fn_sig[..], body.id, span);
+ link_fn_args(self, CodeExtent::from_node_id(body.id), &fn_decl.inputs[..]);
self.visit_block(body);
self.visit_region_obligations(body.id);
self.region_bound_pairs.truncate(len);
visit::walk_expr(rcx, expr);
}
+ ast::ExprBinary(_, ref lhs, ref rhs) => {
+ // If you do `x OP y`, then the types of `x` and `y` must
+ // outlive the operation you are performing.
+ let lhs_ty = rcx.resolve_expr_type_adjusted(&**lhs);
+ let rhs_ty = rcx.resolve_expr_type_adjusted(&**rhs);
+ for &ty in [lhs_ty, rhs_ty].iter() {
+ type_must_outlive(rcx,
+ infer::Operand(expr.span),
+ ty,
+ ty::ReScope(CodeExtent::from_node_id(expr.id)));
+ }
+ visit::walk_expr(rcx, expr);
+ }
+
ast::ExprUnary(op, ref lhs) if has_method_map => {
let implicitly_ref_args = !ast_util::is_by_value_unop(op);
}
ast::ExprMatch(ref discr, ref arms, _) => {
- link_match(rcx, &**discr, &arms[]);
+ link_match(rcx, &**discr, &arms[..]);
visit::walk_expr(rcx, expr);
}
"the trait cannot require that `Self : Sized`");
}
+ ObjectSafetyViolation::SupertraitSelf => {
+ tcx.sess.span_note(
+ span,
+ "the trait cannot use `Self` as a type parameter \
+ in the supertrait listing");
+ }
+
ObjectSafetyViolation::Method(method, MethodViolationCode::ByValueSelf) => {
tcx.sess.span_note(
span,
use astconv::AstConv;
use check::{FnCtxt, Inherited, blank_fn_ctxt, vtable, regionck};
+use constrained_type_params::identify_constrained_type_params;
use CrateCtxt;
use middle::region;
-use middle::subst;
+use middle::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
use middle::traits;
use middle::ty::{self, Ty};
use middle::ty::liberate_late_bound_regions;
use middle::ty_fold::{TypeFolder, TypeFoldable, super_fold_ty};
-use util::ppaux::Repr;
+use util::ppaux::{Repr, UserString};
use std::collections::HashSet;
use syntax::ast;
use syntax::ast_util::{local_def};
use syntax::attr;
use syntax::codemap::Span;
-use syntax::parse::token;
+use syntax::parse::token::{self, special_idents};
use syntax::visit;
use syntax::visit::Visitor;
CheckTypeWellFormedVisitor { ccx: ccx, cache: HashSet::new() }
}
+ fn tcx(&self) -> &ty::ctxt<'tcx> {
+ self.ccx.tcx
+ }
+
/// Checks that the field types (in a struct def'n) or argument types (in an enum def'n) are
/// well-formed, meaning that they do not require any constraints not declared in the struct
/// definition itself. For example, this definition would be illegal:
ast::ItemConst(..) => {
self.check_item_type(item);
}
- ast::ItemStruct(ref struct_def, _) => {
- self.check_type_defn(item, |fcx| vec![struct_variant(fcx, &**struct_def)]);
+ ast::ItemStruct(ref struct_def, ref ast_generics) => {
+ self.check_type_defn(item, |fcx| {
+ vec![struct_variant(fcx, &**struct_def)]
+ });
+
+ self.check_variances_for_type_defn(item, ast_generics);
}
- ast::ItemEnum(ref enum_def, _) => {
- self.check_type_defn(item, |fcx| enum_variants(fcx, enum_def));
+ ast::ItemEnum(ref enum_def, ref ast_generics) => {
+ self.check_type_defn(item, |fcx| {
+ enum_variants(fcx, enum_def)
+ });
+
+ self.check_variances_for_type_defn(item, ast_generics);
}
- ast::ItemTrait(..) => {
+ ast::ItemTrait(_, ref ast_generics, _, _) => {
let trait_predicates =
ty::lookup_predicates(ccx.tcx, local_def(item.id));
reject_non_type_param_bounds(
ccx.tcx,
item.span,
&trait_predicates);
+ self.check_variances(item, ast_generics, &trait_predicates,
+ self.tcx().lang_items.phantom_fn());
}
_ => {}
}
}
});
}
+
+ fn check_variances_for_type_defn(&self,
+ item: &ast::Item,
+ ast_generics: &ast::Generics)
+ {
+ let item_def_id = local_def(item.id);
+ let predicates = ty::lookup_predicates(self.tcx(), item_def_id);
+ self.check_variances(item,
+ ast_generics,
+ &predicates,
+ self.tcx().lang_items.phantom_data());
+ }
+
+ fn check_variances(&self,
+ item: &ast::Item,
+ ast_generics: &ast::Generics,
+ ty_predicates: &ty::GenericPredicates<'tcx>,
+ suggested_marker_id: Option<ast::DefId>)
+ {
+ let variance_lang_items = &[
+ self.tcx().lang_items.phantom_fn(),
+ self.tcx().lang_items.phantom_data(),
+ ];
+
+ let item_def_id = local_def(item.id);
+ let is_lang_item = variance_lang_items.iter().any(|n| *n == Some(item_def_id));
+ if is_lang_item {
+ return;
+ }
+
+ let variances = ty::item_variances(self.tcx(), item_def_id);
+
+ let mut constrained_parameters: HashSet<_> =
+ variances.types
+ .iter_enumerated()
+ .filter(|&(_, _, &variance)| variance != ty::Bivariant)
+ .map(|(space, index, _)| self.param_ty(ast_generics, space, index))
+ .collect();
+
+ identify_constrained_type_params(self.tcx(),
+ ty_predicates.predicates.as_slice(),
+ None,
+ &mut constrained_parameters);
+
+ for (space, index, _) in variances.types.iter_enumerated() {
+ let param_ty = self.param_ty(ast_generics, space, index);
+ if constrained_parameters.contains(¶m_ty) {
+ continue;
+ }
+ let span = self.ty_param_span(ast_generics, item, space, index);
+ self.report_bivariance(span, param_ty.name, suggested_marker_id);
+ }
+
+ for (space, index, &variance) in variances.regions.iter_enumerated() {
+ if variance != ty::Bivariant {
+ continue;
+ }
+
+ assert_eq!(space, TypeSpace);
+ let span = ast_generics.lifetimes[index].lifetime.span;
+ let name = ast_generics.lifetimes[index].lifetime.name;
+ self.report_bivariance(span, name, suggested_marker_id);
+ }
+ }
+
+ fn param_ty(&self,
+ ast_generics: &ast::Generics,
+ space: ParamSpace,
+ index: usize)
+ -> ty::ParamTy
+ {
+ let name = match space {
+ TypeSpace => ast_generics.ty_params[index].ident.name,
+ SelfSpace => special_idents::type_self.name,
+ FnSpace => self.tcx().sess.bug("Fn space occupied?"),
+ };
+
+ ty::ParamTy { space: space, idx: index as u32, name: name }
+ }
+
+ fn ty_param_span(&self,
+ ast_generics: &ast::Generics,
+ item: &ast::Item,
+ space: ParamSpace,
+ index: usize)
+ -> Span
+ {
+ match space {
+ TypeSpace => ast_generics.ty_params[index].span,
+ SelfSpace => item.span,
+ FnSpace => self.tcx().sess.span_bug(item.span, "Fn space occupied?"),
+ }
+ }
+
+ fn report_bivariance(&self,
+ span: Span,
+ param_name: ast::Name,
+ suggested_marker_id: Option<ast::DefId>)
+ {
+ self.tcx().sess.span_err(
+ span,
+ &format!("parameter `{}` is never used",
+ param_name.user_string(self.tcx()))[]);
+
+ match suggested_marker_id {
+ Some(def_id) => {
+ self.tcx().sess.span_help(
+ span,
+ format!("consider removing `{}` or using a marker such as `{}`",
+ param_name.user_string(self.tcx()),
+ ty::item_path_str(self.tcx(), def_id)).as_slice());
+ }
+ None => {
+ // no lang items, no help!
+ }
+ }
+ }
}
// Reject any predicates that do not involve a type parameter.
match fk {
visit::FkFnBlock | visit::FkItemFn(..) => {}
visit::FkMethod(..) => {
- match ty::impl_or_trait_item(self.ccx.tcx, local_def(id)) {
+ match ty::impl_or_trait_item(self.tcx(), local_def(id)) {
ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
- reject_shadowing_type_parameters(self.ccx.tcx, span, &ty_method.generics)
+ reject_shadowing_type_parameters(self.tcx(), span, &ty_method.generics)
}
_ => {}
}
&ast::TraitItem::ProvidedMethod(_) |
&ast::TraitItem::TypeTraitItem(_) => {},
&ast::TraitItem::RequiredMethod(ref method) => {
- match ty::impl_or_trait_item(self.ccx.tcx, local_def(method.id)) {
+ match ty::impl_or_trait_item(self.tcx(), local_def(method.id)) {
ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
reject_non_type_param_bounds(
- self.ccx.tcx,
+ self.tcx(),
method.span,
&ty_method.predicates);
reject_shadowing_type_parameters(
- self.ccx.tcx,
+ self.tcx(),
method.span,
&ty_method.generics);
}
use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region};
use middle::def;
+use constrained_type_params::identify_constrained_type_params;
use middle::lang_items::SizedTraitLangItem;
use middle::region;
use middle::resolve_lifetime;
ast::TupleVariantKind(ref args) if args.len() > 0 => {
let rs = ExplicitRscope;
let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect();
- ty::mk_ctor_fn(tcx, variant_def_id, &input_tys[], enum_scheme.ty)
+ ty::mk_ctor_fn(tcx, variant_def_id, &input_tys[..], enum_scheme.ty)
}
ast::TupleVariantKind(_) => {
trait_id,
&trait_def.generics,
&trait_predicates,
- &trait_items[],
+ &trait_items[..],
&m.id,
&m.ident.name,
&m.explicit_self,
trait_id,
&trait_def.generics,
&trait_predicates,
- &trait_items[],
+ &trait_items[..],
&m.id,
&m.pe_ident().name,
m.pe_explicit_self(),
local_def(field.node.id)].ty).collect();
let ctor_fn_ty = ty::mk_ctor_fn(tcx,
local_def(ctor_id),
- &inputs[],
+ &inputs[..],
selfty);
write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
tcx.tcache.borrow_mut().insert(local_def(ctor_id),
let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
ty_generics(ccx,
subst::FnSpace,
- &early_lifetimes[],
+ &early_lifetimes[..],
&generics.ty_params[],
&generics.where_clause,
base_generics)
let mut input_parameters: HashSet<_> =
impl_trait_ref.iter()
.flat_map(|t| t.input_types().iter()) // Types in trait ref, if any
- .chain(Some(impl_scheme.ty).iter()) // Self type, always
+ .chain(Some(impl_scheme.ty).iter()) // Self type, always
.flat_map(|t| t.walk())
- .filter_map(to_opt_param_ty)
+ .filter_map(|t| t.as_opt_param_ty())
.collect();
- loop {
- let num_inputs = input_parameters.len();
-
- let projection_predicates =
- impl_predicates.predicates
- .iter()
- .filter_map(|predicate| {
- match *predicate {
- // Ignore higher-ranked binders. For the purposes
- // of this check, they don't matter because they
- // only affect named regions, and we're just
- // concerned about type parameters here.
- ty::Predicate::Projection(ref data) => Some(data.0.clone()),
- _ => None,
- }
- });
-
- for projection in projection_predicates {
- // Special case: watch out for some kind of sneaky attempt
- // to project out an associated type defined by this very trait.
- if Some(projection.projection_ty.trait_ref.clone()) == impl_trait_ref {
- continue;
- }
-
- let relies_only_on_inputs =
- projection.projection_ty.trait_ref.input_types().iter()
- .flat_map(|t| t.walk())
- .filter_map(to_opt_param_ty)
- .all(|t| input_parameters.contains(&t));
-
- if relies_only_on_inputs {
- input_parameters.extend(
- projection.ty.walk().filter_map(to_opt_param_ty));
- }
- }
-
- if input_parameters.len() == num_inputs {
- break;
- }
- }
+ identify_constrained_type_params(tcx,
+ impl_predicates.predicates.as_slice(),
+ impl_trait_ref,
+ &mut input_parameters);
for (index, ty_param) in ast_generics.ty_params.iter().enumerate() {
let param_ty = ty::ParamTy { space: TypeSpace,
}
}
}
-
- fn to_opt_param_ty<'tcx>(ty: Ty<'tcx>) -> Option<ty::ParamTy> {
- match ty.sty {
- ty::ty_param(ref d) => Some(d.clone()),
- _ => None,
- }
- }
}
--- /dev/null
+// Copyright 2015 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.
+
+use middle::ty::{self};
+
+use std::collections::HashSet;
+use std::rc::Rc;
+
+pub fn identify_constrained_type_params<'tcx>(_tcx: &ty::ctxt<'tcx>,
+ predicates: &[ty::Predicate<'tcx>],
+ impl_trait_ref: Option<Rc<ty::TraitRef<'tcx>>>,
+ input_parameters: &mut HashSet<ty::ParamTy>)
+{
+ loop {
+ let num_inputs = input_parameters.len();
+
+ let projection_predicates =
+ predicates.iter()
+ .filter_map(|predicate| {
+ match *predicate {
+ // Ignore higher-ranked binders. For the purposes
+ // of this check, they don't matter because they
+ // only affect named regions, and we're just
+ // concerned about type parameters here.
+ ty::Predicate::Projection(ref data) => Some(data.0.clone()),
+ _ => None,
+ }
+ });
+
+ for projection in projection_predicates {
+ // Special case: watch out for some kind of sneaky attempt
+ // to project out an associated type defined by this very trait.
+ if Some(projection.projection_ty.trait_ref.clone()) == impl_trait_ref {
+ continue;
+ }
+
+ let relies_only_on_inputs =
+ projection.projection_ty.trait_ref.input_types()
+ .iter()
+ .flat_map(|t| t.walk())
+ .filter_map(|t| t.as_opt_param_ty())
+ .all(|t| input_parameters.contains(&t));
+
+ if relies_only_on_inputs {
+ input_parameters.extend(
+ projection.ty.walk().filter_map(|t| t.as_opt_param_ty()));
+ }
+ }
+
+ if input_parameters.len() == num_inputs {
+ break;
+ }
+ }
+}
mod rscope;
mod astconv;
mod collect;
+mod constrained_type_params;
mod coherence;
mod variance;
//! and the definition-site variance of the [corresponding] type parameter
//! of a class `C` is `V1`, then the variance of `X` in the type expression
//! `C<E>` is `V3 = V1.xform(V2)`.
+//!
+//! ### Constraints
+//!
+//! If I have a struct or enum with where clauses:
+//!
+//! struct Foo<T:Bar> { ... }
+//!
+//! you might wonder whether the variance of `T` with respect to `Bar`
+//! affects the variance `T` with respect to `Foo`. I claim no. The
+//! reason: assume that `T` is invariant w/r/t `Bar` but covariant w/r/t
+//! `Foo`. And then we have a `Foo<X>` that is upcast to `Foo<Y>`, where
+//! `X <: Y`. However, while `X : Bar`, `Y : Bar` does not hold. In that
+//! case, the upcast will be illegal, but not because of a variance
+//! failure, but rather because the target type `Foo<Y>` is itself just
+//! not well-formed. Basically we get to assume well-formedness of all
+//! types involved before considering variance.
use self::VarianceTerm::*;
use self::ParamKind::*;
use middle::ty::{self, Ty};
use std::fmt;
use std::rc::Rc;
-use std::iter::repeat;
use syntax::ast;
use syntax::ast_map;
use syntax::ast_util;
empty_variances: Rc<ty::ItemVariances>,
+ // For marker types, UnsafeCell, and other lang items where
+ // variance is hardcoded, records the item-id and the hardcoded
+ // variance.
+ lang_items: Vec<(ast::NodeId, Vec<ty::Variance>)>,
+
// Maps from the node id of a type/generic parameter to the
// corresponding inferred index.
inferred_map: NodeMap<InferredIndex>,
#[derive(Copy, Debug, PartialEq)]
enum ParamKind {
TypeParam,
- RegionParam
+ RegionParam,
}
struct InferredInfo<'a> {
index: uint,
param_id: ast::NodeId,
term: VarianceTermPtr<'a>,
+
+ // Initial value to use for this parameter when inferring
+ // variance. For most parameters, this is Bivariant. But for lang
+ // items and input type parameters on traits, it is different.
+ initial_variance: ty::Variance,
}
fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>,
inferred_map: NodeMap(),
inferred_infos: Vec::new(),
+ lang_items: lang_items(tcx),
+
// cache and share the variance struct used for items with
// no type/region parameters
empty_variances: Rc::new(ty::ItemVariances {
terms_cx
}
+fn lang_items(tcx: &ty::ctxt) -> Vec<(ast::NodeId,Vec<ty::Variance>)> {
+ let all = vec![
+ (tcx.lang_items.phantom_fn(), vec![ty::Contravariant, ty::Covariant]),
+ (tcx.lang_items.phantom_data(), vec![ty::Covariant]),
+ (tcx.lang_items.unsafe_cell_type(), vec![ty::Invariant]),
+
+ // Deprecated:
+ (tcx.lang_items.covariant_type(), vec![ty::Covariant]),
+ (tcx.lang_items.contravariant_type(), vec![ty::Contravariant]),
+ (tcx.lang_items.invariant_type(), vec![ty::Invariant]),
+ (tcx.lang_items.covariant_lifetime(), vec![ty::Covariant]),
+ (tcx.lang_items.contravariant_lifetime(), vec![ty::Contravariant]),
+ (tcx.lang_items.invariant_lifetime(), vec![ty::Invariant]),
+
+ ];
+
+ all.into_iter()
+ .filter(|&(ref d,_)| d.is_some())
+ .filter(|&(ref d,_)| d.as_ref().unwrap().krate == ast::LOCAL_CRATE)
+ .map(|(d, v)| (d.unwrap().node, v))
+ .collect()
+}
+
impl<'a, 'tcx> TermsContext<'a, 'tcx> {
+ fn add_inferreds_for_item(&mut self,
+ item_id: ast::NodeId,
+ has_self: bool,
+ generics: &ast::Generics)
+ {
+ /*!
+ * Add "inferreds" for the generic parameters declared on this
+ * item. This has a lot of annoying parameters because we are
+ * trying to drive this from the AST, rather than the
+ * ty::Generics, so that we can get span info -- but this
+ * means we must accommodate syntactic distinctions.
+ */
+
+ // NB: In the code below for writing the results back into the
+ // tcx, we rely on the fact that all inferreds for a particular
+ // item are assigned continuous indices.
+
+ let inferreds_on_entry = self.num_inferred();
+
+ if has_self {
+ self.add_inferred(item_id, TypeParam, SelfSpace, 0, item_id);
+ }
+
+ for (i, p) in generics.lifetimes.iter().enumerate() {
+ let id = p.lifetime.id;
+ self.add_inferred(item_id, RegionParam, TypeSpace, i, id);
+ }
+
+ for (i, p) in generics.ty_params.iter().enumerate() {
+ self.add_inferred(item_id, TypeParam, TypeSpace, i, p.id);
+ }
+
+ // If this item has no type or lifetime parameters,
+ // then there are no variances to infer, so just
+ // insert an empty entry into the variance map.
+ // Arguably we could just leave the map empty in this
+ // case but it seems cleaner to be able to distinguish
+ // "invalid item id" from "item id with no
+ // parameters".
+ if self.num_inferred() == inferreds_on_entry {
+ let newly_added =
+ self.tcx.item_variance_map.borrow_mut().insert(
+ ast_util::local_def(item_id),
+ self.empty_variances.clone()).is_none();
+ assert!(newly_added);
+ }
+ }
+
fn add_inferred(&mut self,
item_id: ast::NodeId,
kind: ParamKind,
param_id: ast::NodeId) {
let inf_index = InferredIndex(self.inferred_infos.len());
let term = self.arena.alloc(InferredTerm(inf_index));
+ let initial_variance = self.pick_initial_variance(item_id, space, index);
self.inferred_infos.push(InferredInfo { item_id: item_id,
kind: kind,
space: space,
index: index,
param_id: param_id,
- term: term });
+ term: term,
+ initial_variance: initial_variance });
let newly_added = self.inferred_map.insert(param_id, inf_index).is_none();
assert!(newly_added);
- debug!("add_inferred(item_id={}, \
+ debug!("add_inferred(item_path={}, \
+ item_id={}, \
kind={:?}, \
+ space={:?}, \
index={}, \
- param_id={},
- inf_index={:?})",
- item_id, kind, index, param_id, inf_index);
+ param_id={}, \
+ inf_index={:?}, \
+ initial_variance={:?})",
+ ty::item_path_str(self.tcx, ast_util::local_def(item_id)),
+ item_id, kind, space, index, param_id, inf_index,
+ initial_variance);
+ }
+
+ fn pick_initial_variance(&self,
+ item_id: ast::NodeId,
+ space: ParamSpace,
+ index: uint)
+ -> ty::Variance
+ {
+ match space {
+ SelfSpace | FnSpace => {
+ ty::Bivariant
+ }
+
+ TypeSpace => {
+ match self.lang_items.iter().find(|&&(n, _)| n == item_id) {
+ Some(&(_, ref variances)) => variances[index],
+ None => ty::Bivariant
+ }
+ }
+ }
}
fn num_inferred(&self) -> uint {
fn visit_item(&mut self, item: &ast::Item) {
debug!("add_inferreds for item {}", item.repr(self.tcx));
- let inferreds_on_entry = self.num_inferred();
-
- // NB: In the code below for writing the results back into the
- // tcx, we rely on the fact that all inferreds for a particular
- // item are assigned continuous indices.
- match item.node {
- ast::ItemTrait(..) => {
- self.add_inferred(item.id, TypeParam, SelfSpace, 0, item.id);
- }
- _ => { }
- }
-
match item.node {
ast::ItemEnum(_, ref generics) |
- ast::ItemStruct(_, ref generics) |
+ ast::ItemStruct(_, ref generics) => {
+ self.add_inferreds_for_item(item.id, false, generics);
+ }
ast::ItemTrait(_, ref generics, _, _) => {
- for (i, p) in generics.lifetimes.iter().enumerate() {
- let id = p.lifetime.id;
- self.add_inferred(item.id, RegionParam, TypeSpace, i, id);
- }
- for (i, p) in generics.ty_params.iter().enumerate() {
- self.add_inferred(item.id, TypeParam, TypeSpace, i, p.id);
- }
-
- // If this item has no type or lifetime parameters,
- // then there are no variances to infer, so just
- // insert an empty entry into the variance map.
- // Arguably we could just leave the map empty in this
- // case but it seems cleaner to be able to distinguish
- // "invalid item id" from "item id with no
- // parameters".
- if self.num_inferred() == inferreds_on_entry {
- let newly_added = self.tcx.item_variance_map.borrow_mut().insert(
- ast_util::local_def(item.id),
- self.empty_variances.clone()).is_none();
- assert!(newly_added);
- }
-
+ self.add_inferreds_for_item(item.id, true, generics);
visit::walk_item(self, item);
}
struct ConstraintContext<'a, 'tcx: 'a> {
terms_cx: TermsContext<'a, 'tcx>,
- // These are the def-id of the std::marker::InvariantType,
- // std::marker::InvariantLifetime, and so on. The arrays
- // are indexed by the `ParamKind` (type, lifetime, self). Note
- // that there are no marker types for self, so the entries for
- // self are always None.
- invariant_lang_items: [Option<ast::DefId>; 2],
- covariant_lang_items: [Option<ast::DefId>; 2],
- contravariant_lang_items: [Option<ast::DefId>; 2],
- unsafe_cell_lang_item: Option<ast::DefId>,
-
// These are pointers to common `ConstantTerm` instances
covariant: VarianceTermPtr<'a>,
contravariant: VarianceTermPtr<'a>,
fn add_constraints_from_crate<'a, 'tcx>(terms_cx: TermsContext<'a, 'tcx>,
krate: &ast::Crate)
- -> ConstraintContext<'a, 'tcx> {
- let mut invariant_lang_items = [None; 2];
- let mut covariant_lang_items = [None; 2];
- let mut contravariant_lang_items = [None; 2];
-
- covariant_lang_items[TypeParam as uint] =
- terms_cx.tcx.lang_items.covariant_type();
- covariant_lang_items[RegionParam as uint] =
- terms_cx.tcx.lang_items.covariant_lifetime();
-
- contravariant_lang_items[TypeParam as uint] =
- terms_cx.tcx.lang_items.contravariant_type();
- contravariant_lang_items[RegionParam as uint] =
- terms_cx.tcx.lang_items.contravariant_lifetime();
-
- invariant_lang_items[TypeParam as uint] =
- terms_cx.tcx.lang_items.invariant_type();
- invariant_lang_items[RegionParam as uint] =
- terms_cx.tcx.lang_items.invariant_lifetime();
-
- let unsafe_cell_lang_item = terms_cx.tcx.lang_items.unsafe_cell_type();
-
+ -> ConstraintContext<'a, 'tcx>
+{
let covariant = terms_cx.arena.alloc(ConstantTerm(ty::Covariant));
let contravariant = terms_cx.arena.alloc(ConstantTerm(ty::Contravariant));
let invariant = terms_cx.arena.alloc(ConstantTerm(ty::Invariant));
let bivariant = terms_cx.arena.alloc(ConstantTerm(ty::Bivariant));
let mut constraint_cx = ConstraintContext {
terms_cx: terms_cx,
-
- invariant_lang_items: invariant_lang_items,
- covariant_lang_items: covariant_lang_items,
- contravariant_lang_items: contravariant_lang_items,
- unsafe_cell_lang_item: unsafe_cell_lang_item,
-
covariant: covariant,
contravariant: contravariant,
invariant: invariant,
match item.node {
ast::ItemEnum(ref enum_definition, _) => {
- let generics = &ty::lookup_item_type(tcx, did).generics;
+ let scheme = ty::lookup_item_type(tcx, did);
+
+ // Not entirely obvious: constraints on structs/enums do not
+ // affect the variance of their type parameters. See discussion
+ // in comment at top of module.
+ //
+ // self.add_constraints_from_generics(&scheme.generics);
// Hack: If we directly call `ty::enum_variants`, it
// annoyingly takes it upon itself to run off and
&**ast_variant,
/*discriminant*/ 0);
for arg_ty in &variant.args {
- self.add_constraints_from_ty(generics, *arg_ty, self.covariant);
+ self.add_constraints_from_ty(&scheme.generics, *arg_ty, self.covariant);
}
}
}
ast::ItemStruct(..) => {
- let generics = &ty::lookup_item_type(tcx, did).generics;
+ let scheme = ty::lookup_item_type(tcx, did);
+
+ // Not entirely obvious: constraints on structs/enums do not
+ // affect the variance of their type parameters. See discussion
+ // in comment at top of module.
+ //
+ // self.add_constraints_from_generics(&scheme.generics);
+
let struct_fields = ty::lookup_struct_fields(tcx, did);
for field_info in &struct_fields {
assert_eq!(field_info.id.krate, ast::LOCAL_CRATE);
let field_ty = ty::node_id_to_type(tcx, field_info.id.node);
- self.add_constraints_from_ty(generics, field_ty, self.covariant);
+ self.add_constraints_from_ty(&scheme.generics, field_ty, self.covariant);
}
}
ast::ItemTrait(..) => {
+ let trait_def = ty::lookup_trait_def(tcx, did);
+ let predicates = ty::predicates(tcx, ty::mk_self_type(tcx), &trait_def.bounds);
+ self.add_constraints_from_predicates(&trait_def.generics,
+ &predicates[],
+ self.covariant);
+
let trait_items = ty::trait_items(tcx, did);
for trait_item in &*trait_items {
match *trait_item {
ty::MethodTraitItem(ref method) => {
- self.add_constraints_from_sig(&method.generics,
- &method.fty.sig,
- self.covariant);
+ self.add_constraints_from_predicates(
+ &method.generics,
+ method.predicates.predicates.get_slice(FnSpace),
+ self.contravariant);
+
+ self.add_constraints_from_sig(
+ &method.generics,
+ &method.fty.sig,
+ self.covariant);
}
ty::TypeTraitItem(_) => {}
}
ast::ItemTy(..) |
ast::ItemImpl(..) |
ast::ItemMac(..) => {
- visit::walk_item(self, item);
}
}
+
+ visit::walk_item(self, item);
}
}
-> VarianceTermPtr<'a> {
assert_eq!(param_def_id.krate, item_def_id.krate);
- if self.invariant_lang_items[kind as uint] == Some(item_def_id) {
- self.invariant
- } else if self.covariant_lang_items[kind as uint] == Some(item_def_id) {
- self.covariant
- } else if self.contravariant_lang_items[kind as uint] == Some(item_def_id) {
- self.contravariant
- } else if kind == TypeParam && Some(item_def_id) == self.unsafe_cell_lang_item {
- self.invariant
- } else if param_def_id.krate == ast::LOCAL_CRATE {
+ if param_def_id.krate == ast::LOCAL_CRATE {
// Parameter on an item defined within current crate:
// variance not yet inferred, so return a symbolic
// variance.
}
}
+ fn add_constraints_from_trait_ref(&mut self,
+ generics: &ty::Generics<'tcx>,
+ trait_ref: &ty::TraitRef<'tcx>,
+ variance: VarianceTermPtr<'a>) {
+ debug!("add_constraints_from_trait_ref: trait_ref={} variance={:?}",
+ trait_ref.repr(self.tcx()),
+ variance);
+
+ let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id);
+
+ self.add_constraints_from_substs(
+ generics,
+ trait_ref.def_id,
+ trait_def.generics.types.as_slice(),
+ trait_def.generics.regions.as_slice(),
+ trait_ref.substs,
+ variance);
+ }
+
/// Adds constraints appropriate for an instance of `ty` appearing
/// in a context with the generics defined in `generics` and
/// ambient variance `variance`
generics: &ty::Generics<'tcx>,
ty: Ty<'tcx>,
variance: VarianceTermPtr<'a>) {
- debug!("add_constraints_from_ty(ty={})", ty.repr(self.tcx()));
+ debug!("add_constraints_from_ty(ty={}, variance={:?})",
+ ty.repr(self.tcx()),
+ variance);
match ty.sty {
ty::ty_bool |
self.add_constraints_from_ty(generics, typ, variance);
}
+
ty::ty_ptr(ref mt) => {
self.add_constraints_from_mt(generics, mt, variance);
}
}
ty::ty_trait(ref data) => {
- let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(),
- self.tcx().types.err);
- let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id());
-
- // Traits never declare region parameters in the self
- // space nor anything in the fn space.
- assert!(trait_def.generics.regions.is_empty_in(subst::SelfSpace));
- assert!(trait_def.generics.types.is_empty_in(subst::FnSpace));
- assert!(trait_def.generics.regions.is_empty_in(subst::FnSpace));
+ let poly_trait_ref =
+ data.principal_trait_ref_with_self_ty(self.tcx(),
+ self.tcx().types.err);
// The type `Foo<T+'a>` is contravariant w/r/t `'a`:
let contra = self.contravariant(variance);
self.add_constraints_from_region(generics, data.bounds.region_bound, contra);
- self.add_constraints_from_substs(
- generics,
- trait_ref.def_id(),
- trait_def.generics.types.get_slice(subst::TypeSpace),
- trait_def.generics.regions.get_slice(subst::TypeSpace),
- trait_ref.substs(),
- variance);
+ // Ignore the SelfSpace, it is erased.
+ self.add_constraints_from_trait_ref(generics, &*poly_trait_ref.0, variance);
let projections = data.projection_bounds_with_self_ty(self.tcx(),
self.tcx().types.err);
self.add_constraints_from_sig(generics, sig, variance);
}
- ty::ty_infer(..) | ty::ty_err => {
+ ty::ty_err => {
+ // we encounter this when walking the trait references for object
+ // types, where we use ty_err as the Self type
+ }
+
+ ty::ty_infer(..) => {
self.tcx().sess.bug(
&format!("unexpected type encountered in \
variance inference: {}",
region_param_defs: &[ty::RegionParameterDef],
substs: &subst::Substs<'tcx>,
variance: VarianceTermPtr<'a>) {
- debug!("add_constraints_from_substs(def_id={:?})", def_id);
+ debug!("add_constraints_from_substs(def_id={}, substs={}, variance={:?})",
+ def_id.repr(self.tcx()),
+ substs.repr(self.tcx()),
+ variance);
for p in type_param_defs {
let variance_decl =
p.space, p.index as uint);
let variance_i = self.xform(variance, variance_decl);
let substs_ty = *substs.types.get(p.space, p.index as uint);
+ debug!("add_constraints_from_substs: variance_decl={:?} variance_i={:?}",
+ variance_decl, variance_i);
self.add_constraints_from_ty(generics, substs_ty, variance_i);
}
}
}
+ fn add_constraints_from_predicates(&mut self,
+ generics: &ty::Generics<'tcx>,
+ predicates: &[ty::Predicate<'tcx>],
+ variance: VarianceTermPtr<'a>) {
+ debug!("add_constraints_from_generics({})",
+ generics.repr(self.tcx()));
+
+ for predicate in predicates.iter() {
+ match *predicate {
+ ty::Predicate::Trait(ty::Binder(ref data)) => {
+ self.add_constraints_from_trait_ref(generics, &*data.trait_ref, variance);
+ }
+
+ ty::Predicate::Equate(ty::Binder(ref data)) => {
+ self.add_constraints_from_ty(generics, data.0, variance);
+ self.add_constraints_from_ty(generics, data.1, variance);
+ }
+
+ ty::Predicate::TypeOutlives(ty::Binder(ref data)) => {
+ self.add_constraints_from_ty(generics, data.0, variance);
+
+ let variance_r = self.xform(variance, self.contravariant);
+ self.add_constraints_from_region(generics, data.1, variance_r);
+ }
+
+ ty::Predicate::RegionOutlives(ty::Binder(ref data)) => {
+ // `'a : 'b` is still true if 'a gets bigger
+ self.add_constraints_from_region(generics, data.0, variance);
+
+ // `'a : 'b` is still true if 'b gets smaller
+ let variance_r = self.xform(variance, self.contravariant);
+ self.add_constraints_from_region(generics, data.1, variance_r);
+ }
+
+ ty::Predicate::Projection(ty::Binder(ref data)) => {
+ self.add_constraints_from_trait_ref(generics,
+ &*data.projection_ty.trait_ref,
+ variance);
+
+ self.add_constraints_from_ty(generics, data.ty, self.invariant);
+ }
+ }
+ }
+ }
+
/// Adds constraints appropriate for a function with signature
/// `sig` appearing in a context with ambient variance `variance`
fn add_constraints_from_sig(&mut self,
fn solve_constraints(constraints_cx: ConstraintContext) {
let ConstraintContext { terms_cx, constraints, .. } = constraints_cx;
- let solutions: Vec<_> = repeat(ty::Bivariant).take(terms_cx.num_inferred()).collect();
+
+ let solutions =
+ terms_cx.inferred_infos.iter()
+ .map(|ii| ii.initial_variance)
+ .collect();
+
let mut solutions_cx = SolveContext {
terms_cx: terms_cx,
constraints: constraints,
let mut types = VecPerParamSpace::empty();
let mut regions = VecPerParamSpace::empty();
- while index < num_inferred &&
- inferred_infos[index].item_id == item_id {
+ while index < num_inferred && inferred_infos[index].item_id == item_id {
let info = &inferred_infos[index];
let variance = solutions[index];
debug!("Index {} Info {} / {:?} / {:?} Variance {:?}",
index, info.index, info.kind, info.space, variance);
match info.kind {
- TypeParam => {
- types.push(info.space, variance);
- }
- RegionParam => {
- regions.push(info.space, variance);
- }
+ TypeParam => { types.push(info.space, variance); }
+ RegionParam => { regions.push(info.space, variance); }
}
+
index += 1;
}
// attribute and report an error with various results if found.
if ty::has_attr(tcx, item_def_id, "rustc_variance") {
let found = item_variances.repr(tcx);
- span_err!(tcx.sess, tcx.map.span(item_id), E0208, "{}", &found[]);
+ span_err!(tcx.sess, tcx.map.span(item_id), E0208, "{}", &found[..]);
}
let newly_added = tcx.item_variance_map.borrow_mut()
(x, ty::Bivariant) | (ty::Bivariant, x) => x,
}
}
+
impl Lock {
pub fn new(p: &Path) -> Lock {
- let buf = CString::from_slice(p.as_vec());
+ let buf = CString::new(p.as_vec()).unwrap();
let fd = unsafe {
libc::open(buf.as_ptr(), libc::O_RDWR | libc::O_CREAT,
libc::S_IRWXU)
class,
id,
&mut out).unwrap();
- String::from_utf8_lossy(&out[]).into_owned()
+ String::from_utf8_lossy(&out[..]).into_owned()
}
/// Exhausts the `lexer` writing the output into `out`.
s.push_str(&highlight::highlight(&text,
None,
Some("rust-example-rendered")));
- let output = CString::from_vec(s.into_bytes());
+ let output = CString::new(s).unwrap();
hoedown_buffer_puts(ob, output.as_ptr());
})
}
format!("{} ", sec)
});
- let text = CString::from_vec(text.into_bytes());
+ let text = CString::new(text).unwrap();
unsafe { hoedown_buffer_puts(ob, text.as_ptr()) }
}
try!(write!(fmt,
r##"<span id='render-detail'>
- <a id="collapse-all" href="#">[-]
- </a> <a id="expand-all" href="#">[+]</a>
+ <a id="collapse-all" href="#">[-]</a> <a id="expand-all" href="#">[+]</a>
</span>"##));
// Write `src` tag
color: #000;
background: transparent;
}
-p a { color: #4e8bca; }
-p a:hover { text-decoration: underline; }
+.docblock a { color: #4e8bca; }
+.docblock a:hover { text-decoration: underline; }
.content span.trait, .content a.trait, .block a.current.trait { color: #ed9603; }
.content span.mod, .content a.mod, block a.current.mod { color: #4d76ae; }
#![feature(collections)]
#![feature(core)]
#![feature(env)]
-#![feature(hash)]
#![feature(int_uint)]
#![feature(old_io)]
#![feature(libc)]
let mut a: Vec<clean::Attribute> = i.attrs.iter().filter(|&a| match a {
&clean::NameValue(ref x, _) if "doc" == *x => false,
_ => true
- }).map(|x| x.clone()).collect();
+ }).cloned().collect();
if docstr.len() > 0 {
a.push(clean::NameValue("doc".to_string(), docstr));
}
name: name,
items: items.clone(),
generics: gen.clone(),
- bounds: b.iter().map(|x| (*x).clone()).collect(),
+ bounds: b.iter().cloned().collect(),
id: item.id,
attrs: item.attrs.clone(),
whence: item.span,
use std::usize;
use std::default::Default;
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
+#[cfg(stage0)] use std::hash::Hasher;
use std::collections::hash_state::HashState;
use {Decodable, Encodable, Decoder, Encoder};
-use std::collections::{DList, RingBuf, BTreeMap, BTreeSet, HashMap, HashSet, VecMap};
+use std::collections::{LinkedList, VecDeque, BTreeMap, BTreeSet, HashMap, HashSet, VecMap};
use collections::enum_set::{EnumSet, CLike};
impl<
T: Encodable
-> Encodable for DList<T> {
+> Encodable for LinkedList<T> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
}
}
-impl<T:Decodable> Decodable for DList<T> {
- fn decode<D: Decoder>(d: &mut D) -> Result<DList<T>, D::Error> {
+impl<T:Decodable> Decodable for LinkedList<T> {
+ fn decode<D: Decoder>(d: &mut D) -> Result<LinkedList<T>, D::Error> {
d.read_seq(|d, len| {
- let mut list = DList::new();
+ let mut list = LinkedList::new();
for i in 0..len {
list.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
}
}
-impl<T: Encodable> Encodable for RingBuf<T> {
+impl<T: Encodable> Encodable for VecDeque<T> {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
s.emit_seq(self.len(), |s| {
for (i, e) in self.iter().enumerate() {
}
}
-impl<T:Decodable> Decodable for RingBuf<T> {
- fn decode<D: Decoder>(d: &mut D) -> Result<RingBuf<T>, D::Error> {
+impl<T:Decodable> Decodable for VecDeque<T> {
+ fn decode<D: Decoder>(d: &mut D) -> Result<VecDeque<T>, D::Error> {
d.read_seq(|d, len| {
- let mut deque: RingBuf<T> = RingBuf::new();
+ let mut deque: VecDeque<T> = VecDeque::new();
for i in 0..len {
deque.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d))));
}
}
}
+#[cfg(stage0)]
impl<K, V, S> Encodable for HashMap<K, V, S>
where K: Encodable + Hash< <S as HashState>::Hasher> + Eq,
V: Encodable,
})
}
}
+#[cfg(not(stage0))]
+impl<K, V, S> Encodable for HashMap<K, V, S>
+ where K: Encodable + Hash + Eq,
+ V: Encodable,
+ S: HashState,
+{
+ 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(stage0)]
impl<K, V, S> Decodable for HashMap<K, V, S>
where K: Decodable + Hash< <S as HashState>::Hasher> + Eq,
V: Decodable,
})
}
}
+#[cfg(not(stage0))]
+impl<K, V, S> Decodable for HashMap<K, V, S>
+ where K: Decodable + Hash + Eq,
+ V: Decodable,
+ S: HashState + Default,
+{
+ 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(stage0)]
impl<T, S> Encodable for HashSet<T, S>
where T: Encodable + Hash< <S as HashState>::Hasher> + Eq,
S: HashState,
})
}
}
+#[cfg(not(stage0))]
+impl<T, S> Encodable for HashSet<T, S>
+ where T: Encodable + Hash + Eq,
+ S: HashState,
+{
+ 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(stage0)]
impl<T, S> Decodable for HashSet<T, S>
where T: Decodable + Hash< <S as HashState>::Hasher> + Eq,
S: HashState + Default,
})
}
}
+#[cfg(not(stage0))]
+impl<T, S> Decodable for HashSet<T, S>
+ where T: Decodable + Hash + Eq,
+ S: HashState + Default,
+{
+ 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)
+ })
+ }
+}
impl<V: Encodable> Encodable for VecMap<V> {
fn encode<S: Encoder>(&self, e: &mut S) -> Result<(), S::Error> {
/// Returns None otherwise.
pub fn as_string<'a>(&'a self) -> Option<&'a str> {
match *self {
- Json::String(ref s) => Some(&s[]),
+ Json::String(ref s) => Some(&s[..]),
_ => None
}
}
return Err(ExpectedError("String or Object".to_string(), format!("{}", json)))
}
};
- let idx = match names.iter().position(|n| *n == &name[]) {
+ let idx = match names.iter().position(|n| *n == &name[..]) {
Some(idx) => idx,
None => return Err(UnknownVariantError(name))
};
hm.insert(1, true);
let mut mem_buf = Vec::new();
write!(&mut mem_buf, "{}", super::as_pretty_json(&hm)).unwrap();
- let json_str = from_utf8(&mem_buf[]).unwrap();
+ let json_str = from_utf8(&mem_buf[..]).unwrap();
match from_str(json_str) {
Err(_) => panic!("Unable to parse json_str: {:?}", json_str),
_ => {} // it parsed and we are good to go
hm.insert(1, true);
let mut mem_buf = Vec::new();
write!(&mut mem_buf, "{}", super::as_pretty_json(&hm)).unwrap();
- let json_str = from_utf8(&mem_buf[]).unwrap();
+ let json_str = from_utf8(&mem_buf[..]).unwrap();
match from_str(json_str) {
Err(_) => panic!("Unable to parse json_str: {:?}", json_str),
_ => {} // it parsed and we are good to go
write!(&mut writer, "{}",
super::as_pretty_json(&json).indent(i)).unwrap();
- let printed = from_utf8(&writer[]).unwrap();
+ let printed = from_utf8(&writer[..]).unwrap();
// Check for indents at each line
let lines: Vec<&str> = printed.lines().collect();
let mut map = HashMap::new();
map.insert(Enum::Foo, 0);
let result = json::encode(&map).unwrap();
- assert_eq!(&result[], r#"{"Foo":0}"#);
+ assert_eq!(&result[..], r#"{"Foo":0}"#);
let decoded: HashMap<Enum, _> = json::decode(&result).unwrap();
assert_eq!(map, decoded);
}
#![feature(int_uint)]
#![feature(old_io)]
#![feature(old_path)]
-#![feature(hash)]
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(std_misc)]
impl Encodable for String {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
- s.emit_str(&self[])
+ s.emit_str(&self[..])
}
}
use self::SearchResult::*;
use self::VacantEntryState::*;
-use borrow::BorrowFrom;
+use borrow::Borrow;
use clone::Clone;
use cmp::{max, Eq, PartialEq};
use default::Default;
use fmt::{self, Debug};
-use hash::{self, Hash, SipHasher};
+use hash::{Hash, SipHasher};
use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map};
use marker::Sized;
use mem::{self, replace};
}
}
-impl<K, V, S, H> HashMap<K, V, S>
- where K: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<K, V, S> HashMap<K, V, S>
+ where K: Eq + Hash, S: HashState
{
- fn make_hash<X: ?Sized>(&self, x: &X) -> SafeHash where X: Hash<H> {
+ fn make_hash<X: ?Sized>(&self, x: &X) -> SafeHash where X: Hash {
table::make_hash(&self.hash_state, x)
}
/// If you already have the hash for the key lying around, use
/// search_hashed.
fn search<'a, Q: ?Sized>(&'a self, q: &Q) -> Option<FullBucketImm<'a, K, V>>
- where Q: BorrowFrom<K> + Eq + Hash<H>
+ where K: Borrow<Q>, Q: Eq + Hash
{
let hash = self.make_hash(q);
- search_hashed(&self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k)))
+ search_hashed(&self.table, hash, |k| q.eq(k.borrow()))
.into_option()
}
fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> Option<FullBucketMut<'a, K, V>>
- where Q: BorrowFrom<K> + Eq + Hash<H>
+ where K: Borrow<Q>, Q: Eq + Hash
{
let hash = self.make_hash(q);
- search_hashed(&mut self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k)))
+ search_hashed(&mut self.table, hash, |k| q.eq(k.borrow()))
.into_option()
}
}
}
-impl<K: Hash<Hasher> + Eq, V> HashMap<K, V, RandomState> {
+impl<K: Hash + Eq, V> HashMap<K, V, RandomState> {
/// Create an empty HashMap.
///
/// # Example
}
}
-impl<K, V, S, H> HashMap<K, V, S>
- where K: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<K, V, S> HashMap<K, V, S>
+ where K: Eq + Hash, S: HashState
{
/// Creates an empty hashmap which will use the given hasher to hash keys.
///
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
- where Q: Hash<H> + Eq + BorrowFrom<K>
+ where K: Borrow<Q>, Q: Hash + Eq
{
self.search(k).map(|bucket| bucket.into_refs().1)
}
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
- where Q: Hash<H> + Eq + BorrowFrom<K>
+ where K: Borrow<Q>, Q: Hash + Eq
{
self.search(k).is_some()
}
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
- where Q: Hash<H> + Eq + BorrowFrom<K>
+ where K: Borrow<Q>, Q: Hash + Eq
{
self.search_mut(k).map(|bucket| bucket.into_mut_refs().1)
}
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
- where Q: Hash<H> + Eq + BorrowFrom<K>
+ where K: Borrow<Q>, Q: Hash + Eq
{
if self.table.size() == 0 {
return None
}
}
-impl<K, V, S, H> PartialEq for HashMap<K, V, S>
- where K: Eq + Hash<H>, V: PartialEq,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<K, V, S> PartialEq for HashMap<K, V, S>
+ where K: Eq + Hash, V: PartialEq, S: HashState
{
fn eq(&self, other: &HashMap<K, V, S>) -> bool {
if self.len() != other.len() { return false; }
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, H> Eq for HashMap<K, V, S>
- where K: Eq + Hash<H>, V: Eq,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<K, V, S> Eq for HashMap<K, V, S>
+ where K: Eq + Hash, V: Eq, S: HashState
{}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, H> Debug for HashMap<K, V, S>
- where K: Eq + Hash<H> + Debug, V: Debug,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<K, V, S> Debug for HashMap<K, V, S>
+ where K: Eq + Hash + Debug, V: Debug, S: HashState
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "HashMap {{"));
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, H> Default for HashMap<K, V, S>
- where K: Eq + Hash<H>,
- S: HashState<Hasher=H> + Default,
- H: hash::Hasher<Output=u64>
+impl<K, V, S> Default for HashMap<K, V, S>
+ where K: Eq + Hash,
+ S: HashState + Default,
{
fn default() -> HashMap<K, V, S> {
HashMap::with_hash_state(Default::default())
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, Q: ?Sized, V, S, H> Index<Q> for HashMap<K, V, S>
- where K: Eq + Hash<H>,
- Q: Eq + Hash<H> + BorrowFrom<K>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<K, Q: ?Sized, V, S> Index<Q> for HashMap<K, V, S>
+ where K: Eq + Hash + Borrow<Q>,
+ Q: Eq + Hash,
+ S: HashState,
{
type Output = V;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, H, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
- where K: Eq + Hash<H>,
- Q: Eq + Hash<H> + BorrowFrom<K>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<K, V, S, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
+ where K: Eq + Hash + Borrow<Q>,
+ Q: Eq + Hash,
+ S: HashState,
{
#[inline]
fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K, V, S, H> IntoIterator for &'a HashMap<K, V, S>
- where K: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<'a, K, V, S> IntoIterator for &'a HashMap<K, V, S>
+ where K: Eq + Hash, S: HashState
{
type Item = (&'a K, &'a V);
type IntoIter = Iter<'a, K, V>;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, K, V, S, H> IntoIterator for &'a mut HashMap<K, V, S>
- where K: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<'a, K, V, S> IntoIterator for &'a mut HashMap<K, V, S>
+ where K: Eq + Hash, S: HashState
{
type Item = (&'a K, &'a mut V);
type IntoIter = IterMut<'a, K, V>;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, H> IntoIterator for HashMap<K, V, S>
- where K: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<K, V, S> IntoIterator for HashMap<K, V, S>
+ where K: Eq + Hash, S: HashState
{
type Item = (K, V);
type IntoIter = IntoIter<K, V>;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, H> FromIterator<(K, V)> for HashMap<K, V, S>
- where K: Eq + Hash<H>,
- S: HashState<Hasher=H> + Default,
- H: hash::Hasher<Output=u64>
+impl<K, V, S> FromIterator<(K, V)> for HashMap<K, V, S>
+ where K: Eq + Hash, S: HashState + Default
{
- fn from_iter<T: Iterator<Item=(K, V)>>(iter: T) -> HashMap<K, V, S> {
+ fn from_iter<T: IntoIterator<Item=(K, V)>>(iterable: T) -> HashMap<K, V, S> {
+ let iter = iterable.into_iter();
let lower = iter.size_hint().0;
let mut map = HashMap::with_capacity_and_hash_state(lower,
Default::default());
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<K, V, S, H> Extend<(K, V)> for HashMap<K, V, S>
- where K: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<K, V, S> Extend<(K, V)> for HashMap<K, V, S>
+ where K: Eq + Hash, S: HashState
{
- fn extend<T: Iterator<Item=(K, V)>>(&mut self, iter: T) {
+ fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) {
for (k, v) in iter {
self.insert(k, v);
}
#[unstable(feature = "std_misc",
reason = "hashing an hash maps may be altered")]
impl HashState for RandomState {
- type Hasher = Hasher;
- fn hasher(&self) -> Hasher {
- Hasher { inner: SipHasher::new_with_keys(self.k0, self.k1) }
+ type Hasher = SipHasher;
+ fn hasher(&self) -> SipHasher {
+ SipHasher::new_with_keys(self.k0, self.k1)
}
}
}
}
-/// A hasher implementation which is generated from `RandomState` instances.
-///
-/// This is the default hasher used in a `HashMap` to hash keys. Types do not
-/// typically declare an ability to explicitly hash into this particular type,
-/// but rather in a `H: hash::Writer` type parameter.
-#[unstable(feature = "std_misc",
- reason = "hashing an hash maps may be altered")]
-pub struct Hasher { inner: SipHasher }
-
-impl hash::Writer for Hasher {
- fn write(&mut self, data: &[u8]) { self.inner.write(data) }
-}
-
-impl hash::Hasher for Hasher {
- type Output = u64;
- fn reset(&mut self) { self.inner.reset() }
- fn finish(&self) -> u64 { self.inner.finish() }
-}
-
#[cfg(test)]
mod test_map {
use prelude::v1::*;
--- /dev/null
+// Copyright 2014-2015 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.
+//
+// ignore-lexer-test FIXME #15883
+
+use self::Entry::*;
+use self::SearchResult::*;
+use self::VacantEntryState::*;
+
+use borrow::Borrow;
+use clone::Clone;
+use cmp::{max, Eq, PartialEq};
+use default::Default;
+use fmt::{self, Debug};
+use hash::{self, Hash, SipHasher};
+use iter::{self, Iterator, ExactSizeIterator, IntoIterator, IteratorExt, FromIterator, Extend, Map};
+use marker::Sized;
+use mem::{self, replace};
+use num::{Int, UnsignedInt};
+use ops::{Deref, FnMut, Index, IndexMut};
+use option::Option::{self, Some, None};
+use rand::{self, Rng};
+use result::Result::{self, Ok, Err};
+
+use super::table::{
+ self,
+ Bucket,
+ EmptyBucket,
+ FullBucket,
+ FullBucketImm,
+ FullBucketMut,
+ RawTable,
+ SafeHash
+};
+use super::table::BucketState::{
+ Empty,
+ Full,
+};
+use super::state::HashState;
+
+const INITIAL_LOG2_CAP: usize = 5;
+#[unstable(feature = "std_misc")]
+pub const INITIAL_CAPACITY: usize = 1 << INITIAL_LOG2_CAP; // 2^5
+
+/// The default behavior of HashMap implements a load factor of 90.9%.
+/// This behavior is characterized by the following condition:
+///
+/// - if size > 0.909 * capacity: grow the map
+#[derive(Clone)]
+struct DefaultResizePolicy;
+
+impl DefaultResizePolicy {
+ fn new() -> DefaultResizePolicy {
+ DefaultResizePolicy
+ }
+
+ #[inline]
+ fn min_capacity(&self, usable_size: usize) -> usize {
+ // Here, we are rephrasing the logic by specifying the lower limit
+ // on capacity:
+ //
+ // - if `cap < size * 1.1`: grow the map
+ usable_size * 11 / 10
+ }
+
+ /// An inverse of `min_capacity`, approximately.
+ #[inline]
+ fn usable_capacity(&self, cap: usize) -> usize {
+ // As the number of entries approaches usable capacity,
+ // min_capacity(size) must be smaller than the internal capacity,
+ // so that the map is not resized:
+ // `min_capacity(usable_capacity(x)) <= x`.
+ // The left-hand side can only be smaller due to flooring by integer
+ // division.
+ //
+ // This doesn't have to be checked for overflow since allocation size
+ // in bytes will overflow earlier than multiplication by 10.
+ cap * 10 / 11
+ }
+}
+
+#[test]
+fn test_resize_policy() {
+ use prelude::v1::*;
+ let rp = DefaultResizePolicy;
+ for n in 0..1000 {
+ assert!(rp.min_capacity(rp.usable_capacity(n)) <= n);
+ assert!(rp.usable_capacity(rp.min_capacity(n)) <= n);
+ }
+}
+
+// The main performance trick in this hashmap is called Robin Hood Hashing.
+// It gains its excellent performance from one essential operation:
+//
+// If an insertion collides with an existing element, and that element's
+// "probe distance" (how far away the element is from its ideal location)
+// is higher than how far we've already probed, swap the elements.
+//
+// This massively lowers variance in probe distance, and allows us to get very
+// high load factors with good performance. The 90% load factor I use is rather
+// conservative.
+//
+// > Why a load factor of approximately 90%?
+//
+// In general, all the distances to initial buckets will converge on the mean.
+// At a load factor of α, the odds of finding the target bucket after k
+// probes is approximately 1-α^k. If we set this equal to 50% (since we converge
+// on the mean) and set k=8 (64-byte cache line / 8-byte hash), α=0.92. I round
+// this down to make the math easier on the CPU and avoid its FPU.
+// Since on average we start the probing in the middle of a cache line, this
+// strategy pulls in two cache lines of hashes on every lookup. I think that's
+// pretty good, but if you want to trade off some space, it could go down to one
+// cache line on average with an α of 0.84.
+//
+// > Wait, what? Where did you get 1-α^k from?
+//
+// On the first probe, your odds of a collision with an existing element is α.
+// The odds of doing this twice in a row is approximately α^2. For three times,
+// α^3, etc. Therefore, the odds of colliding k times is α^k. The odds of NOT
+// colliding after k tries is 1-α^k.
+//
+// The paper from 1986 cited below mentions an implementation which keeps track
+// of the distance-to-initial-bucket histogram. This approach is not suitable
+// for modern architectures because it requires maintaining an internal data
+// structure. This allows very good first guesses, but we are most concerned
+// with guessing entire cache lines, not individual indexes. Furthermore, array
+// accesses are no longer linear and in one direction, as we have now. There
+// is also memory and cache pressure that this would entail that would be very
+// difficult to properly see in a microbenchmark.
+//
+// ## Future Improvements (FIXME!)
+//
+// Allow the load factor to be changed dynamically and/or at initialization.
+//
+// Also, would it be possible for us to reuse storage when growing the
+// underlying table? This is exactly the use case for 'realloc', and may
+// be worth exploring.
+//
+// ## Future Optimizations (FIXME!)
+//
+// Another possible design choice that I made without any real reason is
+// parameterizing the raw table over keys and values. Technically, all we need
+// is the size and alignment of keys and values, and the code should be just as
+// efficient (well, we might need one for power-of-two size and one for not...).
+// This has the potential to reduce code bloat in rust executables, without
+// really losing anything except 4 words (key size, key alignment, val size,
+// val alignment) which can be passed in to every call of a `RawTable` function.
+// This would definitely be an avenue worth exploring if people start complaining
+// about the size of rust executables.
+//
+// Annotate exceedingly likely branches in `table::make_hash`
+// and `search_hashed` to reduce instruction cache pressure
+// and mispredictions once it becomes possible (blocked on issue #11092).
+//
+// Shrinking the table could simply reallocate in place after moving buckets
+// to the first half.
+//
+// The growth algorithm (fragment of the Proof of Correctness)
+// --------------------
+//
+// The growth algorithm is basically a fast path of the naive reinsertion-
+// during-resize algorithm. Other paths should never be taken.
+//
+// Consider growing a robin hood hashtable of capacity n. Normally, we do this
+// by allocating a new table of capacity `2n`, and then individually reinsert
+// each element in the old table into the new one. This guarantees that the
+// new table is a valid robin hood hashtable with all the desired statistical
+// properties. Remark that the order we reinsert the elements in should not
+// matter. For simplicity and efficiency, we will consider only linear
+// reinsertions, which consist of reinserting all elements in the old table
+// into the new one by increasing order of index. However we will not be
+// starting our reinsertions from index 0 in general. If we start from index
+// i, for the purpose of reinsertion we will consider all elements with real
+// index j < i to have virtual index n + j.
+//
+// Our hash generation scheme consists of generating a 64-bit hash and
+// truncating the most significant bits. When moving to the new table, we
+// simply introduce a new bit to the front of the hash. Therefore, if an
+// elements has ideal index i in the old table, it can have one of two ideal
+// locations in the new table. If the new bit is 0, then the new ideal index
+// is i. If the new bit is 1, then the new ideal index is n + i. Intuitively,
+// we are producing two independent tables of size n, and for each element we
+// independently choose which table to insert it into with equal probability.
+// However the rather than wrapping around themselves on overflowing their
+// indexes, the first table overflows into the first, and the first into the
+// second. Visually, our new table will look something like:
+//
+// [yy_xxx_xxxx_xxx|xx_yyy_yyyy_yyy]
+//
+// Where x's are elements inserted into the first table, y's are elements
+// inserted into the second, and _'s are empty sections. We now define a few
+// key concepts that we will use later. Note that this is a very abstract
+// perspective of the table. A real resized table would be at least half
+// empty.
+//
+// Theorem: A linear robin hood reinsertion from the first ideal element
+// produces identical results to a linear naive reinsertion from the same
+// element.
+//
+// FIXME(Gankro, pczarn): review the proof and put it all in a separate doc.rs
+
+/// A hash map implementation which uses linear probing with Robin
+/// Hood bucket stealing.
+///
+/// The hashes are all keyed by the task-local random number generator
+/// on creation by default. This means that the ordering of the keys is
+/// randomized, but makes the tables more resistant to
+/// denial-of-service attacks (Hash DoS). This behaviour can be
+/// overridden with one of the constructors.
+///
+/// It is required that the keys implement the `Eq` and `Hash` traits, although
+/// this can frequently be achieved by using `#[derive(Eq, Hash)]`.
+///
+/// Relevant papers/articles:
+///
+/// 1. Pedro Celis. ["Robin Hood Hashing"](https://cs.uwaterloo.ca/research/tr/1986/CS-86-14.pdf)
+/// 2. Emmanuel Goossaert. ["Robin Hood
+/// hashing"](http://codecapsule.com/2013/11/11/robin-hood-hashing/)
+/// 3. Emmanuel Goossaert. ["Robin Hood hashing: backward shift
+/// deletion"](http://codecapsule.com/2013/11/17/robin-hood-hashing-backward-shift-deletion/)
+///
+/// # Example
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// // type inference lets us omit an explicit type signature (which
+/// // would be `HashMap<&str, &str>` in this example).
+/// let mut book_reviews = HashMap::new();
+///
+/// // review some books.
+/// book_reviews.insert("Adventures of Huckleberry Finn", "My favorite book.");
+/// book_reviews.insert("Grimms' Fairy Tales", "Masterpiece.");
+/// book_reviews.insert("Pride and Prejudice", "Very enjoyable.");
+/// book_reviews.insert("The Adventures of Sherlock Holmes", "Eye lyked it alot.");
+///
+/// // check for a specific one.
+/// if !book_reviews.contains_key(&("Les Misérables")) {
+/// println!("We've got {} reviews, but Les Misérables ain't one.",
+/// book_reviews.len());
+/// }
+///
+/// // oops, this review has a lot of spelling mistakes, let's delete it.
+/// book_reviews.remove(&("The Adventures of Sherlock Holmes"));
+///
+/// // look up the values associated with some keys.
+/// let to_find = ["Pride and Prejudice", "Alice's Adventure in Wonderland"];
+/// for book in to_find.iter() {
+/// match book_reviews.get(book) {
+/// Some(review) => println!("{}: {}", *book, *review),
+/// None => println!("{} is unreviewed.", *book)
+/// }
+/// }
+///
+/// // iterate over everything.
+/// for (book, review) in book_reviews.iter() {
+/// println!("{}: \"{}\"", *book, *review);
+/// }
+/// ```
+///
+/// The easiest way to use `HashMap` with a custom type as key is to derive `Eq` and `Hash`.
+/// We must also derive `PartialEq`.
+///
+/// ```
+/// use std::collections::HashMap;
+///
+/// #[derive(Hash, Eq, PartialEq, Debug)]
+/// struct Viking {
+/// name: String,
+/// country: String,
+/// }
+///
+/// impl Viking {
+/// /// Create a new Viking.
+/// fn new(name: &str, country: &str) -> Viking {
+/// Viking { name: name.to_string(), country: country.to_string() }
+/// }
+/// }
+///
+/// // Use a HashMap to store the vikings' health points.
+/// let mut vikings = HashMap::new();
+///
+/// vikings.insert(Viking::new("Einar", "Norway"), 25);
+/// vikings.insert(Viking::new("Olaf", "Denmark"), 24);
+/// vikings.insert(Viking::new("Harald", "Iceland"), 12);
+///
+/// // Use derived implementation to print the status of the vikings.
+/// for (viking, health) in vikings.iter() {
+/// println!("{:?} has {} hp", viking, health);
+/// }
+/// ```
+#[derive(Clone)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct HashMap<K, V, S = RandomState> {
+ // All hashes are keyed on these values, to prevent hash collision attacks.
+ hash_state: S,
+
+ table: RawTable<K, V>,
+
+ resize_policy: DefaultResizePolicy,
+}
+
+/// Search for a pre-hashed key.
+fn search_hashed<K, V, M, F>(table: M,
+ hash: SafeHash,
+ mut is_match: F)
+ -> SearchResult<K, V, M> where
+ M: Deref<Target=RawTable<K, V>>,
+ F: FnMut(&K) -> bool,
+{
+ let size = table.size();
+ let mut probe = Bucket::new(table, hash);
+ let ib = probe.index();
+
+ while probe.index() != ib + size {
+ let full = match probe.peek() {
+ Empty(b) => return TableRef(b.into_table()), // hit an empty bucket
+ Full(b) => b
+ };
+
+ if full.distance() + ib < full.index() {
+ // We can finish the search early if we hit any bucket
+ // with a lower distance to initial bucket than we've probed.
+ return TableRef(full.into_table());
+ }
+
+ // If the hash doesn't match, it can't be this one..
+ if hash == full.hash() {
+ // If the key doesn't match, it can't be this one..
+ if is_match(full.read().0) {
+ return FoundExisting(full);
+ }
+ }
+
+ probe = full.next();
+ }
+
+ TableRef(probe.into_table())
+}
+
+fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
+ let (empty, retkey, retval) = starting_bucket.take();
+ let mut gap = match empty.gap_peek() {
+ Some(b) => b,
+ None => return (retkey, retval)
+ };
+
+ while gap.full().distance() != 0 {
+ gap = match gap.shift() {
+ Some(b) => b,
+ None => break
+ };
+ }
+
+ // Now we've done all our shifting. Return the value we grabbed earlier.
+ (retkey, retval)
+}
+
+/// Perform robin hood bucket stealing at the given `bucket`. You must
+/// also pass the position of that bucket's initial bucket so we don't have
+/// to recalculate it.
+///
+/// `hash`, `k`, and `v` are the elements to "robin hood" into the hashtable.
+fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
+ mut ib: usize,
+ mut hash: SafeHash,
+ mut k: K,
+ mut v: V)
+ -> &'a mut V {
+ let starting_index = bucket.index();
+ let size = {
+ let table = bucket.table(); // FIXME "lifetime too short".
+ table.size()
+ };
+ // There can be at most `size - dib` buckets to displace, because
+ // in the worst case, there are `size` elements and we already are
+ // `distance` buckets away from the initial one.
+ let idx_end = starting_index + size - bucket.distance();
+
+ loop {
+ let (old_hash, old_key, old_val) = bucket.replace(hash, k, v);
+ loop {
+ let probe = bucket.next();
+ assert!(probe.index() != idx_end);
+
+ let full_bucket = match probe.peek() {
+ Empty(bucket) => {
+ // Found a hole!
+ let b = bucket.put(old_hash, old_key, old_val);
+ // Now that it's stolen, just read the value's pointer
+ // right out of the table!
+ return Bucket::at_index(b.into_table(), starting_index)
+ .peek()
+ .expect_full()
+ .into_mut_refs()
+ .1;
+ },
+ Full(bucket) => bucket
+ };
+
+ let probe_ib = full_bucket.index() - full_bucket.distance();
+
+ bucket = full_bucket;
+
+ // Robin hood! Steal the spot.
+ if ib < probe_ib {
+ ib = probe_ib;
+ hash = old_hash;
+ k = old_key;
+ v = old_val;
+ break;
+ }
+ }
+ }
+}
+
+/// A result that works like Option<FullBucket<..>> but preserves
+/// the reference that grants us access to the table in any case.
+enum SearchResult<K, V, M> {
+ // This is an entry that holds the given key:
+ FoundExisting(FullBucket<K, V, M>),
+
+ // There was no such entry. The reference is given back:
+ TableRef(M)
+}
+
+impl<K, V, M> SearchResult<K, V, M> {
+ fn into_option(self) -> Option<FullBucket<K, V, M>> {
+ match self {
+ FoundExisting(bucket) => Some(bucket),
+ TableRef(_) => None
+ }
+ }
+}
+
+impl<K, V, S, H> HashMap<K, V, S>
+ where K: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ fn make_hash<X: ?Sized>(&self, x: &X) -> SafeHash where X: Hash<H> {
+ table::make_hash(&self.hash_state, x)
+ }
+
+ /// Search for a key, yielding the index if it's found in the hashtable.
+ /// If you already have the hash for the key lying around, use
+ /// search_hashed.
+ fn search<'a, Q: ?Sized>(&'a self, q: &Q) -> Option<FullBucketImm<'a, K, V>>
+ where K: Borrow<Q>, Q: Eq + Hash<H>
+ {
+ let hash = self.make_hash(q);
+ search_hashed(&self.table, hash, |k| q.eq(k.borrow()))
+ .into_option()
+ }
+
+ fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> Option<FullBucketMut<'a, K, V>>
+ where K: Borrow<Q>, Q: Eq + Hash<H>
+ {
+ let hash = self.make_hash(q);
+ search_hashed(&mut self.table, hash, |k| q.eq(k.borrow()))
+ .into_option()
+ }
+
+ // The caller should ensure that invariants by Robin Hood Hashing hold.
+ fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) {
+ let cap = self.table.capacity();
+ let mut buckets = Bucket::new(&mut self.table, hash);
+ let ib = buckets.index();
+
+ while buckets.index() != ib + cap {
+ // We don't need to compare hashes for value swap.
+ // Not even DIBs for Robin Hood.
+ buckets = match buckets.peek() {
+ Empty(empty) => {
+ empty.put(hash, k, v);
+ return;
+ }
+ Full(b) => b.into_bucket()
+ };
+ buckets.next();
+ }
+ panic!("Internal HashMap error: Out of space.");
+ }
+}
+
+impl<K: Hash<Hasher> + Eq, V> HashMap<K, V, RandomState> {
+ /// Create an empty HashMap.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ /// let mut map: HashMap<&str, int> = HashMap::new();
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn new() -> HashMap<K, V, RandomState> {
+ Default::default()
+ }
+
+ /// Creates an empty hash map with the given initial capacity.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ /// let mut map: HashMap<&str, int> = HashMap::with_capacity(10);
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn with_capacity(capacity: usize) -> HashMap<K, V, RandomState> {
+ HashMap::with_capacity_and_hash_state(capacity, Default::default())
+ }
+}
+
+impl<K, V, S, H> HashMap<K, V, S>
+ where K: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ /// Creates an empty hashmap which will use the given hasher to hash keys.
+ ///
+ /// The creates map has the default initial capacity.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ /// use std::collections::hash_map::RandomState;
+ ///
+ /// let s = RandomState::new();
+ /// let mut map = HashMap::with_hash_state(s);
+ /// map.insert(1, 2);
+ /// ```
+ #[inline]
+ #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
+ pub fn with_hash_state(hash_state: S) -> HashMap<K, V, S> {
+ HashMap {
+ hash_state: hash_state,
+ resize_policy: DefaultResizePolicy::new(),
+ table: RawTable::new(0),
+ }
+ }
+
+ /// Create an empty HashMap with space for at least `capacity`
+ /// elements, using `hasher` to hash the keys.
+ ///
+ /// Warning: `hasher` is normally randomly generated, and
+ /// is designed to allow HashMaps to be resistant to attacks that
+ /// cause many collisions and very poor performance. Setting it
+ /// manually using this function can expose a DoS attack vector.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ /// use std::collections::hash_map::RandomState;
+ ///
+ /// let s = RandomState::new();
+ /// let mut map = HashMap::with_capacity_and_hash_state(10, s);
+ /// map.insert(1, 2);
+ /// ```
+ #[inline]
+ #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
+ pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
+ -> HashMap<K, V, S> {
+ let resize_policy = DefaultResizePolicy::new();
+ let min_cap = max(INITIAL_CAPACITY, resize_policy.min_capacity(capacity));
+ let internal_cap = min_cap.checked_next_power_of_two().expect("capacity overflow");
+ assert!(internal_cap >= capacity, "capacity overflow");
+ HashMap {
+ hash_state: hash_state,
+ resize_policy: resize_policy,
+ table: RawTable::new(internal_cap),
+ }
+ }
+
+ /// Returns the number of elements the map can hold without reallocating.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ /// let map: HashMap<int, int> = HashMap::with_capacity(100);
+ /// assert!(map.capacity() >= 100);
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn capacity(&self) -> usize {
+ self.resize_policy.usable_capacity(self.table.capacity())
+ }
+
+ /// Reserves capacity for at least `additional` more elements to be inserted
+ /// in the `HashMap`. The collection may reserve more space to avoid
+ /// frequent reallocations.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the new allocation size overflows `usize`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ /// let mut map: HashMap<&str, int> = HashMap::new();
+ /// map.reserve(10);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn reserve(&mut self, additional: usize) {
+ let new_size = self.len().checked_add(additional).expect("capacity overflow");
+ let min_cap = self.resize_policy.min_capacity(new_size);
+
+ // An invalid value shouldn't make us run out of space. This includes
+ // an overflow check.
+ assert!(new_size <= min_cap);
+
+ if self.table.capacity() < min_cap {
+ let new_capacity = max(min_cap.next_power_of_two(), INITIAL_CAPACITY);
+ self.resize(new_capacity);
+ }
+ }
+
+ /// Resizes the internal vectors to a new capacity. It's your responsibility to:
+ /// 1) Make sure the new capacity is enough for all the elements, accounting
+ /// for the load factor.
+ /// 2) Ensure new_capacity is a power of two or zero.
+ fn resize(&mut self, new_capacity: usize) {
+ assert!(self.table.size() <= new_capacity);
+ assert!(new_capacity.is_power_of_two() || new_capacity == 0);
+
+ let mut old_table = replace(&mut self.table, RawTable::new(new_capacity));
+ let old_size = old_table.size();
+
+ if old_table.capacity() == 0 || old_table.size() == 0 {
+ return;
+ }
+
+ // Grow the table.
+ // Specialization of the other branch.
+ let mut bucket = Bucket::first(&mut old_table);
+
+ // "So a few of the first shall be last: for many be called,
+ // but few chosen."
+ //
+ // We'll most likely encounter a few buckets at the beginning that
+ // have their initial buckets near the end of the table. They were
+ // placed at the beginning as the probe wrapped around the table
+ // during insertion. We must skip forward to a bucket that won't
+ // get reinserted too early and won't unfairly steal others spot.
+ // This eliminates the need for robin hood.
+ loop {
+ bucket = match bucket.peek() {
+ Full(full) => {
+ if full.distance() == 0 {
+ // This bucket occupies its ideal spot.
+ // It indicates the start of another "cluster".
+ bucket = full.into_bucket();
+ break;
+ }
+ // Leaving this bucket in the last cluster for later.
+ full.into_bucket()
+ }
+ Empty(b) => {
+ // Encountered a hole between clusters.
+ b.into_bucket()
+ }
+ };
+ bucket.next();
+ }
+
+ // This is how the buckets might be laid out in memory:
+ // ($ marks an initialized bucket)
+ // ________________
+ // |$$$_$$$$$$_$$$$$|
+ //
+ // But we've skipped the entire initial cluster of buckets
+ // and will continue iteration in this order:
+ // ________________
+ // |$$$$$$_$$$$$
+ // ^ wrap around once end is reached
+ // ________________
+ // $$$_____________|
+ // ^ exit once table.size == 0
+ loop {
+ bucket = match bucket.peek() {
+ Full(bucket) => {
+ let h = bucket.hash();
+ let (b, k, v) = bucket.take();
+ self.insert_hashed_ordered(h, k, v);
+ {
+ let t = b.table(); // FIXME "lifetime too short".
+ if t.size() == 0 { break }
+ };
+ b.into_bucket()
+ }
+ Empty(b) => b.into_bucket()
+ };
+ bucket.next();
+ }
+
+ assert_eq!(self.table.size(), old_size);
+ }
+
+ /// Shrinks the capacity of the map as much as possible. It will drop
+ /// down as much as possible while maintaining the internal rules
+ /// and possibly leaving some space in accordance with the resize policy.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut map: HashMap<int, int> = HashMap::with_capacity(100);
+ /// map.insert(1, 2);
+ /// map.insert(3, 4);
+ /// assert!(map.capacity() >= 100);
+ /// map.shrink_to_fit();
+ /// assert!(map.capacity() >= 2);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn shrink_to_fit(&mut self) {
+ let min_capacity = self.resize_policy.min_capacity(self.len());
+ let min_capacity = max(min_capacity.next_power_of_two(), INITIAL_CAPACITY);
+
+ // An invalid value shouldn't make us run out of space.
+ debug_assert!(self.len() <= min_capacity);
+
+ if self.table.capacity() != min_capacity {
+ let old_table = replace(&mut self.table, RawTable::new(min_capacity));
+ let old_size = old_table.size();
+
+ // Shrink the table. Naive algorithm for resizing:
+ for (h, k, v) in old_table.into_iter() {
+ self.insert_hashed_nocheck(h, k, v);
+ }
+
+ debug_assert_eq!(self.table.size(), old_size);
+ }
+ }
+
+ /// Insert a pre-hashed key-value pair, without first checking
+ /// that there's enough room in the buckets. Returns a reference to the
+ /// newly insert value.
+ ///
+ /// If the key already exists, the hashtable will be returned untouched
+ /// and a reference to the existing element will be returned.
+ fn insert_hashed_nocheck(&mut self, hash: SafeHash, k: K, v: V) -> &mut V {
+ self.insert_or_replace_with(hash, k, v, |_, _, _| ())
+ }
+
+ fn insert_or_replace_with<'a, F>(&'a mut self,
+ hash: SafeHash,
+ k: K,
+ v: V,
+ mut found_existing: F)
+ -> &'a mut V where
+ F: FnMut(&mut K, &mut V, V),
+ {
+ // Worst case, we'll find one empty bucket among `size + 1` buckets.
+ let size = self.table.size();
+ let mut probe = Bucket::new(&mut self.table, hash);
+ let ib = probe.index();
+
+ loop {
+ let mut bucket = match probe.peek() {
+ Empty(bucket) => {
+ // Found a hole!
+ return bucket.put(hash, k, v).into_mut_refs().1;
+ }
+ Full(bucket) => bucket
+ };
+
+ // hash matches?
+ if bucket.hash() == hash {
+ // key matches?
+ if k == *bucket.read_mut().0 {
+ let (bucket_k, bucket_v) = bucket.into_mut_refs();
+ debug_assert!(k == *bucket_k);
+ // Key already exists. Get its reference.
+ found_existing(bucket_k, bucket_v, v);
+ return bucket_v;
+ }
+ }
+
+ let robin_ib = bucket.index() as int - bucket.distance() as int;
+
+ if (ib as int) < robin_ib {
+ // Found a luckier bucket than me. Better steal his spot.
+ return robin_hood(bucket, robin_ib as usize, hash, k, v);
+ }
+
+ probe = bucket.next();
+ assert!(probe.index() != ib + size + 1);
+ }
+ }
+
+ /// An iterator visiting all keys in arbitrary order.
+ /// Iterator element type is `&'a K`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut map = HashMap::new();
+ /// map.insert("a", 1);
+ /// map.insert("b", 2);
+ /// map.insert("c", 3);
+ ///
+ /// for key in map.keys() {
+ /// println!("{}", key);
+ /// }
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
+ fn first<A, B>((a, _): (A, B)) -> A { a }
+ let first: fn((&'a K,&'a V)) -> &'a K = first; // coerce to fn ptr
+
+ Keys { inner: self.iter().map(first) }
+ }
+
+ /// An iterator visiting all values in arbitrary order.
+ /// Iterator element type is `&'a V`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut map = HashMap::new();
+ /// map.insert("a", 1);
+ /// map.insert("b", 2);
+ /// map.insert("c", 3);
+ ///
+ /// for val in map.values() {
+ /// println!("{}", val);
+ /// }
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn values<'a>(&'a self) -> Values<'a, K, V> {
+ fn second<A, B>((_, b): (A, B)) -> B { b }
+ let second: fn((&'a K,&'a V)) -> &'a V = second; // coerce to fn ptr
+
+ Values { inner: self.iter().map(second) }
+ }
+
+ /// An iterator visiting all key-value pairs in arbitrary order.
+ /// Iterator element type is `(&'a K, &'a V)`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut map = HashMap::new();
+ /// map.insert("a", 1);
+ /// map.insert("b", 2);
+ /// map.insert("c", 3);
+ ///
+ /// for (key, val) in map.iter() {
+ /// println!("key: {} val: {}", key, val);
+ /// }
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn iter(&self) -> Iter<K, V> {
+ Iter { inner: self.table.iter() }
+ }
+
+ /// An iterator visiting all key-value pairs in arbitrary order,
+ /// with mutable references to the values.
+ /// Iterator element type is `(&'a K, &'a mut V)`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut map = HashMap::new();
+ /// map.insert("a", 1);
+ /// map.insert("b", 2);
+ /// map.insert("c", 3);
+ ///
+ /// // Update all values
+ /// for (_, val) in map.iter_mut() {
+ /// *val *= 2;
+ /// }
+ ///
+ /// for (key, val) in map.iter() {
+ /// println!("key: {} val: {}", key, val);
+ /// }
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn iter_mut(&mut self) -> IterMut<K, V> {
+ IterMut { inner: self.table.iter_mut() }
+ }
+
+ /// Creates a consuming iterator, that is, one that moves each key-value
+ /// pair out of the map in arbitrary order. The map cannot be used after
+ /// calling this.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut map = HashMap::new();
+ /// map.insert("a", 1);
+ /// map.insert("b", 2);
+ /// map.insert("c", 3);
+ ///
+ /// // Not possible with .iter()
+ /// let vec: Vec<(&str, int)> = map.into_iter().collect();
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn into_iter(self) -> IntoIter<K, V> {
+ fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
+ let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two;
+
+ IntoIter {
+ inner: self.table.into_iter().map(last_two)
+ }
+ }
+
+ /// Gets the given key's corresponding entry in the map for in-place manipulation.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn entry(&mut self, key: K) -> Entry<K, V> {
+ // Gotta resize now.
+ self.reserve(1);
+
+ let hash = self.make_hash(&key);
+ search_entry_hashed(&mut self.table, hash, key)
+ }
+
+ /// Returns the number of elements in the map.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut a = HashMap::new();
+ /// assert_eq!(a.len(), 0);
+ /// a.insert(1, "a");
+ /// assert_eq!(a.len(), 1);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn len(&self) -> usize { self.table.size() }
+
+ /// Returns true if the map contains no elements.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut a = HashMap::new();
+ /// assert!(a.is_empty());
+ /// a.insert(1, "a");
+ /// assert!(!a.is_empty());
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn is_empty(&self) -> bool { self.len() == 0 }
+
+ /// Clears the map, returning all key-value pairs as an iterator. Keeps the
+ /// allocated memory for reuse.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut a = HashMap::new();
+ /// a.insert(1, "a");
+ /// a.insert(2, "b");
+ ///
+ /// for (k, v) in a.drain().take(1) {
+ /// assert!(k == 1 || k == 2);
+ /// assert!(v == "a" || v == "b");
+ /// }
+ ///
+ /// assert!(a.is_empty());
+ /// ```
+ #[inline]
+ #[unstable(feature = "std_misc",
+ reason = "matches collection reform specification, waiting for dust to settle")]
+ pub fn drain(&mut self) -> Drain<K, V> {
+ fn last_two<A, B, C>((_, b, c): (A, B, C)) -> (B, C) { (b, c) }
+ let last_two: fn((SafeHash, K, V)) -> (K, V) = last_two; // coerce to fn pointer
+
+ Drain {
+ inner: self.table.drain().map(last_two),
+ }
+ }
+
+ /// Clears the map, removing all key-value pairs. Keeps the allocated memory
+ /// for reuse.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut a = HashMap::new();
+ /// a.insert(1, "a");
+ /// a.clear();
+ /// assert!(a.is_empty());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ #[inline]
+ pub fn clear(&mut self) {
+ self.drain();
+ }
+
+ /// Returns a reference to the value corresponding to the key.
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// `Hash` and `Eq` on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut map = HashMap::new();
+ /// map.insert(1, "a");
+ /// assert_eq!(map.get(&1), Some(&"a"));
+ /// assert_eq!(map.get(&2), None);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
+ where K: Borrow<Q>, Q: Hash<H> + Eq
+ {
+ self.search(k).map(|bucket| bucket.into_refs().1)
+ }
+
+ /// Returns true if the map contains a value for the specified key.
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// `Hash` and `Eq` on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut map = HashMap::new();
+ /// map.insert(1, "a");
+ /// assert_eq!(map.contains_key(&1), true);
+ /// assert_eq!(map.contains_key(&2), false);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn contains_key<Q: ?Sized>(&self, k: &Q) -> bool
+ where K: Borrow<Q>, Q: Hash<H> + Eq
+ {
+ self.search(k).is_some()
+ }
+
+ /// Returns a mutable reference to the value corresponding to the key.
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// `Hash` and `Eq` on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut map = HashMap::new();
+ /// map.insert(1, "a");
+ /// match map.get_mut(&1) {
+ /// Some(x) => *x = "b",
+ /// None => (),
+ /// }
+ /// assert_eq!(map[1], "b");
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn get_mut<Q: ?Sized>(&mut self, k: &Q) -> Option<&mut V>
+ where K: Borrow<Q>, Q: Hash<H> + Eq
+ {
+ self.search_mut(k).map(|bucket| bucket.into_mut_refs().1)
+ }
+
+ /// Inserts a key-value pair from the map. If the key already had a value
+ /// present in the map, that value is returned. Otherwise, `None` is returned.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut map = HashMap::new();
+ /// assert_eq!(map.insert(37, "a"), None);
+ /// assert_eq!(map.is_empty(), false);
+ ///
+ /// map.insert(37, "b");
+ /// assert_eq!(map.insert(37, "c"), Some("b"));
+ /// assert_eq!(map[37], "c");
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn insert(&mut self, k: K, v: V) -> Option<V> {
+ let hash = self.make_hash(&k);
+ self.reserve(1);
+
+ let mut retval = None;
+ self.insert_or_replace_with(hash, k, v, |_, val_ref, val| {
+ retval = Some(replace(val_ref, val));
+ });
+ retval
+ }
+
+ /// Removes a key from the map, returning the value at the key if the key
+ /// was previously in the map.
+ ///
+ /// The key may be any borrowed form of the map's key type, but
+ /// `Hash` and `Eq` on the borrowed form *must* match those for
+ /// the key type.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashMap;
+ ///
+ /// let mut map = HashMap::new();
+ /// map.insert(1, "a");
+ /// assert_eq!(map.remove(&1), Some("a"));
+ /// assert_eq!(map.remove(&1), None);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
+ where K: Borrow<Q>, Q: Hash<H> + Eq
+ {
+ if self.table.size() == 0 {
+ return None
+ }
+
+ self.search_mut(k).map(|bucket| pop_internal(bucket).1)
+ }
+}
+
+fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHash, k: K)
+ -> Entry<'a, K, V>
+{
+ // Worst case, we'll find one empty bucket among `size + 1` buckets.
+ let size = table.size();
+ let mut probe = Bucket::new(table, hash);
+ let ib = probe.index();
+
+ loop {
+ let bucket = match probe.peek() {
+ Empty(bucket) => {
+ // Found a hole!
+ return Vacant(VacantEntry {
+ hash: hash,
+ key: k,
+ elem: NoElem(bucket),
+ });
+ },
+ Full(bucket) => bucket
+ };
+
+ // hash matches?
+ if bucket.hash() == hash {
+ // key matches?
+ if k == *bucket.read().0 {
+ return Occupied(OccupiedEntry{
+ elem: bucket,
+ });
+ }
+ }
+
+ let robin_ib = bucket.index() as int - bucket.distance() as int;
+
+ if (ib as int) < robin_ib {
+ // Found a luckier bucket than me. Better steal his spot.
+ return Vacant(VacantEntry {
+ hash: hash,
+ key: k,
+ elem: NeqElem(bucket, robin_ib as usize),
+ });
+ }
+
+ probe = bucket.next();
+ assert!(probe.index() != ib + size + 1);
+ }
+}
+
+impl<K, V, S, H> PartialEq for HashMap<K, V, S>
+ where K: Eq + Hash<H>, V: PartialEq,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ fn eq(&self, other: &HashMap<K, V, S>) -> bool {
+ if self.len() != other.len() { return false; }
+
+ self.iter().all(|(key, value)|
+ other.get(key).map_or(false, |v| *value == *v)
+ )
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<K, V, S, H> Eq for HashMap<K, V, S>
+ where K: Eq + Hash<H>, V: Eq,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<K, V, S, H> Debug for HashMap<K, V, S>
+ where K: Eq + Hash<H> + Debug, V: Debug,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ try!(write!(f, "HashMap {{"));
+
+ for (i, (k, v)) in self.iter().enumerate() {
+ if i != 0 { try!(write!(f, ", ")); }
+ try!(write!(f, "{:?}: {:?}", *k, *v));
+ }
+
+ write!(f, "}}")
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<K, V, S, H> Default for HashMap<K, V, S>
+ where K: Eq + Hash<H>,
+ S: HashState<Hasher=H> + Default,
+ H: hash::Hasher<Output=u64>
+{
+ fn default() -> HashMap<K, V, S> {
+ HashMap::with_hash_state(Default::default())
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<K, Q: ?Sized, V, S, H> Index<Q> for HashMap<K, V, S>
+ where K: Eq + Hash<H> + Borrow<Q>,
+ Q: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ type Output = V;
+
+ #[inline]
+ fn index<'a>(&'a self, index: &Q) -> &'a V {
+ self.get(index).expect("no entry found for key")
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<K, V, S, H, Q: ?Sized> IndexMut<Q> for HashMap<K, V, S>
+ where K: Eq + Hash<H> + Borrow<Q>,
+ Q: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ #[inline]
+ fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V {
+ self.get_mut(index).expect("no entry found for key")
+ }
+}
+
+/// HashMap iterator.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Iter<'a, K: 'a, V: 'a> {
+ inner: table::Iter<'a, K, V>
+}
+
+// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
+impl<'a, K, V> Clone for Iter<'a, K, V> {
+ fn clone(&self) -> Iter<'a, K, V> {
+ Iter {
+ inner: self.inner.clone()
+ }
+ }
+}
+
+/// HashMap mutable values iterator.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct IterMut<'a, K: 'a, V: 'a> {
+ inner: table::IterMut<'a, K, V>
+}
+
+/// HashMap move iterator.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct IntoIter<K, V> {
+ inner: iter::Map<table::IntoIter<K, V>, fn((SafeHash, K, V)) -> (K, V)>
+}
+
+/// HashMap keys iterator.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Keys<'a, K: 'a, V: 'a> {
+ inner: Map<Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
+}
+
+// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
+impl<'a, K, V> Clone for Keys<'a, K, V> {
+ fn clone(&self) -> Keys<'a, K, V> {
+ Keys {
+ inner: self.inner.clone()
+ }
+ }
+}
+
+/// HashMap values iterator.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Values<'a, K: 'a, V: 'a> {
+ inner: Map<Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
+}
+
+// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
+impl<'a, K, V> Clone for Values<'a, K, V> {
+ fn clone(&self) -> Values<'a, K, V> {
+ Values {
+ inner: self.inner.clone()
+ }
+ }
+}
+
+/// HashMap drain iterator.
+#[unstable(feature = "std_misc",
+ reason = "matches collection reform specification, waiting for dust to settle")]
+pub struct Drain<'a, K: 'a, V: 'a> {
+ inner: iter::Map<table::Drain<'a, K, V>, fn((SafeHash, K, V)) -> (K, V)>
+}
+
+/// A view into a single occupied location in a HashMap.
+#[unstable(feature = "std_misc",
+ reason = "precise API still being fleshed out")]
+pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
+ elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
+}
+
+/// A view into a single empty location in a HashMap.
+#[unstable(feature = "std_misc",
+ reason = "precise API still being fleshed out")]
+pub struct VacantEntry<'a, K: 'a, V: 'a> {
+ hash: SafeHash,
+ key: K,
+ elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>,
+}
+
+/// A view into a single location in a map, which may be vacant or occupied.
+#[unstable(feature = "std_misc",
+ reason = "precise API still being fleshed out")]
+pub enum Entry<'a, K: 'a, V: 'a> {
+ /// An occupied Entry.
+ Occupied(OccupiedEntry<'a, K, V>),
+ /// A vacant Entry.
+ Vacant(VacantEntry<'a, K, V>),
+}
+
+/// Possible states of a VacantEntry.
+enum VacantEntryState<K, V, M> {
+ /// The index is occupied, but the key to insert has precedence,
+ /// and will kick the current one out on insertion.
+ NeqElem(FullBucket<K, V, M>, usize),
+ /// The index is genuinely vacant.
+ NoElem(EmptyBucket<K, V, M>),
+}
+
+impl<'a, K, V, S, H> IntoIterator for &'a HashMap<K, V, S>
+ where K: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ type Item = (&'a K, &'a V);
+ type IntoIter = Iter<'a, K, V>;
+
+ fn into_iter(self) -> Iter<'a, K, V> {
+ self.iter()
+ }
+}
+
+impl<'a, K, V, S, H> IntoIterator for &'a mut HashMap<K, V, S>
+ where K: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ type Item = (&'a K, &'a mut V);
+ type IntoIter = IterMut<'a, K, V>;
+
+ fn into_iter(mut self) -> IterMut<'a, K, V> {
+ self.iter_mut()
+ }
+}
+
+impl<K, V, S, H> IntoIterator for HashMap<K, V, S>
+ where K: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ type Item = (K, V);
+ type IntoIter = IntoIter<K, V>;
+
+ fn into_iter(self) -> IntoIter<K, V> {
+ self.into_iter()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K, V> Iterator for Iter<'a, K, V> {
+ type Item = (&'a K, &'a V);
+
+ #[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() }
+ #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
+ #[inline] fn len(&self) -> usize { self.inner.len() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K, V> Iterator for IterMut<'a, K, V> {
+ type Item = (&'a K, &'a mut V);
+
+ #[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() }
+ #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
+ #[inline] fn len(&self) -> usize { self.inner.len() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<K, V> Iterator for IntoIter<K, V> {
+ type Item = (K, V);
+
+ #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
+ #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<K, V> ExactSizeIterator for IntoIter<K, V> {
+ #[inline] fn len(&self) -> usize { self.inner.len() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K, V> Iterator for Keys<'a, K, V> {
+ type Item = &'a K;
+
+ #[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
+ #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
+ #[inline] fn len(&self) -> usize { self.inner.len() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K, V> Iterator for Values<'a, K, V> {
+ type Item = &'a V;
+
+ #[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
+ #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
+ #[inline] fn len(&self) -> usize { self.inner.len() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K, V> Iterator for Drain<'a, K, V> {
+ type Item = (K, V);
+
+ #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
+ #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
+ #[inline] fn len(&self) -> usize { self.inner.len() }
+}
+
+#[unstable(feature = "std_misc",
+ reason = "matches collection reform v2 specification, waiting for dust to settle")]
+impl<'a, K, V> Entry<'a, K, V> {
+ /// Returns a mutable reference to the entry if occupied, or the VacantEntry if vacant.
+ pub fn get(self) -> Result<&'a mut V, VacantEntry<'a, K, V>> {
+ match self {
+ Occupied(entry) => Ok(entry.into_mut()),
+ Vacant(entry) => Err(entry),
+ }
+ }
+}
+
+impl<'a, K, V> OccupiedEntry<'a, K, V> {
+ /// Gets a reference to the value in the entry.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn get(&self) -> &V {
+ self.elem.read().1
+ }
+
+ /// Gets a mutable reference to the value in the entry.
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn get_mut(&mut self) -> &mut V {
+ self.elem.read_mut().1
+ }
+
+ /// Converts the OccupiedEntry into a mutable reference to the value in the entry
+ /// with a lifetime bound to the map itself
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn into_mut(self) -> &'a mut V {
+ self.elem.into_mut_refs().1
+ }
+
+ /// Sets the value of the entry, and returns the entry's old value
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn insert(&mut self, mut value: V) -> V {
+ let old_value = self.get_mut();
+ mem::swap(&mut value, old_value);
+ value
+ }
+
+ /// Takes the value out of the entry, and returns it
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn remove(self) -> V {
+ pop_internal(self.elem).1
+ }
+}
+
+impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
+ /// Sets the value of the entry with the VacantEntry's key,
+ /// and returns a mutable reference to it
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn insert(self, value: V) -> &'a mut V {
+ match self.elem {
+ NeqElem(bucket, ib) => {
+ robin_hood(bucket, ib, self.hash, self.key, value)
+ }
+ NoElem(bucket) => {
+ bucket.put(self.hash, self.key, value).into_mut_refs().1
+ }
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<K, V, S, H> FromIterator<(K, V)> for HashMap<K, V, S>
+ where K: Eq + Hash<H>,
+ S: HashState<Hasher=H> + Default,
+ H: hash::Hasher<Output=u64>
+{
+ fn from_iter<T: IntoIterator<Item=(K, V)>>(iter: T) -> HashMap<K, V, S> {
+ let iter = iter.into_iter();
+ let lower = iter.size_hint().0;
+ let mut map = HashMap::with_capacity_and_hash_state(lower,
+ Default::default());
+ map.extend(iter);
+ map
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<K, V, S, H> Extend<(K, V)> for HashMap<K, V, S>
+ where K: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) {
+ for (k, v) in iter {
+ self.insert(k, v);
+ }
+ }
+}
+
+
+/// `RandomState` is the default state for `HashMap` types.
+///
+/// A particular instance `RandomState` will create the same instances of
+/// `Hasher`, but the hashers created by two different `RandomState`
+/// instances are unlikely to produce the same result for the same values.
+#[derive(Clone)]
+#[unstable(feature = "std_misc",
+ reason = "hashing an hash maps may be altered")]
+pub struct RandomState {
+ k0: u64,
+ k1: u64,
+}
+
+#[unstable(feature = "std_misc",
+ reason = "hashing an hash maps may be altered")]
+impl RandomState {
+ /// Construct a new `RandomState` that is initialized with random keys.
+ #[inline]
+ #[allow(deprecated)]
+ pub fn new() -> RandomState {
+ let mut r = rand::thread_rng();
+ RandomState { k0: r.gen(), k1: r.gen() }
+ }
+}
+
+#[unstable(feature = "std_misc",
+ reason = "hashing an hash maps may be altered")]
+impl HashState for RandomState {
+ type Hasher = Hasher;
+ fn hasher(&self) -> Hasher {
+ Hasher { inner: SipHasher::new_with_keys(self.k0, self.k1) }
+ }
+}
+
+#[unstable(feature = "std_misc",
+ reason = "hashing an hash maps may be altered")]
+impl Default for RandomState {
+ #[inline]
+ fn default() -> RandomState {
+ RandomState::new()
+ }
+}
+
+/// A hasher implementation which is generated from `RandomState` instances.
+///
+/// This is the default hasher used in a `HashMap` to hash keys. Types do not
+/// typically declare an ability to explicitly hash into this particular type,
+/// but rather in a `H: hash::Writer` type parameter.
+#[unstable(feature = "std_misc",
+ reason = "hashing an hash maps may be altered")]
+pub struct Hasher { inner: SipHasher }
+
+impl hash::Writer for Hasher {
+ fn write(&mut self, data: &[u8]) {
+ hash::Writer::write(&mut self.inner, data)
+ }
+}
+
+impl hash::Hasher for Hasher {
+ type Output = u64;
+ fn reset(&mut self) { hash::Hasher::reset(&mut self.inner) }
+ fn finish(&self) -> u64 { self.inner.finish() }
+}
+
+#[cfg(test)]
+mod test_map {
+ use prelude::v1::*;
+
+ use super::HashMap;
+ use super::Entry::{Occupied, Vacant};
+ use iter::{range_inclusive, range_step_inclusive, repeat};
+ use cell::RefCell;
+ use rand::{weak_rng, Rng};
+
+ #[test]
+ fn test_create_capacity_zero() {
+ let mut m = HashMap::with_capacity(0);
+
+ assert!(m.insert(1, 1).is_none());
+
+ assert!(m.contains_key(&1));
+ assert!(!m.contains_key(&0));
+ }
+
+ #[test]
+ fn test_insert() {
+ let mut m = HashMap::new();
+ assert_eq!(m.len(), 0);
+ assert!(m.insert(1, 2).is_none());
+ assert_eq!(m.len(), 1);
+ assert!(m.insert(2, 4).is_none());
+ assert_eq!(m.len(), 2);
+ assert_eq!(*m.get(&1).unwrap(), 2);
+ assert_eq!(*m.get(&2).unwrap(), 4);
+ }
+
+ thread_local! { static DROP_VECTOR: RefCell<Vec<int>> = RefCell::new(Vec::new()) }
+
+ #[derive(Hash, PartialEq, Eq)]
+ struct Dropable {
+ k: usize
+ }
+
+ impl Dropable {
+ fn new(k: usize) -> Dropable {
+ DROP_VECTOR.with(|slot| {
+ slot.borrow_mut()[k] += 1;
+ });
+
+ Dropable { k: k }
+ }
+ }
+
+ impl Drop for Dropable {
+ fn drop(&mut self) {
+ DROP_VECTOR.with(|slot| {
+ slot.borrow_mut()[self.k] -= 1;
+ });
+ }
+ }
+
+ impl Clone for Dropable {
+ fn clone(&self) -> Dropable {
+ Dropable::new(self.k)
+ }
+ }
+
+ #[test]
+ fn test_drops() {
+ DROP_VECTOR.with(|slot| {
+ *slot.borrow_mut() = repeat(0).take(200).collect();
+ });
+
+ {
+ let mut m = HashMap::new();
+
+ DROP_VECTOR.with(|v| {
+ for i in 0..200 {
+ assert_eq!(v.borrow()[i], 0);
+ }
+ });
+
+ for i in 0..100 {
+ let d1 = Dropable::new(i);
+ let d2 = Dropable::new(i+100);
+ m.insert(d1, d2);
+ }
+
+ DROP_VECTOR.with(|v| {
+ for i in 0..200 {
+ assert_eq!(v.borrow()[i], 1);
+ }
+ });
+
+ for i in 0..50 {
+ let k = Dropable::new(i);
+ let v = m.remove(&k);
+
+ assert!(v.is_some());
+
+ DROP_VECTOR.with(|v| {
+ assert_eq!(v.borrow()[i], 1);
+ assert_eq!(v.borrow()[i+100], 1);
+ });
+ }
+
+ DROP_VECTOR.with(|v| {
+ for i in 0..50 {
+ assert_eq!(v.borrow()[i], 0);
+ assert_eq!(v.borrow()[i+100], 0);
+ }
+
+ for i in 50..100 {
+ assert_eq!(v.borrow()[i], 1);
+ assert_eq!(v.borrow()[i+100], 1);
+ }
+ });
+ }
+
+ DROP_VECTOR.with(|v| {
+ for i in 0..200 {
+ assert_eq!(v.borrow()[i], 0);
+ }
+ });
+ }
+
+ #[test]
+ fn test_move_iter_drops() {
+ DROP_VECTOR.with(|v| {
+ *v.borrow_mut() = repeat(0).take(200).collect();
+ });
+
+ let hm = {
+ let mut hm = HashMap::new();
+
+ DROP_VECTOR.with(|v| {
+ for i in 0..200 {
+ assert_eq!(v.borrow()[i], 0);
+ }
+ });
+
+ for i in 0..100 {
+ let d1 = Dropable::new(i);
+ let d2 = Dropable::new(i+100);
+ hm.insert(d1, d2);
+ }
+
+ DROP_VECTOR.with(|v| {
+ for i in 0..200 {
+ assert_eq!(v.borrow()[i], 1);
+ }
+ });
+
+ hm
+ };
+
+ // By the way, ensure that cloning doesn't screw up the dropping.
+ drop(hm.clone());
+
+ {
+ let mut half = hm.into_iter().take(50);
+
+ DROP_VECTOR.with(|v| {
+ for i in 0..200 {
+ assert_eq!(v.borrow()[i], 1);
+ }
+ });
+
+ for _ in half.by_ref() {}
+
+ DROP_VECTOR.with(|v| {
+ let nk = (0..100).filter(|&i| {
+ v.borrow()[i] == 1
+ }).count();
+
+ let nv = (0..100).filter(|&i| {
+ v.borrow()[i+100] == 1
+ }).count();
+
+ assert_eq!(nk, 50);
+ assert_eq!(nv, 50);
+ });
+ };
+
+ DROP_VECTOR.with(|v| {
+ for i in 0..200 {
+ assert_eq!(v.borrow()[i], 0);
+ }
+ });
+ }
+
+ #[test]
+ fn test_empty_pop() {
+ let mut m: HashMap<int, bool> = HashMap::new();
+ assert_eq!(m.remove(&0), None);
+ }
+
+ #[test]
+ fn test_lots_of_insertions() {
+ let mut m = HashMap::new();
+
+ // Try this a few times to make sure we never screw up the hashmap's
+ // internal state.
+ for _ in 0..10 {
+ assert!(m.is_empty());
+
+ for i in range_inclusive(1, 1000) {
+ assert!(m.insert(i, i).is_none());
+
+ for j in range_inclusive(1, i) {
+ let r = m.get(&j);
+ assert_eq!(r, Some(&j));
+ }
+
+ for j in range_inclusive(i+1, 1000) {
+ let r = m.get(&j);
+ assert_eq!(r, None);
+ }
+ }
+
+ for i in range_inclusive(1001, 2000) {
+ assert!(!m.contains_key(&i));
+ }
+
+ // remove forwards
+ for i in range_inclusive(1, 1000) {
+ assert!(m.remove(&i).is_some());
+
+ for j in range_inclusive(1, i) {
+ assert!(!m.contains_key(&j));
+ }
+
+ for j in range_inclusive(i+1, 1000) {
+ assert!(m.contains_key(&j));
+ }
+ }
+
+ for i in range_inclusive(1, 1000) {
+ assert!(!m.contains_key(&i));
+ }
+
+ for i in range_inclusive(1, 1000) {
+ assert!(m.insert(i, i).is_none());
+ }
+
+ // remove backwards
+ for i in range_step_inclusive(1000, 1, -1) {
+ assert!(m.remove(&i).is_some());
+
+ for j in range_inclusive(i, 1000) {
+ assert!(!m.contains_key(&j));
+ }
+
+ for j in range_inclusive(1, i-1) {
+ assert!(m.contains_key(&j));
+ }
+ }
+ }
+ }
+
+ #[test]
+ fn test_find_mut() {
+ let mut m = HashMap::new();
+ assert!(m.insert(1, 12).is_none());
+ assert!(m.insert(2, 8).is_none());
+ assert!(m.insert(5, 14).is_none());
+ let new = 100;
+ match m.get_mut(&5) {
+ None => panic!(), Some(x) => *x = new
+ }
+ assert_eq!(m.get(&5), Some(&new));
+ }
+
+ #[test]
+ fn test_insert_overwrite() {
+ let mut m = HashMap::new();
+ assert!(m.insert(1, 2).is_none());
+ assert_eq!(*m.get(&1).unwrap(), 2);
+ assert!(!m.insert(1, 3).is_none());
+ assert_eq!(*m.get(&1).unwrap(), 3);
+ }
+
+ #[test]
+ fn test_insert_conflicts() {
+ let mut m = HashMap::with_capacity(4);
+ assert!(m.insert(1, 2).is_none());
+ assert!(m.insert(5, 3).is_none());
+ assert!(m.insert(9, 4).is_none());
+ assert_eq!(*m.get(&9).unwrap(), 4);
+ assert_eq!(*m.get(&5).unwrap(), 3);
+ assert_eq!(*m.get(&1).unwrap(), 2);
+ }
+
+ #[test]
+ fn test_conflict_remove() {
+ let mut m = HashMap::with_capacity(4);
+ assert!(m.insert(1, 2).is_none());
+ assert_eq!(*m.get(&1).unwrap(), 2);
+ assert!(m.insert(5, 3).is_none());
+ assert_eq!(*m.get(&1).unwrap(), 2);
+ assert_eq!(*m.get(&5).unwrap(), 3);
+ assert!(m.insert(9, 4).is_none());
+ assert_eq!(*m.get(&1).unwrap(), 2);
+ assert_eq!(*m.get(&5).unwrap(), 3);
+ assert_eq!(*m.get(&9).unwrap(), 4);
+ assert!(m.remove(&1).is_some());
+ assert_eq!(*m.get(&9).unwrap(), 4);
+ assert_eq!(*m.get(&5).unwrap(), 3);
+ }
+
+ #[test]
+ fn test_is_empty() {
+ let mut m = HashMap::with_capacity(4);
+ assert!(m.insert(1, 2).is_none());
+ assert!(!m.is_empty());
+ assert!(m.remove(&1).is_some());
+ assert!(m.is_empty());
+ }
+
+ #[test]
+ fn test_pop() {
+ let mut m = HashMap::new();
+ m.insert(1, 2);
+ assert_eq!(m.remove(&1), Some(2));
+ assert_eq!(m.remove(&1), None);
+ }
+
+ #[test]
+ fn test_iterate() {
+ let mut m = HashMap::with_capacity(4);
+ for i in 0..32 {
+ assert!(m.insert(i, i*2).is_none());
+ }
+ assert_eq!(m.len(), 32);
+
+ let mut observed: u32 = 0;
+
+ for (k, v) in &m {
+ assert_eq!(*v, *k * 2);
+ observed |= 1 << *k;
+ }
+ assert_eq!(observed, 0xFFFF_FFFF);
+ }
+
+ #[test]
+ fn test_keys() {
+ let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
+ let map: HashMap<_, _> = vec.into_iter().collect();
+ let keys: Vec<_> = map.keys().cloned().collect();
+ assert_eq!(keys.len(), 3);
+ assert!(keys.contains(&1));
+ assert!(keys.contains(&2));
+ assert!(keys.contains(&3));
+ }
+
+ #[test]
+ fn test_values() {
+ let vec = vec![(1, 'a'), (2, 'b'), (3, 'c')];
+ let map: HashMap<_, _> = vec.into_iter().collect();
+ let values: Vec<_> = map.values().cloned().collect();
+ assert_eq!(values.len(), 3);
+ assert!(values.contains(&'a'));
+ assert!(values.contains(&'b'));
+ assert!(values.contains(&'c'));
+ }
+
+ #[test]
+ fn test_find() {
+ let mut m = HashMap::new();
+ assert!(m.get(&1).is_none());
+ m.insert(1, 2);
+ match m.get(&1) {
+ None => panic!(),
+ Some(v) => assert_eq!(*v, 2)
+ }
+ }
+
+ #[test]
+ fn test_eq() {
+ let mut m1 = HashMap::new();
+ m1.insert(1, 2);
+ m1.insert(2, 3);
+ m1.insert(3, 4);
+
+ let mut m2 = HashMap::new();
+ m2.insert(1, 2);
+ m2.insert(2, 3);
+
+ assert!(m1 != m2);
+
+ m2.insert(3, 4);
+
+ assert_eq!(m1, m2);
+ }
+
+ #[test]
+ fn test_show() {
+ let mut map = HashMap::new();
+ let empty: HashMap<i32, i32> = HashMap::new();
+
+ map.insert(1, 2);
+ map.insert(3, 4);
+
+ let map_str = format!("{:?}", map);
+
+ assert!(map_str == "HashMap {1: 2, 3: 4}" ||
+ map_str == "HashMap {3: 4, 1: 2}");
+ assert_eq!(format!("{:?}", empty), "HashMap {}");
+ }
+
+ #[test]
+ fn test_expand() {
+ let mut m = HashMap::new();
+
+ assert_eq!(m.len(), 0);
+ assert!(m.is_empty());
+
+ let mut i = 0;
+ let old_cap = m.table.capacity();
+ while old_cap == m.table.capacity() {
+ m.insert(i, i);
+ i += 1;
+ }
+
+ assert_eq!(m.len(), i);
+ assert!(!m.is_empty());
+ }
+
+ #[test]
+ fn test_behavior_resize_policy() {
+ let mut m = HashMap::new();
+
+ assert_eq!(m.len(), 0);
+ assert_eq!(m.table.capacity(), 0);
+ assert!(m.is_empty());
+
+ m.insert(0, 0);
+ m.remove(&0);
+ assert!(m.is_empty());
+ let initial_cap = m.table.capacity();
+ m.reserve(initial_cap);
+ let cap = m.table.capacity();
+
+ assert_eq!(cap, initial_cap * 2);
+
+ let mut i = 0;
+ for _ in 0..cap * 3 / 4 {
+ m.insert(i, i);
+ i += 1;
+ }
+ // three quarters full
+
+ assert_eq!(m.len(), i);
+ assert_eq!(m.table.capacity(), cap);
+
+ for _ in 0..cap / 4 {
+ m.insert(i, i);
+ i += 1;
+ }
+ // half full
+
+ let new_cap = m.table.capacity();
+ assert_eq!(new_cap, cap * 2);
+
+ for _ in 0..cap / 2 - 1 {
+ i -= 1;
+ m.remove(&i);
+ assert_eq!(m.table.capacity(), new_cap);
+ }
+ // A little more than one quarter full.
+ m.shrink_to_fit();
+ assert_eq!(m.table.capacity(), cap);
+ // again, a little more than half full
+ for _ in 0..cap / 2 - 1 {
+ i -= 1;
+ m.remove(&i);
+ }
+ m.shrink_to_fit();
+
+ assert_eq!(m.len(), i);
+ assert!(!m.is_empty());
+ assert_eq!(m.table.capacity(), initial_cap);
+ }
+
+ #[test]
+ fn test_reserve_shrink_to_fit() {
+ let mut m = HashMap::new();
+ m.insert(0, 0);
+ m.remove(&0);
+ assert!(m.capacity() >= m.len());
+ for i in 0..128 {
+ m.insert(i, i);
+ }
+ m.reserve(256);
+
+ let usable_cap = m.capacity();
+ for i in 128..(128 + 256) {
+ m.insert(i, i);
+ assert_eq!(m.capacity(), usable_cap);
+ }
+
+ for i in 100..(128 + 256) {
+ assert_eq!(m.remove(&i), Some(i));
+ }
+ m.shrink_to_fit();
+
+ assert_eq!(m.len(), 100);
+ assert!(!m.is_empty());
+ assert!(m.capacity() >= m.len());
+
+ for i in 0..100 {
+ assert_eq!(m.remove(&i), Some(i));
+ }
+ m.shrink_to_fit();
+ m.insert(0, 0);
+
+ assert_eq!(m.len(), 1);
+ assert!(m.capacity() >= m.len());
+ assert_eq!(m.remove(&0), Some(0));
+ }
+
+ #[test]
+ fn test_from_iter() {
+ let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+ let map: HashMap<_, _> = xs.iter().cloned().collect();
+
+ for &(k, v) in &xs {
+ assert_eq!(map.get(&k), Some(&v));
+ }
+ }
+
+ #[test]
+ fn test_size_hint() {
+ let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+ let map: HashMap<_, _> = xs.iter().cloned().collect();
+
+ let mut iter = map.iter();
+
+ for _ in iter.by_ref().take(3) {}
+
+ assert_eq!(iter.size_hint(), (3, Some(3)));
+ }
+
+ #[test]
+ fn test_iter_len() {
+ let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+ let map: HashMap<_, _> = xs.iter().cloned().collect();
+
+ let mut iter = map.iter();
+
+ for _ in iter.by_ref().take(3) {}
+
+ assert_eq!(iter.len(), 3);
+ }
+
+ #[test]
+ fn test_mut_size_hint() {
+ let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+ let mut map: HashMap<_, _> = xs.iter().cloned().collect();
+
+ let mut iter = map.iter_mut();
+
+ for _ in iter.by_ref().take(3) {}
+
+ assert_eq!(iter.size_hint(), (3, Some(3)));
+ }
+
+ #[test]
+ fn test_iter_mut_len() {
+ let xs = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+ let mut map: HashMap<_, _> = xs.iter().cloned().collect();
+
+ let mut iter = map.iter_mut();
+
+ for _ in iter.by_ref().take(3) {}
+
+ assert_eq!(iter.len(), 3);
+ }
+
+ #[test]
+ fn test_index() {
+ let mut map = HashMap::new();
+
+ map.insert(1, 2);
+ map.insert(2, 1);
+ map.insert(3, 4);
+
+ assert_eq!(map[2], 1);
+ }
+
+ #[test]
+ #[should_fail]
+ fn test_index_nonexistent() {
+ let mut map = HashMap::new();
+
+ map.insert(1, 2);
+ map.insert(2, 1);
+ map.insert(3, 4);
+
+ map[4];
+ }
+
+ #[test]
+ fn test_entry(){
+ let xs = [(1, 10), (2, 20), (3, 30), (4, 40), (5, 50), (6, 60)];
+
+ let mut map: HashMap<_, _> = xs.iter().cloned().collect();
+
+ // Existing key (insert)
+ match map.entry(1) {
+ Vacant(_) => unreachable!(),
+ Occupied(mut view) => {
+ assert_eq!(view.get(), &10);
+ assert_eq!(view.insert(100), 10);
+ }
+ }
+ assert_eq!(map.get(&1).unwrap(), &100);
+ assert_eq!(map.len(), 6);
+
+
+ // Existing key (update)
+ match map.entry(2) {
+ Vacant(_) => unreachable!(),
+ Occupied(mut view) => {
+ let v = view.get_mut();
+ let new_v = (*v) * 10;
+ *v = new_v;
+ }
+ }
+ assert_eq!(map.get(&2).unwrap(), &200);
+ assert_eq!(map.len(), 6);
+
+ // Existing key (take)
+ match map.entry(3) {
+ Vacant(_) => unreachable!(),
+ Occupied(view) => {
+ assert_eq!(view.remove(), 30);
+ }
+ }
+ assert_eq!(map.get(&3), None);
+ assert_eq!(map.len(), 5);
+
+
+ // Inexistent key (insert)
+ match map.entry(10) {
+ Occupied(_) => unreachable!(),
+ Vacant(view) => {
+ assert_eq!(*view.insert(1000), 1000);
+ }
+ }
+ assert_eq!(map.get(&10).unwrap(), &1000);
+ assert_eq!(map.len(), 6);
+ }
+
+ #[test]
+ fn test_entry_take_doesnt_corrupt() {
+ // Test for #19292
+ fn check(m: &HashMap<isize, ()>) {
+ for k in m.keys() {
+ assert!(m.contains_key(k),
+ "{} is in keys() but not in the map?", k);
+ }
+ }
+
+ let mut m = HashMap::new();
+ let mut rng = weak_rng();
+
+ // Populate the map with some items.
+ for _ in 0..50 {
+ let x = rng.gen_range(-10, 10);
+ m.insert(x, ());
+ }
+
+ for i in 0..1000 {
+ let x = rng.gen_range(-10, 10);
+ match m.entry(x) {
+ Vacant(_) => {},
+ Occupied(e) => {
+ println!("{}: remove {}", i, x);
+ e.remove();
+ },
+ }
+
+ check(&m);
+ }
+ }
+}
mod bench;
mod table;
+#[cfg(stage0)]
+#[path = "map_stage0.rs"]
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 state;
//
// ignore-lexer-test FIXME #15883
-use borrow::BorrowFrom;
+use borrow::Borrow;
use clone::Clone;
use cmp::{Eq, PartialEq};
use core::marker::Sized;
use default::Default;
use fmt::Debug;
use fmt;
-use hash::{self, Hash};
+use hash::Hash;
use iter::{
Iterator, IntoIterator, ExactSizeIterator, IteratorExt, FromIterator, Map, Chain, Extend,
};
use ops::{BitOr, BitAnd, BitXor, Sub};
use option::Option::{Some, None, self};
-use super::map::{self, HashMap, Keys, INITIAL_CAPACITY, RandomState, Hasher};
+use super::map::{self, HashMap, Keys, INITIAL_CAPACITY, RandomState};
use super::state::HashState;
// Future Optimization (FIXME!)
map: HashMap<T, (), S>
}
-impl<T: Hash<Hasher> + Eq> HashSet<T, RandomState> {
+impl<T: Hash + Eq> HashSet<T, RandomState> {
/// Create an empty HashSet.
///
/// # Example
}
}
-impl<T, S, H> HashSet<T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<T, S> HashSet<T, S>
+ where T: Eq + Hash, S: HashState
{
/// Creates a new empty hash set which will use the given hasher to hash
/// keys.
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
- where Q: BorrowFrom<T> + Hash<H> + Eq
+ where T: Borrow<Q>, Q: Hash + Eq
{
self.map.contains_key(value)
}
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
- where Q: BorrowFrom<T> + Hash<H> + Eq
+ where T: Borrow<Q>, Q: Hash + Eq
{
self.map.remove(value).is_some()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, S, H> PartialEq for HashSet<T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<T, S> PartialEq for HashSet<T, S>
+ where T: Eq + Hash, S: HashState
{
fn eq(&self, other: &HashSet<T, S>) -> bool {
if self.len() != other.len() { return false; }
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, S, H> Eq for HashSet<T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<T, S> Eq for HashSet<T, S>
+ where T: Eq + Hash, S: HashState
{}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, S, H> fmt::Debug for HashSet<T, S>
- where T: Eq + Hash<H> + fmt::Debug,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<T, S> fmt::Debug for HashSet<T, S>
+ where T: Eq + Hash + fmt::Debug,
+ S: HashState
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
try!(write!(f, "HashSet {{"));
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, S, H> FromIterator<T> for HashSet<T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H> + Default,
- H: hash::Hasher<Output=u64>
+impl<T, S> FromIterator<T> for HashSet<T, S>
+ where T: Eq + Hash,
+ S: HashState + Default,
{
- fn from_iter<I: Iterator<Item=T>>(iter: I) -> HashSet<T, S> {
+ fn from_iter<I: IntoIterator<Item=T>>(iterable: I) -> HashSet<T, S> {
+ let iter = iterable.into_iter();
let lower = iter.size_hint().0;
let mut set = HashSet::with_capacity_and_hash_state(lower, Default::default());
set.extend(iter);
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, S, H> Extend<T> for HashSet<T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<T, S> Extend<T> for HashSet<T, S>
+ where T: Eq + Hash,
+ S: HashState,
{
- fn extend<I: Iterator<Item=T>>(&mut self, iter: I) {
+ fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
for k in iter {
self.insert(k);
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, S, H> Default for HashSet<T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H> + Default,
- H: hash::Hasher<Output=u64>
+impl<T, S> Default for HashSet<T, S>
+ where T: Eq + Hash,
+ S: HashState + Default,
{
#[stable(feature = "rust1", since = "1.0.0")]
fn default() -> HashSet<T, S> {
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, T, S, H> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
- where T: Eq + Hash<H> + Clone,
- S: HashState<Hasher=H> + Default,
- H: hash::Hasher<Output=u64>
+impl<'a, 'b, T, S> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
+ where T: Eq + Hash + Clone,
+ S: HashState + Default,
{
type Output = HashSet<T, S>;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, T, S, H> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
- where T: Eq + Hash<H> + Clone,
- S: HashState<Hasher=H> + Default,
- H: hash::Hasher<Output=u64>
+impl<'a, 'b, T, S> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
+ where T: Eq + Hash + Clone,
+ S: HashState + Default,
{
type Output = HashSet<T, S>;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, T, S, H> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
- where T: Eq + Hash<H> + Clone,
- S: HashState<Hasher=H> + Default,
- H: hash::Hasher<Output=u64>
+impl<'a, 'b, T, S> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
+ where T: Eq + Hash + Clone,
+ S: HashState + Default,
{
type Output = HashSet<T, S>;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, 'b, T, S, H> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
- where T: Eq + Hash<H> + Clone,
- S: HashState<Hasher=H> + Default,
- H: hash::Hasher<Output=u64>
+impl<'a, 'b, T, S> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
+ where T: Eq + Hash + Clone,
+ S: HashState + Default,
{
type Output = HashSet<T, S>;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, S, H> IntoIterator for &'a HashSet<T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<'a, T, S> IntoIterator for &'a HashSet<T, S>
+ where T: Eq + Hash, S: HashState
{
type Item = &'a T;
type IntoIter = Iter<'a, T>;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T, S, H> IntoIterator for HashSet<T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<T, S> IntoIterator for HashSet<T, S>
+ where T: Eq + Hash,
+ S: HashState
{
type Item = T;
type IntoIter = IntoIter<T>;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, S, H> Iterator for Intersection<'a, T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<'a, T, S> Iterator for Intersection<'a, T, S>
+ where T: Eq + Hash, S: HashState
{
type Item = &'a T;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, S, H> Iterator for Difference<'a, T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<'a, T, S> Iterator for Difference<'a, T, S>
+ where T: Eq + Hash, S: HashState
{
type Item = &'a T;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S>
+ where T: Eq + Hash, S: HashState
{
type Item = &'a T;
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T, S, H> Iterator for Union<'a, T, S>
- where T: Eq + Hash<H>,
- S: HashState<Hasher=H>,
- H: hash::Hasher<Output=u64>
+impl<'a, T, S> Iterator for Union<'a, T, S>
+ where T: Eq + Hash, S: HashState
{
type Item = &'a T;
--- /dev/null
+// 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.
+//
+// ignore-lexer-test FIXME #15883
+
+use borrow::Borrow;
+use clone::Clone;
+use cmp::{Eq, PartialEq};
+use core::marker::Sized;
+use default::Default;
+use fmt::Debug;
+use fmt;
+use hash::{self, Hash};
+use iter::{
+ Iterator, IntoIterator, ExactSizeIterator, IteratorExt, FromIterator, Map, Chain, Extend,
+};
+use ops::{BitOr, BitAnd, BitXor, Sub};
+use option::Option::{Some, None, self};
+
+use super::map::{self, HashMap, Keys, INITIAL_CAPACITY, RandomState, Hasher};
+use super::state::HashState;
+
+// Future Optimization (FIXME!)
+// =============================
+//
+// Iteration over zero sized values is a noop. There is no need
+// for `bucket.val` in the case of HashSet. I suppose we would need HKT
+// to get rid of it properly.
+
+/// An implementation of a hash set using the underlying representation of a
+/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
+/// requires that the elements implement the `Eq` and `Hash` traits.
+///
+/// # Example
+///
+/// ```
+/// use std::collections::HashSet;
+/// // Type inference lets us omit an explicit type signature (which
+/// // would be `HashSet<&str>` in this example).
+/// let mut books = HashSet::new();
+///
+/// // Add some books.
+/// books.insert("A Dance With Dragons");
+/// books.insert("To Kill a Mockingbird");
+/// books.insert("The Odyssey");
+/// books.insert("The Great Gatsby");
+///
+/// // Check for a specific one.
+/// if !books.contains(&("The Winds of Winter")) {
+/// println!("We have {} books, but The Winds of Winter ain't one.",
+/// books.len());
+/// }
+///
+/// // Remove a book.
+/// books.remove(&"The Odyssey");
+///
+/// // Iterate over everything.
+/// for book in books.iter() {
+/// println!("{}", *book);
+/// }
+/// ```
+///
+/// The easiest way to use `HashSet` with a custom type is to derive
+/// `Eq` and `Hash`. We must also derive `PartialEq`, this will in the
+/// future be implied by `Eq`.
+///
+/// ```
+/// use std::collections::HashSet;
+/// #[derive(Hash, Eq, PartialEq, Debug)]
+/// struct Viking<'a> {
+/// name: &'a str,
+/// power: usize,
+/// }
+///
+/// let mut vikings = HashSet::new();
+///
+/// vikings.insert(Viking { name: "Einar", power: 9 });
+/// vikings.insert(Viking { name: "Einar", power: 9 });
+/// vikings.insert(Viking { name: "Olaf", power: 4 });
+/// vikings.insert(Viking { name: "Harald", power: 8 });
+///
+/// // Use derived implementation to print the vikings.
+/// for x in vikings.iter() {
+/// println!("{:?}", x);
+/// }
+/// ```
+#[derive(Clone)]
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct HashSet<T, S = RandomState> {
+ map: HashMap<T, (), S>
+}
+
+impl<T: Hash<Hasher> + Eq> HashSet<T, RandomState> {
+ /// Create an empty HashSet.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ /// let mut set: HashSet<int> = HashSet::new();
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn new() -> HashSet<T, RandomState> {
+ HashSet::with_capacity(INITIAL_CAPACITY)
+ }
+
+ /// Create an empty HashSet with space for at least `n` elements in
+ /// the hash table.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ /// let mut set: HashSet<int> = HashSet::with_capacity(10);
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn with_capacity(capacity: usize) -> HashSet<T, RandomState> {
+ HashSet { map: HashMap::with_capacity(capacity) }
+ }
+}
+
+impl<T, S, H> HashSet<T, S>
+ where T: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ /// Creates a new empty hash set which will use the given hasher to hash
+ /// keys.
+ ///
+ /// The hash set is also created with the default initial capacity.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ /// use std::collections::hash_map::RandomState;
+ ///
+ /// let s = RandomState::new();
+ /// let mut set = HashSet::with_hash_state(s);
+ /// set.insert(2);
+ /// ```
+ #[inline]
+ #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
+ pub fn with_hash_state(hash_state: S) -> HashSet<T, S> {
+ HashSet::with_capacity_and_hash_state(INITIAL_CAPACITY, hash_state)
+ }
+
+ /// Create an empty HashSet with space for at least `capacity`
+ /// elements in the hash table, using `hasher` to hash the keys.
+ ///
+ /// Warning: `hasher` is normally randomly generated, and
+ /// is designed to allow `HashSet`s to be resistant to attacks that
+ /// cause many collisions and very poor performance. Setting it
+ /// manually using this function can expose a DoS attack vector.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ /// use std::collections::hash_map::RandomState;
+ ///
+ /// let s = RandomState::new();
+ /// let mut set = HashSet::with_capacity_and_hash_state(10, s);
+ /// set.insert(1);
+ /// ```
+ #[inline]
+ #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
+ pub fn with_capacity_and_hash_state(capacity: usize, hash_state: S)
+ -> HashSet<T, S> {
+ HashSet {
+ map: HashMap::with_capacity_and_hash_state(capacity, hash_state),
+ }
+ }
+
+ /// Returns the number of elements the set can hold without reallocating.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ /// let set: HashSet<int> = HashSet::with_capacity(100);
+ /// assert!(set.capacity() >= 100);
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn capacity(&self) -> usize {
+ self.map.capacity()
+ }
+
+ /// Reserves capacity for at least `additional` more elements to be inserted
+ /// in the `HashSet`. The collection may reserve more space to avoid
+ /// frequent reallocations.
+ ///
+ /// # Panics
+ ///
+ /// Panics if the new allocation size overflows `usize`.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ /// let mut set: HashSet<int> = HashSet::new();
+ /// set.reserve(10);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn reserve(&mut self, additional: usize) {
+ self.map.reserve(additional)
+ }
+
+ /// Shrinks the capacity of the set as much as possible. It will drop
+ /// down as much as possible while maintaining the internal rules
+ /// and possibly leaving some space in accordance with the resize policy.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let mut set: HashSet<int> = HashSet::with_capacity(100);
+ /// set.insert(1);
+ /// set.insert(2);
+ /// assert!(set.capacity() >= 100);
+ /// set.shrink_to_fit();
+ /// assert!(set.capacity() >= 2);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn shrink_to_fit(&mut self) {
+ self.map.shrink_to_fit()
+ }
+
+ /// An iterator visiting all elements in arbitrary order.
+ /// Iterator element type is &'a T.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ /// let mut set = HashSet::new();
+ /// set.insert("a");
+ /// set.insert("b");
+ ///
+ /// // Will print in an arbitrary order.
+ /// for x in set.iter() {
+ /// println!("{}", x);
+ /// }
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn iter(&self) -> Iter<T> {
+ Iter { iter: self.map.keys() }
+ }
+
+ /// Creates a consuming iterator, that is, one that moves each value out
+ /// of the set in arbitrary order. The set cannot be used after calling
+ /// this.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ /// let mut set = HashSet::new();
+ /// set.insert("a".to_string());
+ /// set.insert("b".to_string());
+ ///
+ /// // Not possible to collect to a Vec<String> with a regular `.iter()`.
+ /// let v: Vec<String> = set.into_iter().collect();
+ ///
+ /// // Will print in an arbitrary order.
+ /// for x in v.iter() {
+ /// println!("{}", x);
+ /// }
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn into_iter(self) -> IntoIter<T> {
+ fn first<A, B>((a, _): (A, B)) -> A { a }
+ let first: fn((T, ())) -> T = first;
+
+ IntoIter { iter: self.map.into_iter().map(first) }
+ }
+
+ /// Visit the values representing the difference.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ /// let a: HashSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
+ /// let b: HashSet<int> = [4, 2, 3, 4].iter().map(|&x| x).collect();
+ ///
+ /// // Can be seen as `a - b`.
+ /// for x in a.difference(&b) {
+ /// println!("{}", x); // Print 1
+ /// }
+ ///
+ /// let diff: HashSet<int> = a.difference(&b).map(|&x| x).collect();
+ /// assert_eq!(diff, [1].iter().map(|&x| x).collect());
+ ///
+ /// // Note that difference is not symmetric,
+ /// // and `b - a` means something else:
+ /// let diff: HashSet<int> = b.difference(&a).map(|&x| x).collect();
+ /// assert_eq!(diff, [4].iter().map(|&x| x).collect());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S> {
+ Difference {
+ iter: self.iter(),
+ other: other,
+ }
+ }
+
+ /// Visit the values representing the symmetric difference.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ /// let a: HashSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
+ /// let b: HashSet<int> = [4, 2, 3, 4].iter().map(|&x| x).collect();
+ ///
+ /// // Print 1, 4 in arbitrary order.
+ /// for x in a.symmetric_difference(&b) {
+ /// println!("{}", x);
+ /// }
+ ///
+ /// let diff1: HashSet<int> = a.symmetric_difference(&b).map(|&x| x).collect();
+ /// let diff2: HashSet<int> = b.symmetric_difference(&a).map(|&x| x).collect();
+ ///
+ /// assert_eq!(diff1, diff2);
+ /// assert_eq!(diff1, [1, 4].iter().map(|&x| x).collect());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, S>)
+ -> SymmetricDifference<'a, T, S> {
+ SymmetricDifference { iter: self.difference(other).chain(other.difference(self)) }
+ }
+
+ /// Visit the values representing the intersection.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ /// let a: HashSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
+ /// let b: HashSet<int> = [4, 2, 3, 4].iter().map(|&x| x).collect();
+ ///
+ /// // Print 2, 3 in arbitrary order.
+ /// for x in a.intersection(&b) {
+ /// println!("{}", x);
+ /// }
+ ///
+ /// let diff: HashSet<int> = a.intersection(&b).map(|&x| x).collect();
+ /// assert_eq!(diff, [2, 3].iter().map(|&x| x).collect());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a, T, S> {
+ Intersection {
+ iter: self.iter(),
+ other: other,
+ }
+ }
+
+ /// Visit the values representing the union.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ /// let a: HashSet<int> = [1, 2, 3].iter().map(|&x| x).collect();
+ /// let b: HashSet<int> = [4, 2, 3, 4].iter().map(|&x| x).collect();
+ ///
+ /// // Print 1, 2, 3, 4 in arbitrary order.
+ /// for x in a.union(&b) {
+ /// println!("{}", x);
+ /// }
+ ///
+ /// let diff: HashSet<int> = a.union(&b).map(|&x| x).collect();
+ /// assert_eq!(diff, [1, 2, 3, 4].iter().map(|&x| x).collect());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn union<'a>(&'a self, other: &'a HashSet<T, S>) -> Union<'a, T, S> {
+ Union { iter: self.iter().chain(other.difference(self)) }
+ }
+
+ /// Return the number of elements in the set
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let mut v = HashSet::new();
+ /// assert_eq!(v.len(), 0);
+ /// v.insert(1);
+ /// assert_eq!(v.len(), 1);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn len(&self) -> usize { self.map.len() }
+
+ /// Returns true if the set contains no elements
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let mut v = HashSet::new();
+ /// assert!(v.is_empty());
+ /// v.insert(1);
+ /// assert!(!v.is_empty());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn is_empty(&self) -> bool { self.map.len() == 0 }
+
+ /// Clears the set, returning all elements in an iterator.
+ #[inline]
+ #[unstable(feature = "std_misc",
+ reason = "matches collection reform specification, waiting for dust to settle")]
+ pub fn drain(&mut self) -> Drain<T> {
+ fn first<A, B>((a, _): (A, B)) -> A { a }
+ let first: fn((T, ())) -> T = first; // coerce to fn pointer
+
+ Drain { iter: self.map.drain().map(first) }
+ }
+
+ /// Clears the set, removing all values.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let mut v = HashSet::new();
+ /// v.insert(1);
+ /// v.clear();
+ /// assert!(v.is_empty());
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn clear(&mut self) { self.map.clear() }
+
+ /// Returns `true` if the set contains a value.
+ ///
+ /// The value may be any borrowed form of the set's value type, but
+ /// `Hash` and `Eq` on the borrowed form *must* match those for
+ /// the value type.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let set: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// assert_eq!(set.contains(&1), true);
+ /// assert_eq!(set.contains(&4), false);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool
+ where T: Borrow<Q>, Q: Hash<H> + Eq
+ {
+ self.map.contains_key(value)
+ }
+
+ /// Returns `true` if the set has no elements in common with `other`.
+ /// This is equivalent to checking for an empty intersection.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let a: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let mut b = HashSet::new();
+ ///
+ /// assert_eq!(a.is_disjoint(&b), true);
+ /// b.insert(4);
+ /// assert_eq!(a.is_disjoint(&b), true);
+ /// b.insert(1);
+ /// assert_eq!(a.is_disjoint(&b), false);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn is_disjoint(&self, other: &HashSet<T, S>) -> bool {
+ self.iter().all(|v| !other.contains(v))
+ }
+
+ /// Returns `true` if the set is a subset of another.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let sup: HashSet<_> = [1, 2, 3].iter().cloned().collect();
+ /// let mut set = HashSet::new();
+ ///
+ /// assert_eq!(set.is_subset(&sup), true);
+ /// set.insert(2);
+ /// assert_eq!(set.is_subset(&sup), true);
+ /// set.insert(4);
+ /// assert_eq!(set.is_subset(&sup), false);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn is_subset(&self, other: &HashSet<T, S>) -> bool {
+ self.iter().all(|v| other.contains(v))
+ }
+
+ /// Returns `true` if the set is a superset of another.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let sub: HashSet<_> = [1, 2].iter().cloned().collect();
+ /// let mut set = HashSet::new();
+ ///
+ /// assert_eq!(set.is_superset(&sub), false);
+ ///
+ /// set.insert(0);
+ /// set.insert(1);
+ /// assert_eq!(set.is_superset(&sub), false);
+ ///
+ /// set.insert(2);
+ /// assert_eq!(set.is_superset(&sub), true);
+ /// ```
+ #[inline]
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn is_superset(&self, other: &HashSet<T, S>) -> bool {
+ other.is_subset(self)
+ }
+
+ /// Adds a value to the set. Returns `true` if the value was not already
+ /// present in the set.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let mut set = HashSet::new();
+ ///
+ /// assert_eq!(set.insert(2), true);
+ /// assert_eq!(set.insert(2), false);
+ /// assert_eq!(set.len(), 1);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()).is_none() }
+
+ /// Removes a value from the set. Returns `true` if the value was
+ /// present in the set.
+ ///
+ /// The value may be any borrowed form of the set's value type, but
+ /// `Hash` and `Eq` on the borrowed form *must* match those for
+ /// the value type.
+ ///
+ /// # Example
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let mut set = HashSet::new();
+ ///
+ /// set.insert(2);
+ /// assert_eq!(set.remove(&2), true);
+ /// assert_eq!(set.remove(&2), false);
+ /// ```
+ #[stable(feature = "rust1", since = "1.0.0")]
+ pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
+ where T: Borrow<Q>, Q: Hash<H> + Eq
+ {
+ self.map.remove(value).is_some()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T, S, H> PartialEq for HashSet<T, S>
+ where T: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ fn eq(&self, other: &HashSet<T, S>) -> bool {
+ if self.len() != other.len() { return false; }
+
+ self.iter().all(|key| other.contains(key))
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T, S, H> Eq for HashSet<T, S>
+ where T: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T, S, H> fmt::Debug for HashSet<T, S>
+ where T: Eq + Hash<H> + fmt::Debug,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ try!(write!(f, "HashSet {{"));
+
+ for (i, x) in self.iter().enumerate() {
+ if i != 0 { try!(write!(f, ", ")); }
+ try!(write!(f, "{:?}", *x));
+ }
+
+ write!(f, "}}")
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T, S, H> FromIterator<T> for HashSet<T, S>
+ where T: Eq + Hash<H>,
+ S: HashState<Hasher=H> + Default,
+ H: hash::Hasher<Output=u64>
+{
+ fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> HashSet<T, S> {
+ let iter = iter.into_iter();
+ let lower = iter.size_hint().0;
+ let mut set = HashSet::with_capacity_and_hash_state(lower, Default::default());
+ set.extend(iter);
+ set
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T, S, H> Extend<T> for HashSet<T, S>
+ where T: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
+ for k in iter {
+ self.insert(k);
+ }
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T, S, H> Default for HashSet<T, S>
+ where T: Eq + Hash<H>,
+ S: HashState<Hasher=H> + Default,
+ H: hash::Hasher<Output=u64>
+{
+ #[stable(feature = "rust1", since = "1.0.0")]
+ fn default() -> HashSet<T, S> {
+ HashSet::with_hash_state(Default::default())
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b, T, S, H> BitOr<&'b HashSet<T, S>> for &'a HashSet<T, S>
+ where T: Eq + Hash<H> + Clone,
+ S: HashState<Hasher=H> + Default,
+ H: hash::Hasher<Output=u64>
+{
+ type Output = HashSet<T, S>;
+
+ /// Returns the union of `self` and `rhs` as a new `HashSet<T, S>`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
+ /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
+ ///
+ /// let set = &a | &b;
+ ///
+ /// let mut i = 0;
+ /// let expected = [1, 2, 3, 4, 5];
+ /// for x in set.iter() {
+ /// assert!(expected.contains(x));
+ /// i += 1;
+ /// }
+ /// assert_eq!(i, expected.len());
+ /// ```
+ fn bitor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
+ self.union(rhs).cloned().collect()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b, T, S, H> BitAnd<&'b HashSet<T, S>> for &'a HashSet<T, S>
+ where T: Eq + Hash<H> + Clone,
+ S: HashState<Hasher=H> + Default,
+ H: hash::Hasher<Output=u64>
+{
+ type Output = HashSet<T, S>;
+
+ /// Returns the intersection of `self` and `rhs` as a new `HashSet<T, S>`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
+ /// let b: HashSet<_> = vec![2, 3, 4].into_iter().collect();
+ ///
+ /// let set = &a & &b;
+ ///
+ /// let mut i = 0;
+ /// let expected = [2, 3];
+ /// for x in set.iter() {
+ /// assert!(expected.contains(x));
+ /// i += 1;
+ /// }
+ /// assert_eq!(i, expected.len());
+ /// ```
+ fn bitand(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
+ self.intersection(rhs).cloned().collect()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b, T, S, H> BitXor<&'b HashSet<T, S>> for &'a HashSet<T, S>
+ where T: Eq + Hash<H> + Clone,
+ S: HashState<Hasher=H> + Default,
+ H: hash::Hasher<Output=u64>
+{
+ type Output = HashSet<T, S>;
+
+ /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet<T, S>`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
+ /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
+ ///
+ /// let set = &a ^ &b;
+ ///
+ /// let mut i = 0;
+ /// let expected = [1, 2, 4, 5];
+ /// for x in set.iter() {
+ /// assert!(expected.contains(x));
+ /// i += 1;
+ /// }
+ /// assert_eq!(i, expected.len());
+ /// ```
+ fn bitxor(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
+ self.symmetric_difference(rhs).cloned().collect()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, 'b, T, S, H> Sub<&'b HashSet<T, S>> for &'a HashSet<T, S>
+ where T: Eq + Hash<H> + Clone,
+ S: HashState<Hasher=H> + Default,
+ H: hash::Hasher<Output=u64>
+{
+ type Output = HashSet<T, S>;
+
+ /// Returns the difference of `self` and `rhs` as a new `HashSet<T, S>`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// use std::collections::HashSet;
+ ///
+ /// let a: HashSet<_> = vec![1, 2, 3].into_iter().collect();
+ /// let b: HashSet<_> = vec![3, 4, 5].into_iter().collect();
+ ///
+ /// let set = &a - &b;
+ ///
+ /// let mut i = 0;
+ /// let expected = [1, 2];
+ /// for x in set.iter() {
+ /// assert!(expected.contains(x));
+ /// i += 1;
+ /// }
+ /// assert_eq!(i, expected.len());
+ /// ```
+ fn sub(self, rhs: &HashSet<T, S>) -> HashSet<T, S> {
+ self.difference(rhs).cloned().collect()
+ }
+}
+
+/// HashSet iterator
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Iter<'a, K: 'a> {
+ iter: Keys<'a, K, ()>
+}
+
+/// HashSet move iterator
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct IntoIter<K> {
+ iter: Map<map::IntoIter<K, ()>, fn((K, ())) -> K>
+}
+
+/// HashSet drain iterator
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Drain<'a, K: 'a> {
+ iter: Map<map::Drain<'a, K, ()>, fn((K, ())) -> K>,
+}
+
+/// Intersection iterator
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Intersection<'a, T: 'a, S: 'a> {
+ // iterator of the first set
+ iter: Iter<'a, T>,
+ // the second set
+ other: &'a HashSet<T, S>,
+}
+
+/// Difference iterator
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Difference<'a, T: 'a, S: 'a> {
+ // iterator of the first set
+ iter: Iter<'a, T>,
+ // the second set
+ other: &'a HashSet<T, S>,
+}
+
+/// Symmetric difference iterator.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct SymmetricDifference<'a, T: 'a, S: 'a> {
+ iter: Chain<Difference<'a, T, S>, Difference<'a, T, S>>
+}
+
+/// Set union iterator.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Union<'a, T: 'a, S: 'a> {
+ iter: Chain<Iter<'a, T>, Difference<'a, T, S>>
+}
+
+impl<'a, T, S, H> IntoIterator for &'a HashSet<T, S>
+ where T: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ type Item = &'a T;
+ type IntoIter = Iter<'a, T>;
+
+ fn into_iter(self) -> Iter<'a, T> {
+ self.iter()
+ }
+}
+
+impl<T, S, H> IntoIterator for HashSet<T, S>
+ where T: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ type Item = T;
+ type IntoIter = IntoIter<T>;
+
+ fn into_iter(self) -> IntoIter<T> {
+ self.into_iter()
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K> Iterator for Iter<'a, K> {
+ type Item = &'a K;
+
+ fn next(&mut self) -> Option<&'a K> { self.iter.next() }
+ fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K> ExactSizeIterator for Iter<'a, K> {
+ fn len(&self) -> usize { self.iter.len() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<K> Iterator for IntoIter<K> {
+ type Item = K;
+
+ fn next(&mut self) -> Option<K> { self.iter.next() }
+ fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<K> ExactSizeIterator for IntoIter<K> {
+ fn len(&self) -> usize { self.iter.len() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K> Iterator for Drain<'a, K> {
+ type Item = K;
+
+ fn next(&mut self) -> Option<K> { self.iter.next() }
+ fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, K> ExactSizeIterator for Drain<'a, K> {
+ fn len(&self) -> usize { self.iter.len() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T, S, H> Iterator for Intersection<'a, T, S>
+ where T: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<&'a T> {
+ loop {
+ match self.iter.next() {
+ None => return None,
+ Some(elt) => if self.other.contains(elt) {
+ return Some(elt)
+ },
+ }
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let (_, upper) = self.iter.size_hint();
+ (0, upper)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T, S, H> Iterator for Difference<'a, T, S>
+ where T: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<&'a T> {
+ loop {
+ match self.iter.next() {
+ None => return None,
+ Some(elt) => if !self.other.contains(elt) {
+ return Some(elt)
+ },
+ }
+ }
+ }
+
+ fn size_hint(&self) -> (usize, Option<usize>) {
+ let (_, upper) = self.iter.size_hint();
+ (0, upper)
+ }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, S>
+ where T: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<&'a T> { self.iter.next() }
+ fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T, S, H> Iterator for Union<'a, T, S>
+ where T: Eq + Hash<H>,
+ S: HashState<Hasher=H>,
+ H: hash::Hasher<Output=u64>
+{
+ type Item = &'a T;
+
+ fn next(&mut self) -> Option<&'a T> { self.iter.next() }
+ fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+
+#[cfg(test)]
+mod test_set {
+ use prelude::v1::*;
+
+ use super::HashSet;
+
+ #[test]
+ fn test_disjoint() {
+ let mut xs = HashSet::new();
+ let mut ys = HashSet::new();
+ assert!(xs.is_disjoint(&ys));
+ assert!(ys.is_disjoint(&xs));
+ assert!(xs.insert(5));
+ assert!(ys.insert(11));
+ assert!(xs.is_disjoint(&ys));
+ assert!(ys.is_disjoint(&xs));
+ assert!(xs.insert(7));
+ assert!(xs.insert(19));
+ assert!(xs.insert(4));
+ assert!(ys.insert(2));
+ assert!(ys.insert(-11));
+ assert!(xs.is_disjoint(&ys));
+ assert!(ys.is_disjoint(&xs));
+ assert!(ys.insert(7));
+ assert!(!xs.is_disjoint(&ys));
+ assert!(!ys.is_disjoint(&xs));
+ }
+
+ #[test]
+ fn test_subset_and_superset() {
+ let mut a = HashSet::new();
+ assert!(a.insert(0));
+ assert!(a.insert(5));
+ assert!(a.insert(11));
+ assert!(a.insert(7));
+
+ let mut b = HashSet::new();
+ assert!(b.insert(0));
+ assert!(b.insert(7));
+ assert!(b.insert(19));
+ assert!(b.insert(250));
+ assert!(b.insert(11));
+ assert!(b.insert(200));
+
+ assert!(!a.is_subset(&b));
+ assert!(!a.is_superset(&b));
+ assert!(!b.is_subset(&a));
+ assert!(!b.is_superset(&a));
+
+ assert!(b.insert(5));
+
+ assert!(a.is_subset(&b));
+ assert!(!a.is_superset(&b));
+ assert!(!b.is_subset(&a));
+ assert!(b.is_superset(&a));
+ }
+
+ #[test]
+ fn test_iterate() {
+ let mut a = HashSet::new();
+ for i in 0..32 {
+ assert!(a.insert(i));
+ }
+ let mut observed: u32 = 0;
+ for k in &a {
+ observed |= 1 << *k;
+ }
+ assert_eq!(observed, 0xFFFF_FFFF);
+ }
+
+ #[test]
+ fn test_intersection() {
+ let mut a = HashSet::new();
+ let mut b = HashSet::new();
+
+ assert!(a.insert(11));
+ assert!(a.insert(1));
+ assert!(a.insert(3));
+ assert!(a.insert(77));
+ assert!(a.insert(103));
+ assert!(a.insert(5));
+ assert!(a.insert(-5));
+
+ assert!(b.insert(2));
+ assert!(b.insert(11));
+ assert!(b.insert(77));
+ assert!(b.insert(-9));
+ assert!(b.insert(-42));
+ assert!(b.insert(5));
+ assert!(b.insert(3));
+
+ let mut i = 0;
+ let expected = [3, 5, 11, 77];
+ for x in a.intersection(&b) {
+ assert!(expected.contains(x));
+ i += 1
+ }
+ assert_eq!(i, expected.len());
+ }
+
+ #[test]
+ fn test_difference() {
+ let mut a = HashSet::new();
+ let mut b = HashSet::new();
+
+ assert!(a.insert(1));
+ assert!(a.insert(3));
+ assert!(a.insert(5));
+ assert!(a.insert(9));
+ assert!(a.insert(11));
+
+ assert!(b.insert(3));
+ assert!(b.insert(9));
+
+ let mut i = 0;
+ let expected = [1, 5, 11];
+ for x in a.difference(&b) {
+ assert!(expected.contains(x));
+ i += 1
+ }
+ assert_eq!(i, expected.len());
+ }
+
+ #[test]
+ fn test_symmetric_difference() {
+ let mut a = HashSet::new();
+ let mut b = HashSet::new();
+
+ assert!(a.insert(1));
+ assert!(a.insert(3));
+ assert!(a.insert(5));
+ assert!(a.insert(9));
+ assert!(a.insert(11));
+
+ assert!(b.insert(-2));
+ assert!(b.insert(3));
+ assert!(b.insert(9));
+ assert!(b.insert(14));
+ assert!(b.insert(22));
+
+ let mut i = 0;
+ let expected = [-2, 1, 5, 11, 14, 22];
+ for x in a.symmetric_difference(&b) {
+ assert!(expected.contains(x));
+ i += 1
+ }
+ assert_eq!(i, expected.len());
+ }
+
+ #[test]
+ fn test_union() {
+ let mut a = HashSet::new();
+ let mut b = HashSet::new();
+
+ assert!(a.insert(1));
+ assert!(a.insert(3));
+ assert!(a.insert(5));
+ assert!(a.insert(9));
+ assert!(a.insert(11));
+ assert!(a.insert(16));
+ assert!(a.insert(19));
+ assert!(a.insert(24));
+
+ assert!(b.insert(-2));
+ assert!(b.insert(1));
+ assert!(b.insert(5));
+ assert!(b.insert(9));
+ assert!(b.insert(13));
+ assert!(b.insert(19));
+
+ let mut i = 0;
+ let expected = [-2, 1, 3, 5, 9, 11, 13, 16, 19, 24];
+ for x in a.union(&b) {
+ assert!(expected.contains(x));
+ i += 1
+ }
+ assert_eq!(i, expected.len());
+ }
+
+ #[test]
+ fn test_from_iter() {
+ let xs = [1, 2, 3, 4, 5, 6, 7, 8, 9];
+
+ let set: HashSet<_> = xs.iter().cloned().collect();
+
+ for x in &xs {
+ assert!(set.contains(x));
+ }
+ }
+
+ #[test]
+ fn test_move_iter() {
+ let hs = {
+ let mut hs = HashSet::new();
+
+ hs.insert('a');
+ hs.insert('b');
+
+ hs
+ };
+
+ let v = hs.into_iter().collect::<Vec<char>>();
+ assert!(['a', 'b'] == v || ['b', 'a'] == v);
+ }
+
+ #[test]
+ fn test_eq() {
+ // These constants once happened to expose a bug in insert().
+ // I'm keeping them around to prevent a regression.
+ let mut s1 = HashSet::new();
+
+ s1.insert(1);
+ s1.insert(2);
+ s1.insert(3);
+
+ let mut s2 = HashSet::new();
+
+ s2.insert(1);
+ s2.insert(2);
+
+ assert!(s1 != s2);
+
+ s2.insert(3);
+
+ assert_eq!(s1, s2);
+ }
+
+ #[test]
+ fn test_show() {
+ let mut set = HashSet::new();
+ let empty = HashSet::<i32>::new();
+
+ set.insert(1);
+ set.insert(2);
+
+ let set_str = format!("{:?}", set);
+
+ assert!(set_str == "HashSet {1, 2}" || set_str == "HashSet {2, 1}");
+ assert_eq!(format!("{:?}", empty), "HashSet {}");
+ }
+
+ #[test]
+ fn test_trivial_drain() {
+ let mut s = HashSet::<i32>::new();
+ for _ in s.drain() {}
+ assert!(s.is_empty());
+ drop(s);
+
+ let mut s = HashSet::<i32>::new();
+ drop(s.drain());
+ assert!(s.is_empty());
+ }
+
+ #[test]
+ fn test_drain() {
+ let mut s: HashSet<_> = (1..100).collect();
+
+ // try this a bunch of times to make sure we don't screw up internal state.
+ for _ in 0..20 {
+ assert_eq!(s.len(), 99);
+
+ {
+ let mut last_i = 0;
+ let mut d = s.drain();
+ for (i, x) in d.by_ref().take(50).enumerate() {
+ last_i = i;
+ assert!(x != 0);
+ }
+ assert_eq!(last_i, 49);
+ }
+
+ for _ in &s { panic!("s should be empty!"); }
+
+ // reset to try again.
+ s.extend(1..100);
+ }
+ }
+}
use clone::Clone;
use default::Default;
use hash;
+use marker;
/// A trait representing stateful hashes which can be used to hash keys in a
/// `HashMap`.
///
/// This struct has is 0-sized and does not need construction.
#[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
-pub struct DefaultState<H>;
+pub struct DefaultState<H>(marker::PhantomData<H>);
impl<H: Default + hash::Hasher> HashState for DefaultState<H> {
type Hasher = H;
}
impl<H> Clone for DefaultState<H> {
- fn clone(&self) -> DefaultState<H> { DefaultState }
+ fn clone(&self) -> DefaultState<H> { DefaultState(marker::PhantomData) }
}
impl<H> Default for DefaultState<H> {
- fn default() -> DefaultState<H> { DefaultState }
+ fn default() -> DefaultState<H> { DefaultState(marker::PhantomData) }
}
use ops::{Deref, DerefMut, Drop};
use option::Option;
use option::Option::{Some, None};
-use ptr::{self, PtrExt, copy_nonoverlapping_memory, zero_memory};
-use rt::heap::{allocate, deallocate};
+use ptr::{self, PtrExt, copy_nonoverlapping_memory, Unique, zero_memory};
+use rt::heap::{allocate, deallocate, EMPTY};
use collections::hash_state::HashState;
const EMPTY_BUCKET: u64 = 0u64;
pub struct RawTable<K, V> {
capacity: usize,
size: usize,
- hashes: *mut u64,
+ hashes: Unique<u64>,
+
// Because K/V do not appear directly in any of the types in the struct,
// inform rustc that in fact instances of K and V are reachable from here.
- marker: marker::CovariantType<(K,V)>,
+ marker: marker::PhantomData<(K,V)>,
}
unsafe impl<K: Send, V: Send> Send for RawTable<K, V> {}
struct RawBucket<K, V> {
hash: *mut u64,
key: *mut K,
- val: *mut V
+ val: *mut V,
+ _marker: marker::PhantomData<(K,V)>,
}
impl<K,V> Copy for RawBucket<K,V> {}
/// 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(stage0)]
pub fn make_hash<T: ?Sized, S, H>(hash_state: &S, t: &T) -> SafeHash
where T: Hash<H>,
S: HashState<Hasher=H>,
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
+ where T: Hash, S: HashState
+{
+ 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() }
+}
+
// `replace` casts a `*u64` to a `*SafeHash`. Since we statically
// ensure that a `FullBucket` points to an index with a non-zero hash,
// and a `SafeHash` is just a `u64` with a different name, this is
}
impl<K, V> RawBucket<K, V> {
- unsafe fn offset(self, count: int) -> RawBucket<K, V> {
+ unsafe fn offset(self, count: isize) -> RawBucket<K, V> {
RawBucket {
hash: self.hash.offset(count),
key: self.key.offset(count),
val: self.val.offset(count),
+ _marker: marker::PhantomData,
}
}
}
return RawTable {
size: 0,
capacity: 0,
- hashes: ptr::null_mut(),
- marker: marker::CovariantType,
+ hashes: Unique::new(EMPTY as *mut u64),
+ marker: marker::PhantomData,
};
}
+
// No need for `checked_mul` before a more restrictive check performed
// later in this method.
let hashes_size = capacity * size_of::<u64>();
RawTable {
capacity: capacity,
size: 0,
- hashes: hashes,
- marker: marker::CovariantType,
+ hashes: Unique::new(hashes),
+ marker: marker::PhantomData,
}
}
let hashes_size = self.capacity * size_of::<u64>();
let keys_size = self.capacity * size_of::<K>();
- let buffer = self.hashes as *mut u8;
+ let buffer = *self.hashes as *mut u8;
let (keys_offset, vals_offset) = calculate_offsets(hashes_size,
keys_size, min_align_of::<K>(),
min_align_of::<V>());
unsafe {
RawBucket {
- hash: self.hashes,
+ hash: *self.hashes,
key: buffer.offset(keys_offset as isize) as *mut K,
- val: buffer.offset(vals_offset as isize) as *mut V
+ val: buffer.offset(vals_offset as isize) as *mut V,
+ _marker: marker::PhantomData,
}
}
}
pub fn new(capacity: usize) -> RawTable<K, V> {
unsafe {
let ret = RawTable::new_uninitialized(capacity);
- zero_memory(ret.hashes, capacity);
+ zero_memory(*ret.hashes, capacity);
ret
}
}
hashes_end: unsafe {
self.hashes.offset(self.capacity as isize)
},
- marker: marker::ContravariantLifetime,
+ marker: marker::PhantomData,
}
}
iter: RawBuckets {
raw: raw,
hashes_end: hashes_end,
- marker: marker::ContravariantLifetime,
+ marker: marker::PhantomData,
},
table: self,
}
iter: RawBuckets {
raw: raw,
hashes_end: hashes_end,
- marker: marker::ContravariantLifetime::<'static>,
+ marker: marker::PhantomData,
},
table: self,
}
raw: raw_bucket.offset(self.capacity as isize),
hashes_end: raw_bucket.hash,
elems_left: self.size,
- marker: marker::ContravariantLifetime,
+ marker: marker::PhantomData,
}
}
}
struct RawBuckets<'a, K, V> {
raw: RawBucket<K, V>,
hashes_end: *mut u64,
- marker: marker::ContravariantLifetime<'a>,
+
+ // Strictly speaking, this should be &'a (K,V), but that would
+ // require that K:'a, and we often use RawBuckets<'static...> for
+ // move iterations, so that messes up a lot of other things. So
+ // just use `&'a (K,V)` as this is not a publicly exposed type
+ // anyway.
+ marker: marker::PhantomData<&'a ()>,
}
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
RawBuckets {
raw: self.raw,
hashes_end: self.hashes_end,
- marker: marker::ContravariantLifetime,
+ marker: marker::PhantomData,
}
}
}
raw: RawBucket<K, V>,
hashes_end: *mut u64,
elems_left: usize,
- marker: marker::ContravariantLifetime<'a>,
+
+ // As above, `&'a (K,V)` would seem better, but we often use
+ // 'static for the lifetime, and this is not a publicly exposed
+ // type.
+ marker: marker::PhantomData<&'a ()>,
}
impl<'a, K, V> Iterator for RevMoveBuckets<'a, K, V> {
#[unsafe_destructor]
impl<K, V> Drop for RawTable<K, V> {
fn drop(&mut self) {
- if self.hashes.is_null() {
+ if self.capacity == 0 {
return;
}
+
// This is done in reverse because we've likely partially taken
// some elements out with `.into_iter()` from the front.
// Check if the size is 0, so we don't do a useless scan when
vals_size, min_align_of::<V>());
unsafe {
- deallocate(self.hashes as *mut u8, size, align);
+ deallocate(*self.hashes as *mut u8, size, align);
// Remember how everything was allocated out of one buffer
// during initialization? We only need one call to free here.
}
//!
//! Rust's collections can be grouped into four major categories:
//!
-//! * Sequences: `Vec`, `RingBuf`, `DList`, `BitV`
+//! * Sequences: `Vec`, `VecDeque`, `LinkedList`, `BitV`
//! * Maps: `HashMap`, `BTreeMap`, `VecMap`
//! * Sets: `HashSet`, `BTreeSet`, `BitVSet`
//! * Misc: `BinaryHeap`
//! * You want a resizable array.
//! * You want a heap-allocated array.
//!
-//! ### Use a `RingBuf` when:
+//! ### Use a `VecDeque` when:
//! * You want a `Vec` that supports efficient insertion at both ends of the sequence.
//! * You want a queue.
//! * You want a double-ended queue (deque).
//!
-//! ### Use a `DList` when:
-//! * You want a `Vec` or `RingBuf` of unknown size, and can't tolerate amortization.
+//! ### Use a `LinkedList` when:
+//! * You want a `Vec` or `VecDeque` of unknown size, and can't tolerate amortization.
//! * You want to efficiently split and append lists.
//! * You are *absolutely* certain you *really*, *truly*, want a doubly linked list.
//!
//!
//! ### Use a `BitV` when:
//! * You want to store an unbounded number of booleans in a small space.
-//! * You want a bitvector.
+//! * You want a bit vector.
//!
//! ### Use a `BitVSet` when:
//! * You want a `VecSet`.
//!
//! ## Sequences
//!
-//! | | get(i) | insert(i) | remove(i) | append | split_off(i) |
-//! |---------|----------------|-----------------|----------------|--------|----------------|
-//! | Vec | O(1) | O(n-i)* | O(n-i) | O(m)* | O(n-i) |
-//! | RingBuf | O(1) | O(min(i, n-i))* | O(min(i, n-i)) | O(m)* | O(min(i, n-i)) |
-//! | DList | O(min(i, n-i)) | O(min(i, n-i)) | O(min(i, n-i)) | O(1) | O(min(i, n-i)) |
-//! | Bitv | O(1) | O(n-i)* | O(n-i) | O(m)* | O(n-i) |
+//! | | get(i) | insert(i) | remove(i) | append | split_off(i) |
+//! |--------------|----------------|-----------------|----------------|--------|----------------|
+//! | Vec | O(1) | O(n-i)* | O(n-i) | O(m)* | O(n-i) |
+//! | VecDeque | O(1) | O(min(i, n-i))* | O(min(i, n-i)) | O(m)* | O(min(i, n-i)) |
+//! | LinkedList | O(min(i, n-i)) | O(min(i, n-i)) | O(min(i, n-i)) | O(1) | O(min(i, n-i)) |
+//! | BitVec | O(1) | O(n-i)* | O(n-i) | O(m)* | O(n-i) |
//!
-//! Note that where ties occur, Vec is generally going to be faster than RingBuf, and RingBuf
-//! is generally going to be faster than DList. Bitv is not a general purpose collection, and
+//! Note that where ties occur, Vec is generally going to be faster than VecDeque, and VecDeque
+//! is generally going to be faster than LinkedList. BitVec is not a general purpose collection, and
//! therefore cannot reasonably be compared.
//!
//! ## Maps
//!
-//! For Sets, all operations have the cost of the equivalent Map operation. For BitvSet,
+//! For Sets, all operations have the cost of the equivalent Map operation. For BitSet,
//! refer to VecMap.
//!
//! | | get | insert | remove | predecessor |
//!
//! Any `with_capacity` constructor will instruct the collection to allocate enough space
//! for the specified number of elements. Ideally this will be for exactly that many
-//! elements, but some implementation details may prevent this. `Vec` and `RingBuf` can
+//! elements, but some implementation details may prevent this. `Vec` and `VecDeque` can
//! be relied on to allocate exactly the requested amount, though. Use `with_capacity`
//! when you know exactly how many elements will be inserted, or at least have a
//! reasonable upper-bound on that number.
//! ```
//!
//! ```
-//! use std::collections::RingBuf;
+//! use std::collections::VecDeque;
//!
//! let vec = vec![1, 2, 3, 4];
-//! let buf: RingBuf<_> = vec.into_iter().collect();
+//! let buf: VecDeque<_> = vec.into_iter().collect();
//! ```
//!
//! Iterators also provide a series of *adapter* methods for performing common tasks to
#![stable(feature = "rust1", since = "1.0.0")]
pub use core_collections::Bound;
-pub use core_collections::{BinaryHeap, Bitv, BitvSet, BTreeMap, BTreeSet};
-pub use core_collections::{DList, RingBuf, VecMap};
+pub use core_collections::{BinaryHeap, BitVec, BitSet, BTreeMap, BTreeSet};
+pub use core_collections::{LinkedList, VecDeque, VecMap};
-pub use core_collections::{binary_heap, bitv, bitv_set, btree_map, btree_set};
-pub use core_collections::{dlist, ring_buf, vec_map};
+pub use core_collections::{binary_heap, bit_vec, bit_set, btree_map, btree_set};
+pub use core_collections::{linked_list, vec_deque, vec_map};
pub use self::hash_map::HashMap;
pub use self::hash_set::HashSet;
// This function should have a lifetime constraint of 'a on
// T but that feature is still unimplemented
- let raw_string = CString::from_slice(symbol.as_bytes());
+ let raw_string = CString::new(symbol).unwrap();
let maybe_symbol_value = dl::check_for_errors_in(|| {
dl::symbol(self.handle, raw_string.as_ptr())
});
mod dl {
use prelude::v1::*;
- use ffi::{self, CString};
+ use ffi::{CString, CStr};
use str;
use libc;
use ptr;
const LAZY: libc::c_int = 1;
unsafe fn open_external(filename: &[u8]) -> *mut u8 {
- let s = CString::from_slice(filename);
+ let s = CString::new(filename).unwrap();
dlopen(s.as_ptr(), LAZY) as *mut u8
}
let ret = if ptr::null() == last_error {
Ok(result)
} else {
- let s = ffi::c_str_to_bytes(&last_error);
+ let s = CStr::from_ptr(last_error).to_bytes();
Err(str::from_utf8(s).unwrap().to_string())
};
#[cfg(unix)]
fn join_paths_unix() {
fn test_eq(input: &[&str], output: &str) -> bool {
- &*join_paths(input.iter().map(|s| *s)).unwrap() ==
+ &*join_paths(input.iter().cloned()).unwrap() ==
OsStr::from_str(output)
}
"/bin:/usr/bin:/usr/local/bin"));
assert!(test_eq(&["", "/bin", "", "", "/usr/bin", ""],
":/bin:::/usr/bin:"));
- assert!(join_paths(["/te:st"].iter().map(|s| *s)).is_err());
+ assert!(join_paths(["/te:st"].iter().cloned()).is_err());
}
#[test]
#[cfg(windows)]
fn join_paths_windows() {
fn test_eq(input: &[&str], output: &str) -> bool {
- &*join_paths(input.iter().map(|s| *s)).unwrap() ==
+ &*join_paths(input.iter().cloned()).unwrap() ==
OsStr::from_str(output)
}
r";c:\windows;;;c:\;"));
assert!(test_eq(&[r"c:\te;st", r"c:\"],
r#""c:\te;st";c:\"#));
- assert!(join_paths([r#"c:\te"st"#].iter().map(|s| *s)).is_err());
+ assert!(join_paths([r#"c:\te"st"#].iter().cloned()).is_err());
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
+use error::{Error, FromError};
use fmt;
+use io;
use iter::IteratorExt;
use libc;
use mem;
+use old_io;
use ops::Deref;
+use option::Option::{self, Some, None};
+use result::Result::{self, Ok, Err};
use slice::{self, SliceExt};
+use str::StrExt;
use string::String;
use vec::Vec;
-/// A type representing a C-compatible string
+/// A type representing an owned C-compatible string
///
-/// This type serves the primary purpose of being able to generate a
+/// This type serves the primary purpose of being able to safely generate a
/// C-compatible string from a Rust byte slice or vector. An instance of this
/// type is a static guarantee that the underlying bytes contain no interior 0
/// bytes and the final byte is 0.
/// fn my_printer(s: *const libc::c_char);
/// }
///
-/// let to_print = "Hello, world!";
-/// let c_to_print = CString::from_slice(to_print.as_bytes());
+/// let to_print = b"Hello, world!";
+/// let c_to_print = CString::new(to_print).unwrap();
/// unsafe {
/// my_printer(c_to_print.as_ptr());
/// }
/// ```
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
pub struct CString {
- inner: Vec<libc::c_char>,
+ inner: Vec<u8>,
+}
+
+/// Representation of a borrowed C string.
+///
+/// This dynamically sized type is only safely constructed via a borrowed
+/// version of an instance of `CString`. This type can be constructed from a raw
+/// C string as well and represents a C string borrowed from another location.
+///
+/// Note that this structure is **not** `repr(C)` and is not recommended to be
+/// placed in the signatures of FFI functions. Instead safe wrappers of FFI
+/// functions may leverage the unsafe `from_ptr` constructor to provide a safe
+/// interface to other consumers.
+///
+/// # Examples
+///
+/// Inspecting a foreign C string
+///
+/// ```no_run
+/// extern crate libc;
+/// use std::ffi::CStr;
+///
+/// extern { fn my_string() -> *const libc::c_char; }
+///
+/// fn main() {
+/// unsafe {
+/// let slice = CStr::from_ptr(my_string());
+/// println!("string length: {}", slice.to_bytes().len());
+/// }
+/// }
+/// ```
+///
+/// Passing a Rust-originating C string
+///
+/// ```no_run
+/// extern crate libc;
+/// use std::ffi::{CString, CStr};
+///
+/// fn work(data: &CStr) {
+/// extern { fn work_with(data: *const libc::c_char); }
+///
+/// unsafe { work_with(data.as_ptr()) }
+/// }
+///
+/// fn main() {
+/// let s = CString::new("data data data data").unwrap();
+/// work(&s);
+/// }
+/// ```
+#[derive(Hash)]
+pub struct CStr {
+ inner: [libc::c_char]
+}
+
+/// An error returned from `CString::new` to indicate that a nul byte was found
+/// in the vector provided.
+#[derive(Clone, PartialEq, Debug)]
+pub struct NulError(usize, Vec<u8>);
+
+/// A conversion trait used by the constructor of `CString` for types that can
+/// be converted to a vector of bytes.
+pub trait IntoBytes {
+ /// Consumes this container, returning a vector of bytes.
+ fn into_bytes(self) -> Vec<u8>;
}
impl CString {
+ /// Create a new C-compatible string from a container of bytes.
+ ///
+ /// This method will consume the provided data and use the underlying bytes
+ /// to construct a new string, ensuring that there is a trailing 0 byte.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// extern crate libc;
+ /// use std::ffi::CString;
+ ///
+ /// extern { fn puts(s: *const libc::c_char); }
+ ///
+ /// fn main() {
+ /// let to_print = CString::new("Hello!").unwrap();
+ /// unsafe {
+ /// puts(to_print.as_ptr());
+ /// }
+ /// }
+ /// ```
+ ///
+ /// # Errors
+ ///
+ /// This function will return an error if the bytes yielded contain an
+ /// internal 0 byte. The error returned will contain the bytes as well as
+ /// the position of the nul byte.
+ pub fn new<T: IntoBytes>(t: T) -> Result<CString, NulError> {
+ let bytes = t.into_bytes();
+ match bytes.iter().position(|x| *x == 0) {
+ Some(i) => Err(NulError(i, bytes)),
+ None => Ok(unsafe { CString::from_vec_unchecked(bytes) }),
+ }
+ }
+
/// Create a new C-compatible string from a byte slice.
///
/// This method will copy the data of the slice provided into a new
/// allocation, ensuring that there is a trailing 0 byte.
///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// extern crate libc;
+ /// use std::ffi::CString;
+ ///
+ /// extern { fn puts(s: *const libc::c_char); }
+ ///
+ /// fn main() {
+ /// let to_print = CString::new("Hello!").unwrap();
+ /// unsafe {
+ /// puts(to_print.as_ptr());
+ /// }
+ /// }
+ /// ```
+ ///
/// # Panics
///
- /// This function will panic if there are any 0 bytes already in the slice
- /// provided.
+ /// This function will panic if the provided slice contains any
+ /// interior nul bytes.
+ #[unstable(feature = "std_misc")]
+ #[deprecated(since = "1.0.0", reason = "use CString::new instead")]
+ #[allow(deprecated)]
pub fn from_slice(v: &[u8]) -> CString {
CString::from_vec(v.to_vec())
}
///
/// # Panics
///
- /// This function will panic if there are any 0 bytes already in the vector
- /// provided.
+ /// This function will panic if the provided slice contains any
+ /// interior nul bytes.
+ #[unstable(feature = "std_misc")]
+ #[deprecated(since = "1.0.0", reason = "use CString::new instead")]
pub fn from_vec(v: Vec<u8>) -> CString {
- assert!(!v.iter().any(|&x| x == 0));
- unsafe { CString::from_vec_unchecked(v) }
+ match v.iter().position(|x| *x == 0) {
+ Some(i) => panic!("null byte found in slice at: {}", i),
+ None => unsafe { CString::from_vec_unchecked(v) },
+ }
}
/// Create a C-compatible string from a byte vector without checking for
/// is made that `v` contains no 0 bytes.
pub unsafe fn from_vec_unchecked(mut v: Vec<u8>) -> CString {
v.push(0);
- CString { inner: mem::transmute(v) }
+ CString { inner: v }
}
- /// Create a view into this C string which includes the trailing nul
- /// terminator at the end of the string.
- pub fn as_slice_with_nul(&self) -> &[libc::c_char] { &self.inner }
-
- /// Similar to the `as_slice` method, but returns a `u8` slice instead of a
- /// `libc::c_char` slice.
+ /// Returns the contents of this `CString` as a slice of bytes.
+ ///
+ /// The returned slice does **not** contain the trailing nul separator and
+ /// it is guaranteet to not have any interior nul bytes.
pub fn as_bytes(&self) -> &[u8] {
- unsafe { mem::transmute(&**self) }
+ &self.inner[..self.inner.len() - 1]
}
- /// Equivalent to `as_slice_with_nul` except that the type returned is a
- /// `u8` slice instead of a `libc::c_char` slice.
+ /// Equivalent to the `as_bytes` function except that the returned slice
+ /// includes the trailing nul byte.
pub fn as_bytes_with_nul(&self) -> &[u8] {
- unsafe { mem::transmute(self.as_slice_with_nul()) }
+ &self.inner
}
}
impl Deref for CString {
- type Target = [libc::c_char];
+ type Target = CStr;
- fn deref(&self) -> &[libc::c_char] {
- &self.inner[..(self.inner.len() - 1)]
+ fn deref(&self) -> &CStr {
+ unsafe { mem::transmute(self.as_bytes_with_nul()) }
}
}
}
}
-/// Interpret a C string as a byte slice.
-///
-/// This function will calculate the length of the C string provided, and it
-/// will then return a corresponding slice for the contents of the C string not
-/// including the nul terminator.
-///
-/// This function will tie the lifetime of the returned slice to the lifetime of
-/// the pointer provided. This is done to help prevent the slice from escaping
-/// the lifetime of the pointer itself. If a longer lifetime is needed, then
-/// `mem::copy_lifetime` should be used.
-///
-/// This function is unsafe because there is no guarantee of the validity of the
-/// pointer `raw` or a guarantee that a nul terminator will be found.
-///
-/// # Example
-///
-/// ```no_run
-/// # extern crate libc;
-/// # fn main() {
-/// use std::ffi;
-/// use std::str;
-/// use libc;
-///
-/// extern {
-/// fn my_string() -> *const libc::c_char;
-/// }
-///
-/// unsafe {
-/// let to_print = my_string();
-/// let slice = ffi::c_str_to_bytes(&to_print);
-/// println!("string returned: {}", str::from_utf8(slice).unwrap());
-/// }
-/// # }
-/// ```
+impl NulError {
+ /// Returns the position of the nul byte in the slice that was provided to
+ /// `CString::from_vec`.
+ pub fn nul_position(&self) -> usize { self.0 }
+
+ /// Consumes this error, returning the underlying vector of bytes which
+ /// generated the error in the first place.
+ pub fn into_vec(self) -> Vec<u8> { self.1 }
+}
+
+impl Error for NulError {
+ fn description(&self) -> &str { "nul byte found in data" }
+}
+
+impl fmt::Display for NulError {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "nul byte found in provided data at position: {}", self.0)
+ }
+}
+
+impl FromError<NulError> for io::Error {
+ fn from_error(_: NulError) -> io::Error {
+ io::Error::new(io::ErrorKind::InvalidInput,
+ "data provided contains a nul byte", None)
+ }
+}
+
+impl FromError<NulError> for old_io::IoError {
+ fn from_error(_: NulError) -> old_io::IoError {
+ old_io::IoError {
+ kind: old_io::IoErrorKind::InvalidInput,
+ desc: "data provided contains a nul byte",
+ detail: None
+ }
+ }
+}
+
+impl CStr {
+ /// Cast a raw C string to a safe C string wrapper.
+ ///
+ /// This function will cast the provided `ptr` to the `CStr` wrapper which
+ /// allows inspection and interoperation of non-owned C strings. This method
+ /// is unsafe for a number of reasons:
+ ///
+ /// * There is no guarantee to the validity of `ptr`
+ /// * The returned lifetime is not guaranteed to be the actual lifetime of
+ /// `ptr`
+ /// * There is no guarantee that the memory pointed to by `ptr` contains a
+ /// valid nul terminator byte at the end of the string.
+ ///
+ /// > **Note**: This operation is intended to be a 0-cost cast but it is
+ /// > currently implemented with an up-front calculation of the length of
+ /// > the string. This is not guaranteed to always be the case.
+ ///
+ /// # Example
+ ///
+ /// ```no_run
+ /// # extern crate libc;
+ /// # fn main() {
+ /// use std::ffi::CStr;
+ /// use std::str;
+ /// use libc;
+ ///
+ /// extern {
+ /// fn my_string() -> *const libc::c_char;
+ /// }
+ ///
+ /// unsafe {
+ /// let slice = CStr::from_ptr(my_string());
+ /// println!("string returned: {}",
+ /// str::from_utf8(slice.to_bytes()).unwrap());
+ /// }
+ /// # }
+ /// ```
+ pub unsafe fn from_ptr<'a>(ptr: *const libc::c_char) -> &'a CStr {
+ let len = libc::strlen(ptr);
+ mem::transmute(slice::from_raw_parts(ptr, len as usize + 1))
+ }
+
+ /// Return the inner pointer to this C string.
+ ///
+ /// The returned pointer will be valid for as long as `self` is and points
+ /// to a continguous region of memory terminated with a 0 byte to represent
+ /// the end of the string.
+ pub fn as_ptr(&self) -> *const libc::c_char {
+ self.inner.as_ptr()
+ }
+
+ /// Convert this C string to a byte slice.
+ ///
+ /// This function will calculate the length of this string (which normally
+ /// requires a linear amount of work to be done) and then return the
+ /// resulting slice of `u8` elements.
+ ///
+ /// The returned slice will **not** contain the trailing nul that this C
+ /// string has.
+ ///
+ /// > **Note**: This method is currently implemented as a 0-cost cast, but
+ /// > it is planned to alter its definition in the future to perform the
+ /// > length calculation whenever this method is called.
+ pub fn to_bytes(&self) -> &[u8] {
+ let bytes = self.to_bytes_with_nul();
+ &bytes[..bytes.len() - 1]
+ }
+
+ /// Convert this C string to a byte slice containing the trailing 0 byte.
+ ///
+ /// This function is the equivalent of `to_bytes` except that it will retain
+ /// the trailing nul instead of chopping it off.
+ ///
+ /// > **Note**: This method is currently implemented as a 0-cost cast, but
+ /// > it is planned to alter its definition in the future to perform the
+ /// > length calculation whenever this method is called.
+ pub fn to_bytes_with_nul(&self) -> &[u8] {
+ unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.inner) }
+ }
+}
+
+impl PartialEq for CStr {
+ fn eq(&self, other: &CStr) -> bool {
+ self.to_bytes().eq(&other.to_bytes())
+ }
+}
+impl Eq for CStr {}
+impl PartialOrd for CStr {
+ fn partial_cmp(&self, other: &CStr) -> Option<Ordering> {
+ self.to_bytes().partial_cmp(&other.to_bytes())
+ }
+}
+impl Ord for CStr {
+ fn cmp(&self, other: &CStr) -> Ordering {
+ self.to_bytes().cmp(&other.to_bytes())
+ }
+}
+
+/// Deprecated in favor of `CStr`
+#[unstable(feature = "std_misc")]
+#[deprecated(since = "1.0.0", reason = "use CStr::from_ptr(p).to_bytes() instead")]
pub unsafe fn c_str_to_bytes<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
let len = libc::strlen(*raw);
slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize)
}
-/// Interpret a C string as a byte slice with the nul terminator.
-///
-/// This function is identical to `from_raw_buf` except that the returned slice
-/// will include the nul terminator of the string.
-pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char) -> &'a [u8] {
+/// Deprecated in favor of `CStr`
+#[unstable(feature = "std_misc")]
+#[deprecated(since = "1.0.0",
+ reason = "use CStr::from_ptr(p).to_bytes_with_nul() instead")]
+pub unsafe fn c_str_to_bytes_with_nul<'a>(raw: &'a *const libc::c_char)
+ -> &'a [u8] {
let len = libc::strlen(*raw) + 1;
slice::from_raw_parts(*(raw as *const _ as *const *const u8), len as usize)
}
+impl<'a> IntoBytes for &'a str {
+ fn into_bytes(self) -> Vec<u8> { self.as_bytes().to_vec() }
+}
+impl<'a> IntoBytes for &'a [u8] {
+ fn into_bytes(self) -> Vec<u8> { self.to_vec() }
+}
+impl IntoBytes for String {
+ fn into_bytes(self) -> Vec<u8> { self.into_bytes() }
+}
+impl IntoBytes for Vec<u8> {
+ fn into_bytes(self) -> Vec<u8> { self }
+}
+
#[cfg(test)]
mod tests {
use prelude::v1::*;
#[test]
fn simple() {
- let s = CString::from_slice(b"1234");
+ let s = CString::new(b"1234").unwrap();
assert_eq!(s.as_bytes(), b"1234");
assert_eq!(s.as_bytes_with_nul(), b"1234\0");
- unsafe {
- assert_eq!(&*s,
- mem::transmute::<_, &[libc::c_char]>(b"1234"));
- assert_eq!(s.as_slice_with_nul(),
- mem::transmute::<_, &[libc::c_char]>(b"1234\0"));
- }
}
- #[should_fail] #[test]
- fn build_with_zero1() { CString::from_slice(b"\0"); }
- #[should_fail] #[test]
- fn build_with_zero2() { CString::from_vec(vec![0]); }
+ #[test]
+ fn build_with_zero1() {
+ assert!(CString::new(b"\0").is_err());
+ }
+ #[test]
+ fn build_with_zero2() {
+ assert!(CString::new(vec![0]).is_err());
+ }
#[test]
fn build_with_zero3() {
#[test]
fn formatted() {
- let s = CString::from_slice(b"12");
+ let s = CString::new(b"12").unwrap();
assert_eq!(format!("{:?}", s), "\"12\"");
}
+
+ #[test]
+ fn borrowed() {
+ unsafe {
+ let s = CStr::from_ptr(b"12\0".as_ptr() as *const _);
+ assert_eq!(s.to_bytes(), b"12");
+ assert_eq!(s.to_bytes_with_nul(), b"12\0");
+ }
+ }
}
reason = "module just underwent fairly large reorganization and the dust \
still needs to settle")]
-pub use self::c_str::CString;
+pub use self::c_str::{CString, CStr, NulError, IntoBytes};
+#[allow(deprecated)]
pub use self::c_str::c_str_to_bytes;
+#[allow(deprecated)]
pub use self::c_str::c_str_to_bytes_with_nul;
pub use self::os_str::OsString;
use core::prelude::*;
-use core::borrow::{BorrowFrom, ToOwned};
+use borrow::{Borrow, ToOwned};
use fmt::{self, Debug};
use mem;
use string::{String, CowString};
use ops;
use cmp;
-use hash::{Hash, Hasher, Writer};
+use hash::{Hash, Hasher};
+#[cfg(stage0)] use hash::Writer;
use old_path::{Path, GenericPath};
use sys::os_str::{Buf, Slice};
#[inline]
fn deref(&self) -> &OsStr {
- &self[]
+ &self[..]
}
}
}
}
+#[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")]
+impl Hash for OsString {
+ #[inline]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ (&**self).hash(state)
+ }
+}
impl OsStr {
/// Coerce directly from a `&str` slice to a `&OsStr` slice.
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")]
+impl Hash for OsStr {
+ #[inline]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.bytes().hash(state)
+ }
+}
impl Debug for OsStr {
fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> {
}
}
-impl BorrowFrom<OsString> for OsStr {
- fn borrow_from(owned: &OsString) -> &OsStr { &owned[] }
+impl Borrow<OsStr> for OsString {
+ fn borrow(&self) -> &OsStr { &self[..] }
}
-impl ToOwned<OsString> for OsStr {
+impl ToOwned for OsStr {
+ type Owned = OsString;
fn to_owned(&self) -> OsString { self.to_os_string() }
}
impl AsOsStr for OsString {
fn as_os_str(&self) -> &OsStr {
- &self[]
+ &self[..]
}
}
impl AsOsStr for String {
fn as_os_str(&self) -> &OsStr {
- OsStr::from_str(&self[])
+ OsStr::from_str(&self[..])
}
}
#[test]
fn read_char_buffered() {
let buf = [195u8, 159u8];
- let mut reader = BufReader::with_capacity(1, &buf[]);
+ let mut reader = BufReader::with_capacity(1, &buf[..]);
assert_eq!(reader.chars().next(), Some(Ok('ß')));
}
#[test]
fn test_chars() {
let buf = [195u8, 159u8, b'a'];
- let mut reader = BufReader::with_capacity(1, &buf[]);
+ let mut reader = BufReader::with_capacity(1, &buf[..]);
let mut it = reader.chars();
assert_eq!(it.next(), Some(Ok('ß')));
assert_eq!(it.next(), Some(Ok('a')));
fn test_buf_writer() {
let mut buf = [0 as u8; 9];
{
- let mut writer = Cursor::new(&mut buf[]);
+ let mut writer = Cursor::new(&mut buf[..]);
assert_eq!(writer.position(), 0);
assert_eq!(writer.write(&[0]), Ok(1));
assert_eq!(writer.position(), 1);
fn test_buf_writer_seek() {
let mut buf = [0 as u8; 8];
{
- let mut writer = Cursor::new(&mut buf[]);
+ let mut writer = Cursor::new(&mut buf[..]);
assert_eq!(writer.position(), 0);
assert_eq!(writer.write(&[1]), Ok(1));
assert_eq!(writer.position(), 1);
#[test]
fn test_buf_writer_error() {
let mut buf = [0 as u8; 2];
- let mut writer = Cursor::new(&mut buf[]);
+ let mut writer = Cursor::new(&mut buf[..]);
assert_eq!(writer.write(&[0]), Ok(1));
assert_eq!(writer.write(&[0, 0]), Ok(1));
assert_eq!(writer.write(&[0, 0]), Ok(0));
#[test]
fn seek_past_end() {
let buf = [0xff];
- let mut r = Cursor::new(&buf[]);
+ let mut r = Cursor::new(&buf[..]);
assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10));
assert_eq!(r.read(&mut [0]), Ok(0));
assert_eq!(r.read(&mut [0]), Ok(0));
let mut buf = [0];
- let mut r = Cursor::new(&mut buf[]);
+ let mut r = Cursor::new(&mut buf[..]);
assert_eq!(r.seek(SeekFrom::Start(10)), Ok(10));
assert_eq!(r.write(&[3]), Ok(0));
}
#[test]
fn seek_before_0() {
let buf = [0xff_u8];
- let mut r = Cursor::new(&buf[]);
+ let mut r = Cursor::new(&buf[..]);
assert!(r.seek(SeekFrom::End(-2)).is_err());
let mut r = Cursor::new(vec!(10u8));
assert!(r.seek(SeekFrom::End(-2)).is_err());
let mut buf = [0];
- let mut r = Cursor::new(&mut buf[]);
+ let mut r = Cursor::new(&mut buf[..]);
assert!(r.seek(SeekFrom::End(-2)).is_err());
}
// NB: These reexports are in the order they should be listed in rustdoc
pub use core::any;
-pub use core::borrow;
pub use core::cell;
pub use core::clone;
#[cfg(not(test))] pub use core::cmp;
#[cfg(not(test))] pub use alloc::boxed;
pub use alloc::rc;
+pub use core_collections::borrow;
pub use core_collections::fmt;
pub use core_collections::slice;
pub use core_collections::str;
}
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 {
}
}
}
+#[cfg(not(stage0))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl hash::Hash for Repr {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ 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)
+ }
+ }
+ }
+}
/// A trait for objects which can be converted or resolved to one or more
/// `SocketAddr` values.
}
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")]
+impl hash::Hash for Ipv4Addr {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ self.inner.s_addr.hash(s)
+ }
+}
impl PartialOrd for Ipv4Addr {
fn partial_cmp(&self, other: &Ipv4Addr) -> Option<Ordering> {
}
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")]
+impl hash::Hash for Ipv6Addr {
+ fn hash<H: hash::Hasher>(&self, s: &mut H) {
+ self.inner.s6_addr.hash(s)
+ }
+}
impl PartialOrd for Ipv6Addr {
fn partial_cmp(&self, other: &Ipv6Addr) -> Option<Ordering> {
assert_eq!(a, &w.get_ref()[]);
let w = w.into_inner();
let a: &[_] = &[0, 1];
- assert_eq!(a, &w[]);
+ assert_eq!(a, &w[..]);
}
// This is just here to make sure that we don't infinite loop in the
#[test]
fn read_char_buffered() {
let buf = [195u8, 159u8];
- let mut reader = BufferedReader::with_capacity(1, &buf[]);
+ let mut reader = BufferedReader::with_capacity(1, &buf[..]);
assert_eq!(reader.read_char(), Ok('ß'));
}
#[test]
fn test_chars() {
let buf = [195u8, 159u8, b'a'];
- let mut reader = BufferedReader::with_capacity(1, &buf[]);
+ let mut reader = BufferedReader::with_capacity(1, &buf[..]);
let mut it = reader.chars();
assert_eq!(it.next(), Some(Ok('ß')));
assert_eq!(it.next(), Some(Ok('a')));
use fmt;
use isize;
use iter::{Iterator, IteratorExt};
-use marker::Sized;
+use marker::{PhantomFn, Sized};
use mem::transmute;
use ops::FnOnce;
use option::Option;
}
/// A trait that lets you add a `detail` to an IoError easily
-trait UpdateIoError<T> {
+trait UpdateIoError {
/// Returns an IoError with updated description and detail
fn update_err<D>(self, desc: &'static str, detail: D) -> Self where
D: FnOnce(&IoError) -> String;
fn update_desc(self, desc: &'static str) -> Self;
}
-impl<T> UpdateIoError<T> for IoResult<T> {
+impl<T> UpdateIoError for IoResult<T> {
fn update_err<D>(self, desc: &'static str, detail: D) -> IoResult<T> where
D: FnOnce(&IoError) -> String,
{
/// connections.
///
/// Doing so produces some sort of Acceptor.
-pub trait Listener<T, A: Acceptor<T>> {
+pub trait Listener<T, A: Acceptor<T>>
+ : PhantomFn<T,T> // FIXME should be an assoc type anyhow
+{
/// Spin up the listener and start queuing incoming connections
///
/// # Error
/// stream.write(&[1, 2, 3]);
/// ```
pub fn connect<P: BytesContainer>(path: P) -> IoResult<UnixStream> {
- let path = CString::from_slice(path.container_as_bytes());
+ let path = try!(CString::new(path.container_as_bytes()));
UnixStreamImp::connect(&path, None)
.map(|inner| UnixStream { inner: inner })
}
return Err(standard_error(TimedOut));
}
- let path = CString::from_slice(path.container_as_bytes());
+ let path = try!(CString::new(path.container_as_bytes()));
UnixStreamImp::connect(&path, Some(timeout.num_milliseconds() as u64))
.map(|inner| UnixStream { inner: inner })
}
/// # }
/// ```
pub fn bind<P: BytesContainer>(path: P) -> IoResult<UnixListener> {
- let path = CString::from_slice(path.container_as_bytes());
+ let path = try!(CString::new(path.container_as_bytes()));
UnixListenerImp::bind(&path)
.map(|inner| UnixListener { inner: inner })
}
#[derive(Eq, Clone, Debug)]
struct EnvKey(CString);
-#[cfg(windows)]
+#[cfg(all(windows, stage0))]
impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for EnvKey {
fn hash(&self, state: &mut H) {
let &EnvKey(ref x) = self;
}
}
}
+#[cfg(all(windows, not(stage0)))]
+impl hash::Hash for EnvKey {
+ fn hash<H: hash::Hasher>(&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(windows)]
impl PartialEq for EnvKey {
/// otherwise configure the process.
pub fn new<T: BytesContainer>(program: T) -> Command {
Command {
- program: CString::from_slice(program.container_as_bytes()),
+ program: CString::new(program.container_as_bytes()).unwrap(),
args: Vec::new(),
env: None,
cwd: None,
/// Add an argument to pass to the program.
pub fn arg<'a, T: BytesContainer>(&'a mut self, arg: T) -> &'a mut Command {
- self.args.push(CString::from_slice(arg.container_as_bytes()));
+ self.args.push(CString::new(arg.container_as_bytes()).unwrap());
self
}
/// Add multiple arguments to pass to the program.
pub fn args<'a, T: BytesContainer>(&'a mut self, args: &[T]) -> &'a mut Command {
self.args.extend(args.iter().map(|arg| {
- CString::from_slice(arg.container_as_bytes())
+ CString::new(arg.container_as_bytes()).unwrap()
}));
self
}
// if the env is currently just inheriting from the parent's,
// materialize the parent's env into a hashtable.
self.env = Some(os::env_as_bytes().into_iter().map(|(k, v)| {
- (EnvKey(CString::from_slice(&k)),
- CString::from_slice(&v))
+ (EnvKey(CString::new(k).unwrap()),
+ CString::new(v).unwrap())
}).collect());
self.env.as_mut().unwrap()
}
pub fn env<'a, T, U>(&'a mut self, key: T, val: U)
-> &'a mut Command
where T: BytesContainer, U: BytesContainer {
- let key = EnvKey(CString::from_slice(key.container_as_bytes()));
- let val = CString::from_slice(val.container_as_bytes());
+ let key = EnvKey(CString::new(key.container_as_bytes()).unwrap());
+ let val = CString::new(val.container_as_bytes()).unwrap();
self.get_env_map().insert(key, val);
self
}
/// Removes an environment variable mapping.
pub fn env_remove<'a, T>(&'a mut self, key: T) -> &'a mut Command
where T: BytesContainer {
- let key = EnvKey(CString::from_slice(key.container_as_bytes()));
+ let key = EnvKey(CString::new(key.container_as_bytes()).unwrap());
self.get_env_map().remove(&key);
self
}
-> &'a mut Command
where T: BytesContainer, U: BytesContainer {
self.env = Some(env.iter().map(|&(ref k, ref v)| {
- (EnvKey(CString::from_slice(k.container_as_bytes())),
- CString::from_slice(v.container_as_bytes()))
+ (EnvKey(CString::new(k.container_as_bytes()).unwrap()),
+ CString::new(v.container_as_bytes()).unwrap())
}).collect());
self
}
/// Set the working directory for the child process.
pub fn cwd<'a>(&'a mut self, dir: &Path) -> &'a mut Command {
- self.cwd = Some(CString::from_slice(dir.as_vec()));
+ self.cwd = Some(CString::new(dir.as_vec()).unwrap());
self
}
cmd.env("path", "foo");
cmd.env("Path", "bar");
let env = &cmd.env.unwrap();
- let val = env.get(&EnvKey(CString::from_slice(b"PATH")));
- assert!(val.unwrap() == &CString::from_slice(b"bar"));
+ let val = env.get(&EnvKey(CString::new(b"PATH").unwrap()));
+ assert!(val.unwrap() == &CString::new(b"bar").unwrap());
}
}
}
#[inline]
fn container_as_str(&self) -> Option<&str> {
- Some(&self[])
+ Some(&self[..])
}
#[inline]
fn is_str(_: Option<&String>) -> bool { true }
impl BytesContainer for Vec<u8> {
#[inline]
fn container_as_bytes(&self) -> &[u8] {
- &self[]
+ &self[..]
}
}
#[derive(Debug, Clone, PartialEq, Copy)]
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")]
+impl hash::Hash for Path {
+ #[inline]
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ self.repr.hash(state)
+ }
+}
impl BytesContainer for Path {
#[inline]
let exp: &[&[u8]] = &[$($exp),*];
assert_eq!(comps, exp);
let comps = path.components().rev().collect::<Vec<&[u8]>>();
- let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&[u8]>>();
+ let exp = exp.iter().rev().cloned().collect::<Vec<&[u8]>>();
assert_eq!(comps, exp)
}
)
let exp: &[Option<&str>] = &$exp;
assert_eq!(comps, exp);
let comps = path.str_components().rev().collect::<Vec<Option<&str>>>();
- let exp = exp.iter().rev().map(|&x|x).collect::<Vec<Option<&str>>>();
+ let exp = exp.iter().rev().cloned().collect::<Vec<Option<&str>>>();
assert_eq!(comps, exp);
}
)
#[derive(Debug, Clone, PartialEq, Copy)]
pub struct ParsePathError;
+#[cfg(stage0)]
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for Path {
#[cfg(not(test))]
#[inline]
// No-op because the `hash` implementation will be wrong.
}
}
+#[cfg(not(stage0))]
+#[stable(feature = "rust1", since = "1.0.0")]
+impl hash::Hash for Path {
+ #[cfg(not(test))]
+ #[inline]
+ fn hash<H: hash::Hasher>(&self, state: &mut H) {
+ self.repr.hash(state)
+ }
+
+ #[cfg(test)]
+ #[inline]
+ fn hash<H: hash::Hasher>(&self, _: &mut H) {
+ // No-op because the `hash` implementation will be wrong.
+ }
+}
impl BytesContainer for Path {
#[inline]
s.push_str("..");
s.push(SEP);
s.push_str(filename);
- self.update_normalized(&s[]);
+ self.update_normalized(&s[..]);
}
None => {
self.update_normalized(filename);
s.push_str(&self.repr[..end]);
s.push(SEP);
s.push_str(filename);
- self.update_normalized(&s[]);
+ self.update_normalized(&s[..]);
}
Some((idxb,idxa,_)) if self.prefix == Some(DiskPrefix) && idxa == self.prefix_len() => {
let mut s = String::with_capacity(idxb + filename.len());
s.push_str(&self.repr[..idxb]);
s.push_str(filename);
- self.update_normalized(&s[]);
+ self.update_normalized(&s[..]);
}
Some((idxb,_,_)) => {
let mut s = String::with_capacity(idxb + 1 + filename.len());
s.push_str(&self.repr[..idxb]);
s.push(SEP);
s.push_str(filename);
- self.update_normalized(&s[]);
+ self.update_normalized(&s[..]);
}
}
}
}
fn shares_volume(me: &Path, path: &str) -> bool {
// path is assumed to have a prefix of Some(DiskPrefix)
- let repr = &me.repr[];
+ let repr = &me.repr[..];
match me.prefix {
Some(DiskPrefix) => {
repr.as_bytes()[0] == path.as_bytes()[0].to_ascii_uppercase()
else { None };
let pathlen = path_.as_ref().map_or(path.len(), |p| p.len());
let mut s = String::with_capacity(me.repr.len() + 1 + pathlen);
- s.push_str(&me.repr[]);
+ s.push_str(&me.repr[..]);
let plen = me.prefix_len();
// if me is "C:" we don't want to add a path separator
match me.prefix {
}
match path_ {
None => s.push_str(path),
- Some(p) => s.push_str(&p[]),
+ Some(p) => s.push_str(&p[..]),
};
- me.update_normalized(&s[])
+ me.update_normalized(&s[..])
}
if !path.is_empty() {
/// Always returns a `Some` value.
#[inline]
fn as_str<'a>(&'a self) -> Option<&'a str> {
- Some(&self.repr[])
+ Some(&self.repr[..])
}
#[inline]
/// Always returns a `Some` value.
fn dirname_str<'a>(&'a self) -> Option<&'a str> {
Some(match self.sepidx_or_prefix_len() {
- None if ".." == self.repr => &self.repr[],
+ None if ".." == self.repr => &self.repr[..],
None => ".",
Some((_,idxa,end)) if &self.repr[idxa..end] == ".." => {
- &self.repr[]
+ &self.repr[..]
}
Some((idxb,_,end)) if &self.repr[idxb..end] == "\\" => {
- &self.repr[]
+ &self.repr[..]
}
Some((0,idxa,_)) => &self.repr[..idxa],
Some((idxb,idxa,_)) => {
/// See `GenericPath::filename_str` for info.
/// Always returns a `Some` value if `filename` returns a `Some` value.
fn filename_str<'a>(&'a self) -> Option<&'a str> {
- let repr = &self.repr[];
+ let repr = &self.repr[..];
match self.sepidx_or_prefix_len() {
None if "." == repr || ".." == repr => None,
None => Some(repr),
/// Does not distinguish between absolute and cwd-relative paths, e.g.
/// C:\foo and C:foo.
pub fn str_components<'a>(&'a self) -> StrComponents<'a> {
- let repr = &self.repr[];
+ let repr = &self.repr[..];
let s = match self.prefix {
Some(_) => {
let plen = self.prefix_len();
}
fn equiv_prefix(&self, other: &Path) -> bool {
- let s_repr = &self.repr[];
- let o_repr = &other.repr[];
+ let s_repr = &self.repr[..];
+ let o_repr = &other.repr[..];
match (self.prefix, other.prefix) {
(Some(DiskPrefix), Some(VerbatimDiskPrefix)) => {
self.is_absolute() &&
fn update_sepidx(&mut self) {
let s = if self.has_nonsemantic_trailing_slash() {
&self.repr[..self.repr.len()-1]
- } else { &self.repr[] };
+ } else { &self.repr[..] };
let sep_test: fn(char) -> bool = if !prefix_is_verbatim(self.prefix) {
is_sep
} else {
/// non-verbatim, the non-verbatim version is returned.
/// Otherwise, None is returned.
pub fn make_non_verbatim(path: &Path) -> Option<Path> {
- let repr = &path.repr[];
+ let repr = &path.repr[..];
let new_path = match path.prefix {
Some(VerbatimPrefix(_)) | Some(DeviceNSPrefix(_)) => return None,
Some(UNCPrefix(_,_)) | Some(DiskPrefix) | None => return Some(path.clone()),
assert_eq!(comps, exp);
let comps = path.str_components().rev().map(|x|x.unwrap())
.collect::<Vec<&str>>();
- let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&str>>();
+ let exp = exp.iter().rev().cloned().collect::<Vec<&str>>();
assert_eq!(comps, exp);
}
);
let exp: &[&[u8]] = &$exp;
assert_eq!(comps, exp);
let comps = path.components().rev().collect::<Vec<&[u8]>>();
- let exp = exp.iter().rev().map(|&x|x).collect::<Vec<&[u8]>>();
+ let exp = exp.iter().rev().cloned().collect::<Vec<&[u8]>>();
assert_eq!(comps, exp);
}
)
#[cfg(target_os = "macos")]
unsafe fn load_argc_and_argv(argc: int,
argv: *const *const c_char) -> Vec<Vec<u8>> {
+ use ffi::CStr;
use iter::range;
- (0..argc as uint).map(|i| {
- ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec()
+ (0..argc).map(|i| {
+ CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec()
}).collect()
}
let msg = match obj.downcast_ref::<&'static str>() {
Some(s) => *s,
None => match obj.downcast_ref::<String>() {
- Some(s) => &s[],
+ Some(s) => &s[..],
None => "Box<Any>",
}
};
use core::prelude::*;
use ascii::*;
-use borrow::BorrowFrom;
+use borrow::{Borrow, ToOwned, Cow};
use cmp;
-use iter;
+use iter::{self, IntoIterator};
use mem;
use ops::{self, Deref};
-use string::CowString;
use vec::Vec;
use fmt;
}
impl<'a, P: ?Sized + 'a> iter::FromIterator<&'a P> for PathBuf where P: AsPath {
- fn from_iter<I: Iterator<Item = &'a P>>(iter: I) -> PathBuf {
+ fn from_iter<I: IntoIterator<Item = &'a P>>(iter: I) -> PathBuf {
let mut buf = PathBuf::new("");
buf.extend(iter);
buf
}
impl<'a, P: ?Sized + 'a> iter::Extend<&'a P> for PathBuf where P: AsPath {
- fn extend<I: Iterator<Item = &'a P>>(&mut self, iter: I) {
+ fn extend<I: IntoIterator<Item = &'a P>>(&mut self, iter: I) {
for p in iter {
self.push(p)
}
type Target = Path;
fn deref(&self) -> &Path {
- unsafe { mem::transmute(&self.inner[]) }
+ unsafe { mem::transmute(&self.inner[..]) }
}
}
-impl BorrowFrom<PathBuf> for Path {
- fn borrow_from(owned: &PathBuf) -> &Path {
- owned.deref()
+impl Borrow<Path> for PathBuf {
+ fn borrow(&self) -> &Path {
+ self.deref()
}
}
+impl ToOwned for Path {
+ type Owned = PathBuf;
+ fn to_owned(&self) -> PathBuf { self.to_path_buf() }
+}
+
impl cmp::PartialEq for PathBuf {
fn eq(&self, other: &PathBuf) -> bool {
self.components() == other.components()
impl AsOsStr for PathBuf {
fn as_os_str(&self) -> &OsStr {
- &self.inner[]
+ &self.inner[..]
}
}
self.inner.to_str()
}
- /// Convert a `Path` to a `CowString`.
+ /// Convert a `Path` to a `Cow<str>`.
///
/// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER.
- pub fn to_string_lossy(&self) -> CowString {
+ pub fn to_string_lossy(&self) -> Cow<str> {
self.inner.to_string_lossy()
}
#[test]
fn test_choose() {
let mut r = thread_rng();
- assert_eq!(r.choose(&[1, 1, 1]).map(|&x|x), Some(1));
+ assert_eq!(r.choose(&[1, 1, 1]).cloned(), Some(1));
let v: &[int] = &[];
assert_eq!(r.choose(v), None);
use libc;
use mem;
- use ffi;
+ use ffi::CStr;
use sync::{StaticMutex, MUTEX_INIT};
unsafe { mem::transmute(&GLOBAL_ARGS_PTR) }
}
- unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec<Vec<u8>> {
+ unsafe fn load_argc_and_argv(argc: isize,
+ argv: *const *const u8) -> Vec<Vec<u8>> {
let argv = argv as *const *const libc::c_char;
- (0..argc as uint).map(|i| {
- ffi::c_str_to_bytes(&*argv.offset(i as int)).to_vec()
+ (0..argc).map(|i| {
+ CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec()
}).collect()
}
use self::SocketStatus::*;
use self::InAddr::*;
-use ffi::CString;
-use ffi;
+use ffi::{CString, CStr};
use old_io::net::addrinfo;
use old_io::net::ip::{SocketAddr, IpAddr, Ipv4Addr, Ipv6Addr};
use old_io::{IoResult, IoError};
assert!(host.is_some() || servname.is_some());
- let c_host = host.map(|x| CString::from_slice(x.as_bytes()));
+ let c_host = match host {
+ Some(x) => Some(try!(CString::new(x))),
+ None => None,
+ };
let c_host = c_host.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
- let c_serv = servname.map(|x| CString::from_slice(x.as_bytes()));
+ let c_serv = match servname {
+ Some(x) => Some(try!(CString::new(x))),
+ None => None,
+ };
let c_serv = c_serv.as_ref().map(|x| x.as_ptr()).unwrap_or(null());
let hint = hint.map(|hint| {
}
unsafe {
- Ok(str::from_utf8(ffi::c_str_to_bytes(&hostbuf.as_ptr()))
- .unwrap().to_string())
+ let data = CStr::from_ptr(hostbuf.as_ptr());
+ Ok(str::from_utf8(data.to_bytes()).unwrap().to_string())
}
}
pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
init();
- let c_host = CString::from_slice(host.as_bytes());
+ let c_host = try!(CString::new(host));
let mut res = 0 as *mut _;
unsafe {
try!(cvt_gai(getaddrinfo(c_host.as_ptr(), 0 as *const _, 0 as *const _,
use borrow::Cow;
use cmp;
use fmt;
-use hash::{Hash, Writer, Hasher};
-use iter::FromIterator;
+use hash::{Hash, Hasher};
+#[cfg(stage0)] use hash::Writer;
+use iter::{FromIterator, IntoIterator};
use mem;
use num::Int;
use ops;
/// This replaces surrogate code point pairs with supplementary code points,
/// like concatenating ill-formed UTF-16 strings effectively would.
impl FromIterator<CodePoint> for Wtf8Buf {
- fn from_iter<T: Iterator<Item=CodePoint>>(iterator: T) -> Wtf8Buf {
+ fn from_iter<T: IntoIterator<Item=CodePoint>>(iter: T) -> Wtf8Buf {
let mut string = Wtf8Buf::new();
- string.extend(iterator);
+ string.extend(iter);
string
}
}
/// This replaces surrogate code point pairs with supplementary code points,
/// like concatenating ill-formed UTF-16 strings effectively would.
impl Extend<CodePoint> for Wtf8Buf {
- fn extend<T: Iterator<Item=CodePoint>>(&mut self, iterator: T) {
+ fn extend<T: IntoIterator<Item=CodePoint>>(&mut self, iterable: T) {
+ let iterator = iterable.into_iter();
let (low, _high) = iterator.size_hint();
// Lower bound of one byte per code point (ASCII only)
self.bytes.reserve(low);
}
}
+#[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 {
+ #[inline]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ self.value.hash(state)
+ }
+}
+#[cfg(stage0)]
impl<S: Writer + Hasher> Hash<S> for Wtf8Buf {
#[inline]
fn hash(&self, state: &mut S) {
0xfeu8.hash(state)
}
}
+#[cfg(not(stage0))]
+impl Hash for Wtf8Buf {
+ #[inline]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ state.write(&self.bytes);
+ 0xfeu8.hash(state)
+ }
+}
+#[cfg(stage0)]
impl<'a, S: Writer + Hasher> Hash<S> for Wtf8 {
#[inline]
fn hash(&self, state: &mut S) {
0xfeu8.hash(state)
}
}
+#[cfg(not(stage0))]
+impl Hash for Wtf8 {
+ #[inline]
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ state.write(&self.bytes);
+ 0xfeu8.hash(state)
+ }
+}
impl AsciiExt for Wtf8 {
type Owned = Wtf8Buf;
use prelude::v1::*;
-use ffi;
+use ffi::CStr;
use old_io::IoResult;
use libc;
use mem;
output(w, idx,addr, None)
} else {
output(w, idx, addr, Some(unsafe {
- ffi::c_str_to_bytes(&info.dli_sname)
+ CStr::from_ptr(info.dli_sname).to_bytes()
}))
}
}
if ret == 0 || data.is_null() {
output(w, idx, addr, None)
} else {
- output(w, idx, addr, Some(unsafe { ffi::c_str_to_bytes(&data) }))
+ output(w, idx, addr, Some(unsafe { CStr::from_ptr(data).to_bytes() }))
}
}
use prelude::v1::*;
-use ffi::{CString, OsStr, OsString};
+use ffi::{CString, NulError, OsStr, OsString};
use fs::{self, Permissions, OpenOptions};
use net;
use mem;
fn as_bytes(&self) -> &[u8];
/// Convert the `OsStr` slice into a `CString`.
- fn to_cstring(&self) -> CString;
+ fn to_cstring(&self) -> Result<CString, NulError>;
}
impl OsStrExt for OsStr {
&self.as_inner().inner
}
- fn to_cstring(&self) -> CString {
- CString::from_slice(self.as_bytes())
+ fn to_cstring(&self) -> Result<CString, NulError> {
+ CString::new(self.as_bytes())
}
}
/// Includes all extension traits, and some important type definitions.
pub mod prelude {
#[doc(no_inline)]
- pub use super::{Fd, AsRawFd, OsStrExt, OsStringExt, PermissionsExt, CommandExt, ExitStatusExt};
+ pub use super::{Fd, AsRawFd, OsStrExt, OsStringExt, PermissionsExt};
+ #[doc(no_inline)]
+ pub use super::{CommandExt, ExitStatusExt};
}
use prelude::v1::*;
-use ffi::{self, CString};
+use ffi::{CString, CStr};
use old_io::{FilePermission, Write, UnstableFileStat, Open, FileAccess, FileMode};
use old_io::{IoResult, FileStat, SeekStyle};
use old_io::{Read, Truncate, SeekCur, SeekSet, ReadWrite, SeekEnd, Append};
}
}
-fn cstr(path: &Path) -> CString {
- CString::from_slice(path.as_vec())
+fn cstr(path: &Path) -> IoResult<CString> {
+ Ok(try!(CString::new(path.as_vec())))
}
pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult<FileDesc> {
libc::S_IRUSR | libc::S_IWUSR),
};
- let path = cstr(path);
+ let path = try!(cstr(path));
match retry(|| unsafe { libc::open(path.as_ptr(), flags, mode) }) {
-1 => Err(super::last_error()),
fd => Ok(FileDesc::new(fd, true)),
}
pub fn mkdir(p: &Path, mode: uint) -> IoResult<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
mkerr_libc(unsafe { libc::mkdir(p.as_ptr(), mode as libc::mode_t) })
}
let mut buf = Vec::<u8>::with_capacity(size as uint);
let ptr = buf.as_mut_ptr() as *mut dirent_t;
- let p = CString::from_slice(p.as_vec());
+ let p = try!(CString::new(p.as_vec()));
let dir_ptr = unsafe {opendir(p.as_ptr())};
if dir_ptr as uint != 0 {
while unsafe { readdir_r(dir_ptr, ptr, &mut entry_ptr) == 0 } {
if entry_ptr.is_null() { break }
paths.push(unsafe {
- Path::new(ffi::c_str_to_bytes(&rust_list_dir_val(entry_ptr)))
+ Path::new(CStr::from_ptr(rust_list_dir_val(entry_ptr)).to_bytes())
});
}
assert_eq!(unsafe { closedir(dir_ptr) }, 0);
}
pub fn unlink(p: &Path) -> IoResult<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
mkerr_libc(unsafe { libc::unlink(p.as_ptr()) })
}
pub fn rename(old: &Path, new: &Path) -> IoResult<()> {
- let old = cstr(old);
- let new = cstr(new);
+ let old = try!(cstr(old));
+ let new = try!(cstr(new));
mkerr_libc(unsafe {
libc::rename(old.as_ptr(), new.as_ptr())
})
}
pub fn chmod(p: &Path, mode: uint) -> IoResult<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
mkerr_libc(retry(|| unsafe {
libc::chmod(p.as_ptr(), mode as libc::mode_t)
}))
}
pub fn rmdir(p: &Path) -> IoResult<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
mkerr_libc(unsafe { libc::rmdir(p.as_ptr()) })
}
pub fn chown(p: &Path, uid: int, gid: int) -> IoResult<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
mkerr_libc(retry(|| unsafe {
libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t)
}))
}
pub fn readlink(p: &Path) -> IoResult<Path> {
- let c_path = cstr(p);
+ let c_path = try!(cstr(p));
let p = c_path.as_ptr();
let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
if len == -1 {
}
pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
- let src = cstr(src);
- let dst = cstr(dst);
+ let src = try!(cstr(src));
+ let dst = try!(cstr(dst));
mkerr_libc(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) })
}
pub fn link(src: &Path, dst: &Path) -> IoResult<()> {
- let src = cstr(src);
- let dst = cstr(dst);
+ let src = try!(cstr(src));
+ let dst = try!(cstr(dst));
mkerr_libc(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) })
}
}
pub fn stat(p: &Path) -> IoResult<FileStat> {
- let p = cstr(p);
+ let p = try!(cstr(p));
let mut stat: libc::stat = unsafe { mem::zeroed() };
match unsafe { libc::stat(p.as_ptr(), &mut stat) } {
0 => Ok(mkstat(&stat)),
}
pub fn lstat(p: &Path) -> IoResult<FileStat> {
- let p = cstr(p);
+ let p = try!(cstr(p));
let mut stat: libc::stat = unsafe { mem::zeroed() };
match unsafe { libc::lstat(p.as_ptr(), &mut stat) } {
0 => Ok(mkstat(&stat)),
}
pub fn utime(p: &Path, atime: u64, mtime: u64) -> IoResult<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
let buf = libc::utimbuf {
actime: (atime / 1000) as libc::time_t,
modtime: (mtime / 1000) as libc::time_t,
use io::prelude::*;
use os::unix::prelude::*;
-use ffi::{self, CString, OsString, AsOsStr, OsStr};
+use ffi::{CString, CStr, OsString, AsOsStr, OsStr};
use io::{self, Error, Seek, SeekFrom};
use libc::{self, c_int, c_void, size_t, off_t, c_char, mode_t};
use mem;
fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char;
}
unsafe {
- let ptr = rust_list_dir_val(self.dirent);
- ffi::c_str_to_bytes(mem::copy_lifetime(self, &ptr))
+ CStr::from_ptr(rust_list_dir_val(self.dirent)).to_bytes()
}
}
}
(true, false) |
(false, false) => libc::O_RDONLY,
};
- let path = cstr(path);
+ let path = try!(cstr(path));
let fd = try!(cvt_r(|| unsafe {
libc::open(path.as_ptr(), flags, opts.mode)
}));
pub fn fd(&self) -> &FileDesc { &self.0 }
}
-fn cstr(path: &Path) -> CString {
- CString::from_slice(path.as_os_str().as_bytes())
+fn cstr(path: &Path) -> io::Result<CString> {
+ let cstring = try!(path.as_os_str().to_cstring());
+ Ok(cstring)
}
pub fn mkdir(p: &Path) -> io::Result<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
try!(cvt(unsafe { libc::mkdir(p.as_ptr(), 0o777) }));
Ok(())
}
pub fn readdir(p: &Path) -> io::Result<ReadDir> {
let root = Rc::new(p.to_path_buf());
- let p = cstr(p);
+ let p = try!(cstr(p));
unsafe {
let ptr = libc::opendir(p.as_ptr());
if ptr.is_null() {
}
pub fn unlink(p: &Path) -> io::Result<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
try!(cvt(unsafe { libc::unlink(p.as_ptr()) }));
Ok(())
}
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
- let old = cstr(old);
- let new = cstr(new);
+ let old = try!(cstr(old));
+ let new = try!(cstr(new));
try!(cvt(unsafe { libc::rename(old.as_ptr(), new.as_ptr()) }));
Ok(())
}
pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
try!(cvt_r(|| unsafe { libc::chmod(p.as_ptr(), perm.mode) }));
Ok(())
}
pub fn rmdir(p: &Path) -> io::Result<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
try!(cvt(unsafe { libc::rmdir(p.as_ptr()) }));
Ok(())
}
pub fn chown(p: &Path, uid: isize, gid: isize) -> io::Result<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
try!(cvt_r(|| unsafe {
libc::chown(p.as_ptr(), uid as libc::uid_t, gid as libc::gid_t)
}));
}
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
- let c_path = cstr(p);
+ let c_path = try!(cstr(p));
let p = c_path.as_ptr();
let mut len = unsafe { libc::pathconf(p as *mut _, libc::_PC_NAME_MAX) };
if len < 0 {
}
pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
- let src = cstr(src);
- let dst = cstr(dst);
+ let src = try!(cstr(src));
+ let dst = try!(cstr(dst));
try!(cvt(unsafe { libc::symlink(src.as_ptr(), dst.as_ptr()) }));
Ok(())
}
pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
- let src = cstr(src);
- let dst = cstr(dst);
+ let src = try!(cstr(src));
+ let dst = try!(cstr(dst));
try!(cvt(unsafe { libc::link(src.as_ptr(), dst.as_ptr()) }));
Ok(())
}
pub fn stat(p: &Path) -> io::Result<FileAttr> {
- let p = cstr(p);
+ let p = try!(cstr(p));
let mut stat: libc::stat = unsafe { mem::zeroed() };
try!(cvt(unsafe { libc::stat(p.as_ptr(), &mut stat) }));
Ok(FileAttr { stat: stat })
}
pub fn lstat(p: &Path) -> io::Result<FileAttr> {
- let p = cstr(p);
+ let p = try!(cstr(p));
let mut stat: libc::stat = unsafe { mem::zeroed() };
try!(cvt(unsafe { libc::lstat(p.as_ptr(), &mut stat) }));
Ok(FileAttr { stat: stat })
}
pub fn utimes(p: &Path, atime: u64, mtime: u64) -> io::Result<()> {
- let p = cstr(p);
+ let p = try!(cstr(p));
let buf = [super::ms_to_timeval(atime), super::ms_to_timeval(mtime)];
try!(cvt(unsafe { c::utimes(p.as_ptr(), buf.as_ptr()) }));
Ok(())
use prelude::v1::*;
-use ffi;
+use ffi::CStr;
use io::{self, ErrorKind};
use libc;
use num::{Int, SignedInt};
let mut err = decode_error(s);
err.detail = Some(unsafe {
- str::from_utf8(ffi::c_str_to_bytes(&gai_strerror(s))).unwrap().to_string()
+ let data = CStr::from_ptr(gai_strerror(s));
+ str::from_utf8(data.to_bytes()).unwrap().to_string()
});
err
}
use prelude::v1::*;
-use ffi;
+use ffi::CStr;
use io;
use libc::{self, c_int, size_t};
use str;
if err == 0 { return Ok(()) }
let detail = unsafe {
- str::from_utf8(ffi::c_str_to_bytes(&c::gai_strerror(err))).unwrap()
+ str::from_utf8(CStr::from_ptr(c::gai_strerror(err)).to_bytes()).unwrap()
.to_string()
};
Err(io::Error::new(io::ErrorKind::Other,
use os::unix::*;
use error::Error as StdError;
-use ffi::{self, CString, OsString, OsStr, AsOsStr};
+use ffi::{CString, CStr, OsString, OsStr, AsOsStr};
use fmt;
use iter;
use libc::{self, c_int, c_char, c_void};
}
let p = p as *const _;
- str::from_utf8(ffi::c_str_to_bytes(&p)).unwrap().to_string()
+ str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_string()
}
}
if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
Err(IoError::last_error())
} else {
- Ok(Path::new(ffi::c_str_to_bytes(&buf.as_ptr())))
+ Ok(Path::new(CStr::from_ptr(buf.as_ptr()).to_bytes()))
}
}
}
pub fn chdir(p: &Path) -> IoResult<()> {
- let p = CString::from_slice(p.as_vec());
+ let p = CString::new(p.as_vec()).unwrap();
unsafe {
match libc::chdir(p.as_ptr()) == (0 as c_int) {
true => Ok(()),
if v.is_null() {
Err(IoError::last_error())
} else {
- Ok(Path::new(ffi::c_str_to_bytes(&v).to_vec()))
+ Ok(Path::new(CStr::from_ptr(&v).to_bytes().to_vec()))
}
}
}
let (argc, argv) = (*_NSGetArgc() as isize,
*_NSGetArgv() as *const *const c_char);
range(0, argc as isize).map(|i| {
- let bytes = ffi::c_str_to_bytes(&*argv.offset(i)).to_vec();
+ let bytes = CStr::from_ptr(*argv.offset(i)).to_bytes().to_vec();
OsStringExt::from_vec(bytes)
}).collect::<Vec<_>>()
};
let tmp = objc_msgSend(args, object_at_sel, i);
let utf_c_str: *const libc::c_char =
mem::transmute(objc_msgSend(tmp, utf8_sel));
- let bytes = ffi::c_str_to_bytes(&utf_c_str);
+ let bytes = CStr::from_ptr(utf_c_str).to_bytes();
res.push(OsString::from_str(str::from_utf8(bytes).unwrap()))
}
}
}
let mut result = Vec::new();
while *environ != ptr::null() {
- result.push(parse(ffi::c_str_to_bytes(&*environ)));
+ result.push(parse(CStr::from_ptr(*environ).to_bytes()));
environ = environ.offset(1);
}
Env { iter: result.into_iter(), _dont_send_or_sync_me: 0 as *mut _ }
pub fn getenv(k: &OsStr) -> Option<OsString> {
unsafe {
- let s = CString::from_slice(k.as_bytes());
+ let s = k.to_cstring().unwrap();
let s = libc::getenv(s.as_ptr()) as *const _;
if s.is_null() {
None
} else {
- Some(OsStringExt::from_vec(ffi::c_str_to_bytes(&s).to_vec()))
+ Some(OsStringExt::from_vec(CStr::from_ptr(s).to_bytes().to_vec()))
}
}
}
pub fn setenv(k: &OsStr, v: &OsStr) {
unsafe {
- let k = CString::from_slice(k.as_bytes());
- let v = CString::from_slice(v.as_bytes());
+ let k = k.to_cstring().unwrap();
+ let v = v.to_cstring().unwrap();
if libc::funcs::posix01::unistd::setenv(k.as_ptr(), v.as_ptr(), 1) != 0 {
panic!("failed setenv: {}", IoError::last_error());
}
pub fn unsetenv(n: &OsStr) {
unsafe {
- let nbuf = CString::from_slice(n.as_bytes());
+ let nbuf = n.to_cstring().unwrap();
if libc::funcs::posix01::unistd::unsetenv(nbuf.as_ptr()) != 0 {
panic!("failed unsetenv: {}", IoError::last_error());
}
_ => return None
}
let ptr = passwd.pw_dir as *const _;
- let bytes = ffi::c_str_to_bytes(&ptr).to_vec();
+ let bytes = CStr::from_ptr(ptr).to_bytes().to_vec();
return Some(OsStringExt::from_vec(bytes))
}
}
mem::size_of::<libc::sockaddr_un>());
let s = unsafe { &mut *(storage as *mut _ as *mut libc::sockaddr_un) };
- let len = addr.len();
+ let len = addr.as_bytes().len();
if len > s.sun_path.len() - 1 {
return Err(IoError {
kind: old_io::InvalidInput,
})
}
s.sun_family = libc::AF_UNIX as libc::sa_family_t;
- for (slot, value) in s.sun_path.iter_mut().zip(addr.iter()) {
- *slot = *value;
+ for (slot, value) in s.sun_path.iter_mut().zip(addr.as_bytes().iter()) {
+ *slot = *value as libc::c_char;
}
// count the null terminator
use self::Req::*;
use collections::HashMap;
+#[cfg(stage0)]
use collections::hash_map::Hasher;
use ffi::CString;
use hash::Hash;
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>
})
})
}
+ #[cfg(not(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, V: BytesContainer
+ {
+ use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
+ use libc::funcs::bsd44::getdtablesize;
+
+ mod rustrt {
+ extern {
+ pub fn rust_unset_sigprocmask();
+ }
+ }
+
+ 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);
+ })
+ })
+ }
pub fn wait(&self, deadline: u64) -> IoResult<ProcessExit> {
use cmp;
cb(ptrs.as_ptr())
}
+#[cfg(stage0)]
fn with_envp<K,V,T,F>(env: Option<&HashMap<K, V>>,
cb: F)
-> T
_ => cb(ptr::null())
}
}
+#[cfg(not(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,
+ 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())
+ }
+}
fn translate_status(status: c_int) -> ProcessExit {
#![allow(non_snake_case)]
use prelude::v1::*;
use collections::HashMap;
-use collections::hash_map::Hasher;
use env;
use ffi::{OsString, OsStr, CString};
use fmt;
impl Command {
pub fn new(program: &OsStr) -> Command {
Command {
- program: program.to_cstring(),
+ program: program.to_cstring().unwrap(),
args: Vec::new(),
env: None,
cwd: None,
}
pub fn arg(&mut self, arg: &OsStr) {
- self.args.push(arg.to_cstring())
+ self.args.push(arg.to_cstring().unwrap())
}
pub fn args<'a, I: Iterator<Item = &'a OsStr>>(&mut self, args: I) {
- self.args.extend(args.map(OsStrExt::to_cstring))
+ self.args.extend(args.map(|s| OsStrExt::to_cstring(s).unwrap()))
}
fn init_env_map(&mut self) {
if self.env.is_none() {
self.env = Some(HashMap::new())
}
pub fn cwd(&mut self, dir: &OsStr) {
- self.cwd = Some(dir.to_cstring())
+ self.cwd = Some(dir.to_cstring().unwrap())
}
}
pub unsafe fn set_name(name: &str) {
// pthread_setname_np() since glibc 2.12
// availability autodetected via weak linkage
- let cname = CString::from_slice(name.as_bytes());
+ let cname = CString::new(name).unwrap();
type F = unsafe extern "C" fn(libc::pthread_t, *const libc::c_char) -> libc::c_int;
extern {
#[linkage = "extern_weak"]
target_os = "openbsd"))]
pub unsafe fn set_name(name: &str) {
// pthread_set_name_np() since almost forever on all BSDs
- let cname = CString::from_slice(name.as_bytes());
+ let cname = CString::new(name).unwrap();
pthread_set_name_np(pthread_self(), cname.as_ptr());
}
#[cfg(any(target_os = "macos", target_os = "ios"))]
pub unsafe fn set_name(name: &str) {
// pthread_setname_np() since OS X 10.6 and iOS 3.2
- let cname = CString::from_slice(name.as_bytes());
+ let cname = CString::new(name).unwrap();
pthread_setname_np(cname.as_ptr());
}
#![allow(dead_code)]
use dynamic_lib::DynamicLibrary;
-use ffi;
+use ffi::CStr;
use intrinsics;
use old_io::{IoResult, Writer};
use libc;
if ret == libc::TRUE {
try!(write!(w, " - "));
let ptr = info.Name.as_ptr() as *const libc::c_char;
- let bytes = unsafe { ffi::c_str_to_bytes(&ptr) };
+ let bytes = unsafe { CStr::from_ptr(ptr).to_bytes() };
match str::from_utf8(bytes) {
Ok(s) => try!(demangle(w, s)),
Err(..) => try!(w.write_all(&bytes[..bytes.len()-1])),
fallback: usize) -> usize {
let mut module: Vec<u16> = module.utf16_units().collect();
module.push(0);
- let symbol = CString::from_slice(symbol.as_bytes());
+ let symbol = CString::new(symbol).unwrap();
let func = unsafe {
let handle = GetModuleHandleW(module.as_ptr());
GetProcAddress(handle, symbol.as_ptr()) as usize
let mut n = stack_buf.len();
loop {
let buf = if n <= stack_buf.len() {
- &mut stack_buf[]
+ &mut stack_buf[..]
} else {
let extra = n - heap_buf.len();
heap_buf.reserve(extra);
heap_buf.set_len(n);
- &mut heap_buf[]
+ &mut heap_buf[..]
};
// This function is typically called on windows API functions which
let (k, v) = match s.iter().position(|&b| b == '=' as u16) {
Some(n) => (&s[..n], &s[n+1..]),
- None => (s, &[][]),
+ None => (s, &[][..]),
};
Some((OsStringExt::from_wide(k), OsStringExt::from_wide(v)))
}
if !must_yield && in_progress.is_empty() {
None
} else {
- Some(super::os2path(&in_progress[]))
+ Some(super::os2path(&in_progress[..]))
}
}
}
return Err(JoinPathsError)
} else if v.contains(&sep) {
joined.push(b'"' as u16);
- joined.push_all(&v[]);
+ joined.push_all(&v[..]);
joined.push(b'"' as u16);
} else {
- joined.push_all(&v[]);
+ joined.push_all(&v[..]);
}
}
- Ok(OsStringExt::from_wide(&joined[]))
+ Ok(OsStringExt::from_wide(&joined[..]))
}
impl fmt::Display for JoinPathsError {
use prelude::v1::*;
-use collections::hash_map::Hasher;
+#[cfg(stage0)] use collections::hash_map::Hasher;
use collections;
use env;
use ffi::CString;
}
#[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>
})
}
}
+ #[allow(deprecated)]
+ #[cfg(not(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, 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 ()
+ })
+ }
+ }
/// Waits for a process to exit and returns the exit code, failing
/// if there is no process with the specified id.
}
}
+#[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,
_ => cb(ptr::null_mut())
}
}
+#[cfg(not(stage0))]
+fn with_envp<K, V, T, F>(env: Option<&collections::HashMap<K, V>>, cb: F) -> T
+ where K: BytesContainer + Eq + Hash,
+ 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())
+ }
+}
fn with_dirp<T, F>(d: Option<&CString>, cb: F) -> T where
F: FnOnce(*const u16) -> T,
use cell::UnsafeCell;
use fmt;
use io;
-use marker;
+use marker::PhantomData;
use old_io::stdio;
use rt::{self, unwind};
use sync::{Mutex, Condvar, Arc};
T: Send + 'a, F: FnOnce() -> T, F: Send + 'a
{
self.spawn_inner(Thunk::new(f)).map(|inner| {
- JoinGuard { inner: inner, _marker: marker::CovariantType }
+ JoinGuard { inner: inner, _marker: PhantomData }
})
}
#[stable(feature = "rust1", since = "1.0.0")]
pub struct JoinGuard<'a, T: 'a> {
inner: JoinInner<T>,
- _marker: marker::CovariantType<&'a T>,
+ _marker: PhantomData<&'a T>,
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Decodable for Ident {
fn decode<D: Decoder>(d: &mut D) -> Result<Ident, D::Error> {
- Ok(str_to_ident(&try!(d.read_str())[]))
+ Ok(str_to_ident(&try!(d.read_str())[..]))
}
}
if !s.is_empty() {
s.push_str("::");
}
- s.push_str(&e[]);
+ s.push_str(&e[..]);
s
})
}
}
fn find_entry(&self, id: NodeId) -> Option<MapEntry<'ast>> {
- self.map.borrow().get(id as usize).map(|e| *e)
+ self.map.borrow().get(id as usize).cloned()
}
pub fn krate(&self) -> &'ast Crate {
F: FnOnce(Option<&[Attribute]>) -> T,
{
let attrs = match self.get(id) {
- NodeItem(i) => Some(&i.attrs[]),
- NodeForeignItem(fi) => Some(&fi.attrs[]),
+ NodeItem(i) => Some(&i.attrs[..]),
+ NodeForeignItem(fi) => Some(&fi.attrs[..]),
NodeTraitItem(ref tm) => match **tm {
- RequiredMethod(ref type_m) => Some(&type_m.attrs[]),
- ProvidedMethod(ref m) => Some(&m.attrs[]),
- TypeTraitItem(ref typ) => Some(&typ.attrs[]),
+ RequiredMethod(ref type_m) => Some(&type_m.attrs[..]),
+ ProvidedMethod(ref m) => Some(&m.attrs[..]),
+ TypeTraitItem(ref typ) => Some(&typ.attrs[..]),
},
NodeImplItem(ref ii) => {
match **ii {
- MethodImplItem(ref m) => Some(&m.attrs[]),
- TypeImplItem(ref t) => Some(&t.attrs[]),
+ MethodImplItem(ref m) => Some(&m.attrs[..]),
+ TypeImplItem(ref t) => Some(&t.attrs[..]),
}
}
- NodeVariant(ref v) => Some(&v.node.attrs[]),
+ NodeVariant(ref v) => Some(&v.node.attrs[..]),
// unit/tuple structs take the attributes straight from
// the struct definition.
// FIXME(eddyb) make this work again (requires access to the map).
None => return false,
Some((node_id, name)) => (node_id, name),
};
- if &part[] != mod_name.as_str() {
+ if &part[..] != mod_name.as_str() {
return false;
}
cursor = self.map.get_parent(mod_id);
// We are looking at some node `n` with a given name and parent
// id; do their names match what I am seeking?
fn matches_names(&self, parent_of_n: NodeId, name: Name) -> bool {
- name.as_str() == &self.item_name[] &&
+ name.as_str() == &self.item_name[..] &&
self.suffix_matches(parent_of_n)
}
}
fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
let id_str = format!(" (id={})", id);
- let id_str = if include_id { &id_str[] } else { "" };
+ let id_str = if include_id { &id_str[..] } else { "" };
match map.find(id) {
Some(NodeItem(item)) => {
match *trait_ref {
Some(ref trait_ref) => {
pretty.push('.');
- pretty.push_str(&pprust::path_to_string(&trait_ref.path)[]);
+ pretty.push_str(&pprust::path_to_string(&trait_ref.path));
}
None => {}
}
- token::gensym_ident(&pretty[])
+ token::gensym_ident(&pretty[..])
}
pub fn trait_method_to_ty_method(method: &Method) -> TypeMethod {
pub fn path_name_eq(a : &ast::Path, b : &ast::Path) -> bool {
(a.span == b.span)
&& (a.global == b.global)
- && (segments_name_eq(&a.segments[], &b.segments[]))
+ && (segments_name_eq(&a.segments[..], &b.segments[..]))
}
// are two arrays of segments equal when compared unhygienically?
use ptr::P;
use std::cell::{RefCell, Cell};
-use std::collections::BitvSet;
+use std::collections::BitSet;
use std::collections::HashSet;
use std::fmt;
-thread_local! { static USED_ATTRS: RefCell<BitvSet> = RefCell::new(BitvSet::new()) }
+thread_local! { static USED_ATTRS: RefCell<BitSet> = RefCell::new(BitSet::new()) }
pub fn mark_used(attr: &Attribute) {
let AttrId(id) = attr.node.id;
pub trait AttrMetaMethods {
fn check_name(&self, name: &str) -> bool {
- name == &self.name()[]
+ name == &self.name()[..]
}
/// Retrieve the name of the meta item, e.g. `foo` in `#[foo]`,
impl AttrMetaMethods for Attribute {
fn check_name(&self, name: &str) -> bool {
- let matches = name == &self.name()[];
+ let matches = name == &self.name()[..];
if matches {
mark_used(self);
}
fn meta_item_list<'a>(&'a self) -> Option<&'a [P<MetaItem>]> {
match self.node {
- MetaList(_, ref l) => Some(&l[]),
+ MetaList(_, ref l) => Some(&l[..]),
_ => None
}
}
let meta = mk_name_value_item_str(
InternedString::new("doc"),
token::intern_and_get_ident(&strip_doc_comment_decoration(
- &comment)[]));
+ &comment)));
if self.node.style == ast::AttrOuter {
f(&mk_attr_outer(self.node.id, meta))
} else {
}
MetaList(ref n, ref items) if *n == "inline" => {
mark_used(attr);
- if contains_name(&items[], "always") {
+ if contains_name(&items[..], "always") {
InlineAlways
- } else if contains_name(&items[], "never") {
+ } else if contains_name(&items[..], "never") {
InlineNever
} else {
InlineHint
/// Tests if a cfg-pattern matches the cfg set
pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P<MetaItem>], cfg: &ast::MetaItem) -> bool {
match cfg.node {
- ast::MetaList(ref pred, ref mis) if &pred[] == "any" =>
+ ast::MetaList(ref pred, ref mis) if &pred[..] == "any" =>
mis.iter().any(|mi| cfg_matches(diagnostic, cfgs, &**mi)),
- ast::MetaList(ref pred, ref mis) if &pred[] == "all" =>
+ ast::MetaList(ref pred, ref mis) if &pred[..] == "all" =>
mis.iter().all(|mi| cfg_matches(diagnostic, cfgs, &**mi)),
- ast::MetaList(ref pred, ref mis) if &pred[] == "not" => {
+ ast::MetaList(ref pred, ref mis) if &pred[..] == "not" => {
if mis.len() != 1 {
diagnostic.span_err(cfg.span, "expected 1 cfg-pattern");
return false;
'outer: for attr in attrs {
let tag = attr.name();
- let tag = &tag[];
+ let tag = &tag[..];
if tag != "deprecated" && tag != "unstable" && tag != "stable" {
continue // not a stability level
}
}
}
}
- if &meta.name()[] == "since" {
+ if &meta.name()[..] == "since" {
match meta.value_str() {
Some(v) => since = Some(v),
None => {
}
}
}
- if &meta.name()[] == "reason" {
+ if &meta.name()[..] == "reason" {
match meta.value_str() {
Some(v) => reason = Some(v),
None => {
if !set.insert(name.clone()) {
diagnostic.span_fatal(meta.span,
- &format!("duplicate meta item `{}`", name)[]);
+ &format!("duplicate meta item `{}`", name));
}
}
}
for item in items {
match item.node {
ast::MetaWord(ref word) => {
- let hint = match &word[] {
+ let hint = match &word[..] {
// Can't use "extern" because it's not a lexical identifier.
"C" => Some(ReprExtern),
"packed" => Some(ReprPacked),
let mut src = if src.starts_with("\u{feff}") {
String::from_str(&src[3..])
} else {
- String::from_str(&src[])
+ String::from_str(&src[..])
};
// Append '\n' in case it's not already there.
}
};
- if attr::cfg_matches(self.diag, &self.config[], &cfg) {
+ if attr::cfg_matches(self.diag, &self.config[..], &cfg) {
Some(respan(mi.span, ast::Attribute_ {
id: attr::mk_attr_id(),
style: attr.node.style,
panic!(ExplicitBug);
}
pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
- self.span_bug(sp, &format!("unimplemented {}", msg)[]);
+ self.span_bug(sp, &format!("unimplemented {}", msg));
}
pub fn handler<'a>(&'a self) -> &'a Handler {
&self.handler
self.err_count.get());
}
}
- self.fatal(&s[]);
+ self.fatal(&s[..]);
}
pub fn warn(&self, msg: &str) {
self.emit.borrow_mut().emit(None, msg, None, Warning);
panic!(ExplicitBug);
}
pub fn unimpl(&self, msg: &str) -> ! {
- self.bug(&format!("unimplemented {}", msg)[]);
+ self.bug(&format!("unimplemented {}", msg));
}
pub fn emit(&self,
cmsp: Option<(&codemap::CodeMap, Span)>,
}
try!(print_maybe_styled(dst,
- &format!("{}: ", lvl.to_string())[],
+ &format!("{}: ", lvl.to_string()),
term::attr::ForegroundColor(lvl.color())));
try!(print_maybe_styled(dst,
- &format!("{}", msg)[],
+ &format!("{}", msg),
term::attr::Bold));
match code {
Some(code) => {
let style = term::attr::ForegroundColor(term::color::BRIGHT_MAGENTA);
- try!(print_maybe_styled(dst, &format!(" [{}]", code.clone())[], style));
+ try!(print_maybe_styled(dst, &format!(" [{}]", code.clone()), style));
}
None => ()
}
// the span)
let span_end = Span { lo: sp.hi, hi: sp.hi, expn_id: sp.expn_id};
let ses = cm.span_to_string(span_end);
- try!(print_diagnostic(dst, &ses[], lvl, msg, code));
+ try!(print_diagnostic(dst, &ses[..], lvl, msg, code));
if rsp.is_full_span() {
try!(custom_highlight_lines(dst, cm, sp, lvl, cm.span_to_lines(sp)));
}
} else {
- try!(print_diagnostic(dst, &ss[], lvl, msg, code));
+ try!(print_diagnostic(dst, &ss[..], lvl, msg, code));
if rsp.is_full_span() {
try!(highlight_lines(dst, cm, sp, lvl, cm.span_to_lines(sp)));
}
Some(code) =>
match dst.registry.as_ref().and_then(|registry| registry.find_description(code)) {
Some(_) => {
- try!(print_diagnostic(dst, &ss[], Help,
+ try!(print_diagnostic(dst, &ss[..], Help,
&format!("pass `--explain {}` to see a detailed \
- explanation", code)[], None));
+ explanation", code), None));
}
None => ()
},
let fm = &*lines.file;
let mut elided = false;
- let mut display_lines = &lines.lines[];
+ let mut display_lines = &lines.lines[..];
if display_lines.len() > MAX_LINES {
display_lines = &display_lines[0..MAX_LINES];
elided = true;
}
try!(print_maybe_styled(err,
- &format!("{}\n", s)[],
+ &format!("{}\n", s),
term::attr::ForegroundColor(lvl.color())));
}
}
-> old_io::IoResult<()> {
let fm = &*lines.file;
- let lines = &lines.lines[];
+ let lines = &lines.lines[..];
if lines.len() > MAX_LINES {
if let Some(line) = fm.get_line(lines[0]) {
try!(write!(&mut w.dst, "{}:{} {}\n", fm.name,
s.push('^');
s.push('\n');
print_maybe_styled(w,
- &s[],
+ &s[..],
term::attr::ForegroundColor(lvl.color()))
}
cm: &codemap::CodeMap,
sp: Span)
-> old_io::IoResult<()> {
- let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| match expn_info {
- Some(ei) => {
- let ss = ei.callee.span.map_or(String::new(), |span| cm.span_to_string(span));
- let (pre, post) = match ei.callee.format {
- codemap::MacroAttribute => ("#[", "]"),
- codemap::MacroBang => ("", "!")
- };
- try!(print_diagnostic(w, &ss[], Note,
- &format!("in expansion of {}{}{}", pre,
- ei.callee.name,
- post)[], None));
- let ss = cm.span_to_string(ei.call_site);
- try!(print_diagnostic(w, &ss[], Note, "expansion site", None));
- Ok(Some(ei.call_site))
- }
- None => Ok(None)
+ let cs = try!(cm.with_expn_info(sp.expn_id, |expn_info| -> old_io::IoResult<_> {
+ match expn_info {
+ Some(ei) => {
+ let ss = ei.callee.span.map_or(String::new(),
+ |span| cm.span_to_string(span));
+ let (pre, post) = match ei.callee.format {
+ codemap::MacroAttribute => ("#[", "]"),
+ codemap::MacroBang => ("", "!")
+ };
+ try!(print_diagnostic(w, &ss, Note,
+ &format!("in expansion of {}{}{}", pre,
+ ei.callee.name,
+ post), None));
+ let ss = cm.span_to_string(ei.call_site);
+ try!(print_diagnostic(w, &ss, Note, "expansion site", None));
+ Ok(Some(ei.call_site))
+ }
+ None => Ok(None)
+ }
}));
cs.map_or(Ok(()), |call_site| print_macro_backtrace(w, cm, call_site))
}
{
match opt {
Some(t) => t,
- None => diag.handler().bug(&msg()[]),
+ None => diag.handler().bug(&msg()),
}
}
Some(previous_span) => {
ecx.span_warn(span, &format!(
"diagnostic code {} already used", &token::get_ident(code)
- )[]);
+ ));
ecx.span_note(previous_span, "previous invocation");
},
None => ()
if !diagnostics.contains_key(&code.name) {
ecx.span_err(span, &format!(
"used diagnostic code {} not registered", &token::get_ident(code)
- )[]);
+ ));
}
});
MacExpr::new(quote_expr!(ecx, ()))
if diagnostics.insert(code.name, description).is_some() {
ecx.span_err(span, &format!(
"diagnostic code {} already registered", &token::get_ident(*code)
- )[]);
+ ));
}
});
let sym = Ident::new(token::gensym(&(
"__register_diagnostic_".to_string() + &token::get_ident(*code)
- )[]));
+ )));
MacItems::new(vec![quote_item!(ecx, mod $sym {}).unwrap()].into_iter())
}
impl Registry {
pub fn new(descriptions: &[(&'static str, &'static str)]) -> Registry {
- Registry { descriptions: descriptions.iter().map(|&tuple| tuple).collect() }
+ Registry { descriptions: descriptions.iter().cloned().collect() }
}
pub fn find_description(&self, code: &str) -> Option<&'static str> {
- self.descriptions.get(code).map(|desc| *desc)
+ self.descriptions.get(code).cloned()
}
}
pub fn mod_path(&self) -> Vec<ast::Ident> {
let mut v = Vec::new();
v.push(token::str_to_ident(&self.ecfg.crate_name[]));
- v.extend(self.mod_path.iter().map(|a| *a));
+ v.extend(self.mod_path.iter().cloned());
return v;
}
pub fn bt_push(&mut self, ei: ExpnInfo) {
}
base::MacExpr::new(cx.expr_str(
sp,
- token::intern_and_get_ident(&accumulator[])))
+ token::intern_and_get_ident(&accumulator[..])))
}
}
}
}
- let res = str_to_ident(&res_str[]);
+ let res = str_to_ident(&res_str[..]);
let e = P(ast::Expr {
id: ast::DUMMY_NODE_ID,
{
let name = match mitem.node {
MetaWord(ref tname) => {
- match &tname[] {
+ match &tname[..] {
"Copy" => "Copy",
"Send" | "Sync" => {
return cx.span_err(span,
"allow" | "warn" | "deny" | "forbid" => true,
_ => false,
}
- }).map(|a| a.clone()));
+ }).cloned());
push(P(ast::Item {
attrs: attrs,
..(*newitem).clone()
let mut ty_params = ty_params.into_vec();
// Copy the lifetimes
- lifetimes.extend(generics.lifetimes.iter().map(|l| (*l).clone()));
+ lifetimes.extend(generics.lifetimes.iter().cloned());
// Create the type parameters.
ty_params.extend(generics.ty_params.iter().map(|ty_param| {
span: self.span,
bound_lifetimes: wb.bound_lifetimes.clone(),
bounded_ty: wb.bounded_ty.clone(),
- bounds: OwnedSlice::from_vec(wb.bounds.iter().map(|b| b.clone()).collect())
+ bounds: OwnedSlice::from_vec(wb.bounds.iter().cloned().collect())
})
}
ast::WherePredicate::RegionPredicate(ref rb) => {
ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
span: self.span,
lifetime: rb.lifetime,
- bounds: rb.bounds.iter().map(|b| b.clone()).collect()
+ bounds: rb.bounds.iter().cloned().collect()
})
}
ast::WherePredicate::EqPredicate(ref we) => {
let opt_trait_ref = Some(trait_ref);
let ident = ast_util::impl_pretty_name(&opt_trait_ref, &*self_type);
let mut a = vec![attr];
- a.extend(self.attributes.iter().map(|a| a.clone()));
+ a.extend(self.attributes.iter().cloned());
cx.item(
self.span,
ident,
self,
struct_def,
type_ident,
- &self_args[],
- &nonself_args[])
+ &self_args[..],
+ &nonself_args[..])
} else {
method_def.expand_struct_method_body(cx,
self,
struct_def,
type_ident,
- &self_args[],
- &nonself_args[])
+ &self_args[..],
+ &nonself_args[..])
};
method_def.create_method(cx,
self,
enum_def,
type_ident,
- &self_args[],
- &nonself_args[])
+ &self_args[..],
+ &nonself_args[..])
} else {
method_def.expand_enum_method_body(cx,
self,
enum_def,
type_ident,
self_args,
- &nonself_args[])
+ &nonself_args[..])
};
method_def.create_method(cx,
.collect::<Vec<String>>();
let self_arg_idents = self_arg_names.iter()
- .map(|name|cx.ident_of(&name[]))
+ .map(|name|cx.ident_of(&name[..]))
.collect::<Vec<ast::Ident>>();
// The `vi_idents` will be bound, solely in the catch-all, to
// a series of let statements mapping each self_arg to a usize
// corresponding to its variant index.
let vi_idents: Vec<ast::Ident> = self_arg_names.iter()
- .map(|name| { let vi_suffix = format!("{}_vi", &name[]);
- cx.ident_of(&vi_suffix[]) })
+ .map(|name| { let vi_suffix = format!("{}_vi", &name[..]);
+ cx.ident_of(&vi_suffix[..]) })
.collect::<Vec<ast::Ident>>();
// Builds, via callback to call_substructure_method, the
// delegated expression that handles the catch-all case,
// using `__variants_tuple` to drive logic if necessary.
let catch_all_substructure = EnumNonMatchingCollapsed(
- self_arg_idents, &variants[], &vi_idents[]);
+ self_arg_idents, &variants[..], &vi_idents[..]);
// These arms are of the form:
// (Variant1, Variant1, ...) => Body1
idents
};
for self_arg_name in self_arg_names.tail() {
- let (p, idents) = mk_self_pat(cx, &self_arg_name[]);
+ let (p, idents) = mk_self_pat(cx, &self_arg_name[..]);
subpats.push(p);
self_pats_idents.push(idents);
}
&**variant,
field_tuples);
let arm_expr = self.call_substructure_method(
- cx, trait_, type_ident, &self_args[], nonself_args,
+ cx, trait_, type_ident, &self_args[..], nonself_args,
&substructure);
cx.arm(sp, vec![single_pat], arm_expr)
}
let arm_expr = self.call_substructure_method(
- cx, trait_, type_ident, &self_args[], nonself_args,
+ cx, trait_, type_ident, &self_args[..], nonself_args,
&catch_all_substructure);
// Builds the expression:
}
},
EnumNonMatchingCollapsed(ref all_args, _, tuple) =>
- enum_nonmatch_f(cx, trait_span, (&all_args[], tuple),
+ enum_nonmatch_f(cx, trait_span, (&all_args[..], tuple),
substructure.nonself_args),
StaticEnum(..) | StaticStruct(..) => {
cx.span_bug(trait_span, "static function in `derive`")
f(cx, trait_span, called)
},
EnumNonMatchingCollapsed(ref all_self_args, _, tuple) =>
- enum_nonmatch_f(cx, trait_span, (&all_self_args[], tuple),
+ enum_nonmatch_f(cx, trait_span, (&all_self_args[..], tuple),
substructure.nonself_args),
StaticEnum(..) | StaticStruct(..) => {
cx.span_bug(trait_span, "static function in `derive`")
use ext::build::AstBuilder;
use ext::deriving::generic::*;
use ext::deriving::generic::ty::*;
-use parse::token::InternedString;
use ptr::P;
pub fn expand_deriving_hash<F>(cx: &mut ExtCtxt,
{
let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None,
- vec!(box Literal(Path::new_local("__S"))), true);
- let generics = LifetimeBounds {
- lifetimes: Vec::new(),
- bounds: vec!(("__S",
- vec!(path_std!(cx, core::hash::Writer),
- path_std!(cx, core::hash::Hasher)))),
- };
- let args = Path::new_local("__S");
- let inline = cx.meta_word(span, InternedString::new("inline"));
- let attrs = vec!(cx.attribute(span, inline));
+ vec!(), true);
+ let arg = Path::new_local("__H");
let hash_trait_def = TraitDef {
span: span,
attributes: Vec::new(),
path: path,
additional_bounds: Vec::new(),
- generics: generics,
+ generics: LifetimeBounds::empty(),
methods: vec!(
MethodDef {
name: "hash",
- generics: LifetimeBounds::empty(),
+ generics: LifetimeBounds {
+ lifetimes: Vec::new(),
+ bounds: vec![("__H",
+ vec![path_std!(cx, core::hash::Hasher)])],
+ },
explicit_self: borrowed_explicit_self(),
- args: vec!(Ptr(box Literal(args), Borrowed(None, MutMutable))),
+ args: vec!(Ptr(box Literal(arg), Borrowed(None, MutMutable))),
ret_ty: nil_ty(),
- attributes: attrs,
+ attributes: vec![],
combine_substructure: combine_substructure(box |a, b, c| {
hash_substructure(a, b, c)
})
|i| push(i)))
}
- match &tname[] {
+ match &tname[..] {
"Clone" => expand!(clone::expand_deriving_clone),
"Hash" => expand!(hash::expand_deriving_hash),
let formatter = substr.nonself_args[0].clone();
let meth = cx.ident_of("write_fmt");
- let s = token::intern_and_get_ident(&format_string[]);
+ let s = token::intern_and_get_ident(&format_string[..]);
let format_string = cx.expr_str(span, s);
// phew, not our responsibility any more!
Some(v) => v
};
- let e = match env::var(&var[]) {
+ let e = match env::var(&var[..]) {
Err(..) => {
cx.expr_path(cx.path_all(sp,
true,
cx.ident_of("Some")),
vec!(cx.expr_str(sp,
token::intern_and_get_ident(
- &s[]))))
+ &s[..]))))
}
};
MacExpr::new(e)
}
}
- let e = match env::var(&var[]) {
+ let e = match env::var(&var[..]) {
Err(_) => {
cx.span_err(sp, &msg);
cx.expr_usize(sp, 0)
},
});
let fm = fresh_mark();
- let marked_before = mark_tts(&tts[], fm);
+ let marked_before = mark_tts(&tts[..], fm);
// The span that we pass to the expanders we want to
// be the root of the call stack. That's the most
let opt_parsed = {
let expanded = expandfun.expand(fld.cx,
mac_span,
- &marked_before[]);
+ &marked_before[..]);
parse_thunk(expanded)
};
let parsed = match opt_parsed {
fld.cx.span_err(
pth.span,
&format!("non-expression macro in expression position: {}",
- &extnamestr[]
+ &extnamestr[..]
)[]);
return None;
}
}
});
// mark before expansion:
- let marked_before = mark_tts(&tts[], fm);
- expander.expand(fld.cx, it.span, &marked_before[])
+ let marked_before = mark_tts(&tts[..], fm);
+ expander.expand(fld.cx, it.span, &marked_before[..])
}
IdentTT(ref expander, span) => {
if it.ident.name == parse::token::special_idents::invalid.name {
}
});
// mark before expansion:
- let marked_tts = mark_tts(&tts[], fm);
+ let marked_tts = mark_tts(&tts[..], fm);
expander.expand(fld.cx, it.span, it.ident, marked_tts)
}
MacroRulesTT => {
});
let fm = fresh_mark();
- let marked_before = mark_tts(&tts[], fm);
+ let marked_before = mark_tts(&tts[..], fm);
let mac_span = fld.cx.original_span();
let expanded = match expander.expand(fld.cx,
mac_span,
- &marked_before[]).make_pat() {
+ &marked_before[..]).make_pat() {
Some(e) => e,
None => {
fld.cx.span_err(
if valid_ident {
fld.cx.mod_push(it.ident);
}
- let macro_use = contains_macro_use(fld, &new_attrs[]);
+ let macro_use = contains_macro_use(fld, &new_attrs[..]);
let result = with_exts_frame!(fld.cx.syntax_env,
macro_use,
noop_fold_item(it, fld));
node: match node {
MacInvocTT(path, tts, ctxt) => {
MacInvocTT(self.fold_path(path),
- self.fold_tts(&tts[]),
+ self.fold_tts(&tts[..]),
mtwt::apply_mark(self.mark, ctxt))
}
},
.collect();
println!("varref #{}: {:?}, resolves to {}",idx, varref_idents, varref_name);
let string = token::get_ident(final_varref_ident);
- println!("varref's first segment's string: \"{}\"", &string[]);
+ println!("varref's first segment's string: \"{}\"", &string[..]);
println!("binding #{}: {}, resolves to {}",
binding_idx, bindings[binding_idx], binding_name);
mtwt::with_sctable(|x| mtwt::display_sctable(x));
let cxbinds: Vec<&ast::Ident> =
bindings.iter().filter(|b| {
let ident = token::get_ident(**b);
- let string = &ident[];
+ let string = &ident[..];
"xx" == string
}).collect();
- let cxbinds: &[&ast::Ident] = &cxbinds[];
+ let cxbinds: &[&ast::Ident] = &cxbinds[..];
let cxbind = match cxbinds {
[b] => b,
_ => panic!("expected just one binding for ext_cx")
}
};
let interned_name = token::get_ident(ident);
- let name = &interned_name[];
+ let name = &interned_name[..];
p.expect(&token::Eq);
let e = p.parse_expr();
let msg = format!("invalid reference to argument `{}` ({})",
arg, self.describe_num_args());
- self.ecx.span_err(self.fmtsp, &msg[]);
+ self.ecx.span_err(self.fmtsp, &msg[..]);
return;
}
{
Some(e) => e.span,
None => {
let msg = format!("there is no argument named `{}`", name);
- self.ecx.span_err(self.fmtsp, &msg[]);
+ self.ecx.span_err(self.fmtsp, &msg[..]);
return;
}
};
-> P<ast::Expr> {
let trait_ = match *ty {
Known(ref tyname) => {
- match &tyname[] {
+ match &tyname[..] {
"" => "Display",
"?" => "Debug",
"e" => "LowerExp",
for i in 0..tt.len() {
seq.push(tt.get_tt(i));
}
- mk_tts(cx, &seq[])
+ mk_tts(cx, &seq[..])
}
ast::TtToken(sp, ref tok) => {
let e_sp = cx.expr_ident(sp, id_ext("_sp"));
let stmt_let_tt = cx.stmt_let(sp, true, id_ext("tt"), cx.expr_vec_ng(sp));
let mut vector = vec!(stmt_let_sp, stmt_let_tt);
- vector.extend(mk_tts(cx, &tts[]).into_iter());
+ vector.extend(mk_tts(cx, &tts[..]).into_iter());
let block = cx.expr_block(
cx.block_all(sp,
vector,
-> Box<base::MacResult+'static> {
let s = pprust::tts_to_string(tts);
base::MacExpr::new(cx.expr_str(sp,
- token::intern_and_get_ident(&s[])))
+ token::intern_and_get_ident(&s[..])))
}
pub fn expand_mod(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
.connect("::");
base::MacExpr::new(cx.expr_str(
sp,
- token::intern_and_get_ident(&string[])))
+ token::intern_and_get_ident(&string[..])))
}
/// include! : parse the given file as an expr
None => self.p.span_fatal(
self.p.span,
&format!("expected item, found `{}`",
- self.p.this_token_to_string())[]
+ self.p.this_token_to_string())
)
}
}
cx.span_err(sp,
&format!("couldn't read {}: {}",
file.display(),
- e)[]);
+ e));
return DummyResult::expr(sp);
}
Ok(bytes) => bytes,
// Add this input file to the code map to make it available as
// dependency information
let filename = format!("{}", file.display());
- let interned = token::intern_and_get_ident(&src[]);
+ let interned = token::intern_and_get_ident(&src[..]);
cx.codemap().new_filemap(filename, src);
base::MacExpr::new(cx.expr_str(sp, interned))
Err(_) => {
cx.span_err(sp,
&format!("{} wasn't a utf-8 file",
- file.display())[]);
+ file.display()));
return DummyResult::expr(sp);
}
}
match File::open(&file).read_to_end() {
Err(e) => {
cx.span_err(sp,
- &format!("couldn't read {}: {}", file.display(), e)[]);
+ &format!("couldn't read {}: {}", file.display(), e));
return DummyResult::expr(sp);
}
Ok(bytes) => {
- let bytes = bytes.iter().map(|x| *x).collect();
+ let bytes = bytes.iter().cloned().collect();
base::MacExpr::new(cx.expr_lit(sp, ast::LitBinary(Rc::new(bytes))))
}
}
pub fn initial_matcher_pos(ms: Rc<Vec<TokenTree>>, sep: Option<Token>, lo: BytePos)
-> Box<MatcherPos> {
- let match_idx_hi = count_names(&ms[]);
+ let match_idx_hi = count_names(&ms[..]);
let matches: Vec<_> = (0..match_idx_hi).map(|_| Vec::new()).collect();
box MatcherPos {
stack: vec![],
p_s.span_diagnostic
.span_fatal(sp,
&format!("duplicated bind name: {}",
- &string)[])
+ &string))
}
}
}
rdr: TtReader,
ms: Vec<TokenTree> )
-> HashMap<Ident, Rc<NamedMatch>> {
- match parse(sess, cfg, rdr, &ms[]) {
+ match parse(sess, cfg, rdr, &ms[..]) {
Success(m) => m,
Failure(sp, str) => {
- sess.span_diagnostic.span_fatal(sp, &str[])
+ sess.span_diagnostic.span_fatal(sp, &str[..])
}
Error(sp, str) => {
- sess.span_diagnostic.span_fatal(sp, &str[])
+ sess.span_diagnostic.span_fatal(sp, &str[..])
}
}
}
-> ParseResult {
let mut cur_eis = Vec::new();
cur_eis.push(initial_matcher_pos(Rc::new(ms.iter()
- .map(|x| (*x).clone())
+ .cloned()
.collect()),
None,
rdr.peek().sp.lo));
for dv in &mut (&mut eof_eis[0]).matches {
v.push(dv.pop().unwrap());
}
- return Success(nameize(sess, ms, &v[]));
+ return Success(nameize(sess, ms, &v[..]));
} else if eof_eis.len() > 1 {
return Error(sp, "ambiguity: multiple successful parses".to_string());
} else {
_ => {
let token_str = pprust::token_to_string(&p.token);
p.fatal(&format!("expected ident, found {}",
- &token_str[])[])
+ &token_str[..]))
}
},
"path" => {
"meta" => token::NtMeta(p.parse_meta_item()),
_ => {
p.span_fatal_help(sp,
- &format!("invalid fragment specifier `{}`", name)[],
+ &format!("invalid fragment specifier `{}`", name),
"valid fragment specifiers are `ident`, `block`, \
`stmt`, `expr`, `pat`, `ty`, `path`, `meta`, `tt` \
and `item`")
following",
token_str);
let span = parser.span;
- parser.span_err(span, &msg[]);
+ parser.span_err(span, &msg[..]);
}
}
}
self.name,
self.imported_from,
arg,
- &self.lhses[],
- &self.rhses[])
+ &self.lhses,
+ &self.rhses)
}
}
match **lhs {
MatchedNonterminal(NtTT(ref lhs_tt)) => {
let lhs_tt = match **lhs_tt {
- TtDelimited(_, ref delim) => &delim.tts[],
+ TtDelimited(_, ref delim) => &delim.tts[..],
_ => cx.span_fatal(sp, "malformed macro lhs")
};
// `None` is because we're not interpolating
None,
None,
arg.iter()
- .map(|x| (*x).clone())
+ .cloned()
.collect(),
true);
match parse(cx.parse_sess(), cx.cfg(), arg_rdr, lhs_tt) {
best_fail_spot = sp;
best_fail_msg = (*msg).clone();
},
- Error(sp, ref msg) => cx.span_fatal(sp, &msg[])
+ Error(sp, ref msg) => cx.span_fatal(sp, &msg[..])
}
}
_ => cx.bug("non-matcher found in parsed lhses")
}
}
- cx.span_fatal(best_fail_spot, &best_fail_msg[]);
+ cx.span_fatal(best_fail_spot, &best_fail_msg[..]);
}
// Note that macro-by-example's input is also matched against a token tree:
}
LisContradiction(ref msg) => {
// FIXME #2887 blame macro invoker instead
- r.sp_diag.span_fatal(sp.clone(), &msg[]);
+ r.sp_diag.span_fatal(sp.clone(), &msg[..]);
}
LisConstraint(len, _) => {
if len == 0 {
r.sp_diag.span_fatal(
r.cur_span, /* blame the macro writer */
&format!("variable '{:?}' is still repeating at this depth",
- token::get_ident(ident))[]);
+ token::get_ident(ident)));
}
}
}
diag.span_err(span, explain);
diag.span_help(span, &format!("add #![feature({})] to the \
crate attributes to enable",
- feature)[]);
+ feature));
}
pub fn emit_feature_warn(diag: &SpanHandler, feature: &str, span: Span, explain: &str) {
if diag.handler.can_emit_warnings {
diag.span_help(span, &format!("add #![feature({})] to the \
crate attributes to silence this warning",
- feature)[]);
+ feature));
}
}
fn visit_item(&mut self, i: &ast::Item) {
match i.node {
ast::ItemExternCrate(_) => {
- if attr::contains_name(&i.attrs[], "macro_reexport") {
+ if attr::contains_name(&i.attrs[..], "macro_reexport") {
self.gate_feature("macro_reexport", i.span,
"macros reexports are experimental \
and possibly buggy");
}
ast::ItemForeignMod(ref foreign_module) => {
- if attr::contains_name(&i.attrs[], "link_args") {
+ if attr::contains_name(&i.attrs[..], "link_args") {
self.gate_feature("link_args", i.span,
"the `link_args` attribute is not portable \
across platforms, it is recommended to \
}
ast::ItemFn(..) => {
- if attr::contains_name(&i.attrs[], "plugin_registrar") {
+ if attr::contains_name(&i.attrs[..], "plugin_registrar") {
self.gate_feature("plugin_registrar", i.span,
"compiler plugins are experimental and possibly buggy");
}
- if attr::contains_name(&i.attrs[], "start") {
+ if attr::contains_name(&i.attrs[..], "start") {
self.gate_feature("start", i.span,
"a #[start] function is an experimental \
feature whose signature may change \
over time");
}
- if attr::contains_name(&i.attrs[], "main") {
+ if attr::contains_name(&i.attrs[..], "main") {
self.gate_feature("main", i.span,
"declaration of a nonstandard #[main] \
function may change over time, for now \
}
ast::ItemStruct(..) => {
- if attr::contains_name(&i.attrs[], "simd") {
+ if attr::contains_name(&i.attrs[..], "simd") {
self.gate_feature("simd", i.span,
"SIMD types are experimental and possibly buggy");
}
removed in the future");
}
- if attr::contains_name(&i.attrs[],
+ if attr::contains_name(&i.attrs[..],
"old_orphan_check") {
self.gate_feature(
"old_orphan_check",
"the new orphan check rules will eventually be strictly enforced");
}
- if attr::contains_name(&i.attrs[],
+ if attr::contains_name(&i.attrs[..],
"old_impl_check") {
self.gate_feature("old_impl_check",
i.span,
}
fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
- if attr::contains_name(&i.attrs[], "linkage") {
+ if attr::contains_name(&i.attrs, "linkage") {
self.gate_feature("linkage", i.span,
"the `linkage` attribute is experimental \
and not portable across platforms")
#![feature(collections)]
#![feature(core)]
#![feature(env)]
-#![feature(hash)]
#![feature(int_uint)]
#![feature(old_io)]
#![feature(libc)]
use std::default::Default;
use std::fmt;
-use std::iter::FromIterator;
+use std::iter::{IntoIterator, FromIterator};
use std::ops::Deref;
use std::vec;
use serialize::{Encodable, Decodable, Encoder, Decoder};
}
impl<T> FromIterator<T> for OwnedSlice<T> {
- fn from_iter<I: Iterator<Item=T>>(iter: I) -> OwnedSlice<T> {
- OwnedSlice::from_vec(iter.collect())
+ fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> OwnedSlice<T> {
+ OwnedSlice::from_vec(iter.into_iter().collect())
}
}
pub fn strip_doc_comment_decoration(comment: &str) -> String {
/// remove whitespace-only lines from the start/end of lines
- fn vertical_trim(lines: Vec<String> ) -> Vec<String> {
+ fn vertical_trim(lines: Vec<String>) -> Vec<String> {
let mut i = 0;
let mut j = lines.len();
// first line of all-stars should be omitted
while j > i && lines[j - 1].trim().is_empty() {
j -= 1;
}
- return lines[i..j].iter().map(|x| (*x).clone()).collect();
+ lines[i..j].iter().cloned().collect()
}
/// remove a "[ \t]*\*" block from each line, if possible
let line = rdr.read_one_line_comment();
debug!("{}", line);
// Doc comments are not put in comments.
- if is_doc_comment(&line[]) {
+ if is_doc_comment(&line[..]) {
break;
}
lines.push(line);
fn trim_whitespace_prefix_and_push_line(lines: &mut Vec<String> ,
s: String, col: CharPos) {
let len = s.len();
- let s1 = match all_whitespace(&s[], col) {
+ let s1 = match all_whitespace(&s[..], col) {
Some(col) => {
if col < len {
(&s[col..len]).to_string()
rdr.bump();
rdr.bump();
}
- if is_block_doc_comment(&curr_line[]) {
+ if is_block_doc_comment(&curr_line[..]) {
return
}
assert!(!curr_line.contains_char('\n'));
use parse::token;
use parse::token::{str_to_ident};
-use std::borrow::IntoCow;
+use std::borrow::{IntoCow, Cow};
use std::char;
use std::fmt;
use std::mem::replace;
use std::num;
use std::rc::Rc;
use std::str;
-use std::string::CowString;
pub use ext::tt::transcribe::{TtReader, new_tt_reader, new_tt_reader_with_doc_flag};
let mut m = m.to_string();
m.push_str(": ");
for c in c.escape_default() { m.push(c) }
- self.fatal_span_(from_pos, to_pos, &m[]);
+ self.fatal_span_(from_pos, to_pos, &m[..]);
}
/// Report a lexical error spanning [`from_pos`, `to_pos`), appending an
let mut m = m.to_string();
m.push_str(": ");
for c in c.escape_default() { m.push(c) }
- self.err_span_(from_pos, to_pos, &m[]);
+ self.err_span_(from_pos, to_pos, &m[..]);
}
/// Report a lexical error spanning [`from_pos`, `to_pos`), appending the
let from = self.byte_offset(from_pos).to_usize();
let to = self.byte_offset(to_pos).to_usize();
m.push_str(&self.filemap.src[from..to]);
- self.fatal_span_(from_pos, to_pos, &m[]);
+ self.fatal_span_(from_pos, to_pos, &m[..]);
}
/// Advance peek_tok and peek_span to refer to the next token, and
/// Converts CRLF to LF in the given string, raising an error on bare CR.
fn translate_crlf<'b>(&self, start: BytePos,
- s: &'b str, errmsg: &'b str) -> CowString<'b> {
+ s: &'b str, errmsg: &'b str) -> Cow<'b, str> {
let mut i = 0;
while i < s.len() {
let str::CharRange { ch, next } = s.char_range_at(i);
self.translate_crlf(start_bpos, string,
"bare CR not allowed in block doc-comment")
} else { string.into_cow() };
- token::DocComment(token::intern(&string[]))
+ token::DocComment(token::intern(&string[..]))
} else {
token::Comment
};
unreachable!()
}
};
- match str::from_utf8(&bytes[]).ok() {
+ match str::from_utf8(&bytes[..]).ok() {
Some(s) => {
return string_to_filemap(sess, s.to_string(),
path.as_str().unwrap().to_string())
}
let msg = format!("lexer should have rejected a bad character escape {}", lit);
- let msg2 = &msg[];
+ let msg2 = &msg[..];
fn esc(len: usize, lit: &str) -> Option<(char, isize)> {
num::from_str_radix(&lit[2..len], 16).ok()
// s can only be ascii, byte indexing is fine
let s2 = s.chars().filter(|&c| c != '_').collect::<String>();
- let mut s = &s2[];
+ let mut s = &s2[..];
debug!("integer_lit: {}, {:?}", s, suffix);
#[test]
fn string_to_tts_macro () {
let tts = string_to_tts("macro_rules! zip (($a)=>($a))".to_string());
- let tts: &[ast::TokenTree] = &tts[];
+ let tts: &[ast::TokenTree] = &tts[..];
match tts {
[ast::TtToken(_, token::Ident(name_macro_rules, token::Plain)),
ast::TtToken(_, token::Not),
let use_s = "use foo::bar::baz;";
let vitem = string_to_item(use_s.to_string()).unwrap();
let vitem_s = item_to_string(&*vitem);
- assert_eq!(&vitem_s[], use_s);
+ assert_eq!(&vitem_s[..], use_s);
let use_s = "use foo::bar as baz;";
let vitem = string_to_item(use_s.to_string()).unwrap();
let vitem_s = item_to_string(&*vitem);
- assert_eq!(&vitem_s[], use_s);
+ assert_eq!(&vitem_s[..], use_s);
}
#[test] fn parse_extern_crate() {
let ex_s = "extern crate foo;";
let vitem = string_to_item(ex_s.to_string()).unwrap();
let vitem_s = item_to_string(&*vitem);
- assert_eq!(&vitem_s[], ex_s);
+ assert_eq!(&vitem_s[..], ex_s);
let ex_s = "extern crate \"foo\" as bar;";
let vitem = string_to_item(ex_s.to_string()).unwrap();
let vitem_s = item_to_string(&*vitem);
- assert_eq!(&vitem_s[], ex_s);
+ assert_eq!(&vitem_s[..], ex_s);
}
fn get_spans_of_pat_idents(src: &str) -> Vec<Span> {
let source = "/// doc comment\r\nfn foo() {}".to_string();
let item = parse_item_from_source_str(name.clone(), source, Vec::new(), &sess).unwrap();
let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap();
- assert_eq!(&doc[], "/// doc comment");
+ assert_eq!(&doc[..], "/// doc comment");
let source = "/// doc comment\r\n/// line 2\r\nfn foo() {}".to_string();
let item = parse_item_from_source_str(name.clone(), source, Vec::new(), &sess).unwrap();
let docs = item.attrs.iter().filter(|a| &a.name()[] == "doc")
.map(|a| a.value_str().unwrap().to_string()).collect::<Vec<_>>();
let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()];
- assert_eq!(&docs[], b);
+ assert_eq!(&docs[..], b);
let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string();
let item = parse_item_from_source_str(name, source, Vec::new(), &sess).unwrap();
let doc = first_attr_value_str_by_name(&item.attrs, "doc").unwrap();
- assert_eq!(&doc[], "/** doc comment\n * with CRLF */");
+ assert_eq!(&doc[..], "/** doc comment\n * with CRLF */");
}
#[test]
let span = tts.iter().rev().next().unwrap().get_span();
match sess.span_diagnostic.cm.span_to_snippet(span) {
- Ok(s) => assert_eq!(&s[], "{ body }"),
+ Ok(s) => assert_eq!(&s[..], "{ body }"),
Err(_) => panic!("could not get snippet"),
}
}
ProcExpr,
ClosureType,
ClosureKind,
+ EmptyIndex,
}
pub trait ParserObsoleteMethods {
sp: Span,
kind: ObsoleteSyntax,
kind_str: &str,
- desc: &str);
+ desc: &str,
+ error: bool);
fn is_obsolete_ident(&mut self, ident: &str) -> bool;
fn eat_obsolete_ident(&mut self, ident: &str) -> bool;
}
impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
/// Reports an obsolete syntax non-fatal error.
fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
- let (kind_str, desc) = match kind {
+ let (kind_str, desc, error) = match kind {
ObsoleteSyntax::ForSized => (
"for Sized?",
"no longer required. Traits (and their `Self` type) do not have the `Sized` bound \
by default",
+ true,
),
ObsoleteSyntax::ProcType => (
"the `proc` type",
"use unboxed closures instead",
+ true,
),
ObsoleteSyntax::ProcExpr => (
"`proc` expression",
"use a `move ||` expression instead",
+ true,
),
ObsoleteSyntax::ClosureType => (
"`|usize| -> bool` closure type",
- "use unboxed closures instead, no type annotation needed"
+ "use unboxed closures instead, no type annotation needed",
+ true,
),
ObsoleteSyntax::ClosureKind => (
"`:`, `&mut:`, or `&:`",
- "rely on inference instead"
+ "rely on inference instead",
+ true,
),
ObsoleteSyntax::Sized => (
"`Sized? T` for removing the `Sized` bound",
- "write `T: ?Sized` instead"
+ "write `T: ?Sized` instead",
+ true,
+ ),
+ ObsoleteSyntax::EmptyIndex => (
+ "[]",
+ "write `[..]` instead",
+ false, // warning for now
),
};
- self.report(sp, kind, kind_str, desc);
+ self.report(sp, kind, kind_str, desc, error);
}
/// Reports an obsolete syntax non-fatal error, and returns
sp: Span,
kind: ObsoleteSyntax,
kind_str: &str,
- desc: &str) {
- self.span_err(sp,
- &format!("obsolete syntax: {}", kind_str)[]);
+ desc: &str,
+ error: bool) {
+ if error {
+ self.span_err(sp, &format!("obsolete syntax: {}", kind_str)[]);
+ } else {
+ self.span_warn(sp, &format!("obsolete syntax: {}", kind_str)[]);
+ }
if !self.obsolete_set.contains(&kind) {
self.sess
fn maybe_append(mut lhs: Vec<Attribute>, rhs: Option<Vec<Attribute>>)
-> Vec<Attribute> {
- match rhs {
- Some(ref attrs) => lhs.extend(attrs.iter().map(|a| a.clone())),
- None => {}
+ if let Some(ref attrs) = rhs {
+ lhs.extend(attrs.iter().cloned())
}
lhs
}
let token_str = Parser::token_to_string(t);
let last_span = self.last_span;
self.span_fatal(last_span, &format!("unexpected token: `{}`",
- token_str)[]);
+ token_str));
}
pub fn unexpected(&mut self) -> ! {
let this_token_str = self.this_token_to_string();
self.fatal(&format!("expected `{}`, found `{}`",
token_str,
- this_token_str)[])
+ this_token_str))
}
} else {
self.expect_one_of(slice::ref_slice(t), &[]);
expected.push_all(&*self.expected_tokens);
expected.sort_by(|a, b| a.to_string().cmp(&b.to_string()));
expected.dedup();
- let expect = tokens_to_string(&expected[]);
+ let expect = tokens_to_string(&expected[..]);
let actual = self.this_token_to_string();
self.fatal(
&(if expected.len() > 1 {
(format!("expected {}, found `{}`",
expect,
actual))
- }[])
+ })[..]
)
}
}
debug!("commit_expr {:?}", e);
if let ExprPath(..) = e.node {
// might be unit-struct construction; check for recoverableinput error.
- let mut expected = edible.iter().map(|x| x.clone()).collect::<Vec<_>>();
+ let mut expected = edible.iter().cloned().collect::<Vec<_>>();
expected.push_all(inedible);
- self.check_for_erroneous_unit_struct_expecting(&expected[]);
+ self.check_for_erroneous_unit_struct_expecting(&expected[..]);
}
self.expect_one_of(edible, inedible)
}
if self.last_token
.as_ref()
.map_or(false, |t| t.is_ident() || t.is_path()) {
- let mut expected = edible.iter().map(|x| x.clone()).collect::<Vec<_>>();
- expected.push_all(&inedible[]);
- self.check_for_erroneous_unit_struct_expecting(
- &expected[]);
+ let mut expected = edible.iter().cloned().collect::<Vec<_>>();
+ expected.push_all(&inedible);
+ self.check_for_erroneous_unit_struct_expecting(&expected);
}
self.expect_one_of(edible, inedible)
}
_ => {
let token_str = self.this_token_to_string();
self.fatal(&format!("expected ident, found `{}`",
- token_str)[])
+ token_str))
}
}
}
let span = self.span;
self.span_err(span,
&format!("expected identifier, found keyword `{}`",
- token_str)[]);
+ token_str));
}
}
if self.token.is_reserved_keyword() {
let token_str = self.this_token_to_string();
self.fatal(&format!("`{}` is a reserved keyword",
- token_str)[])
+ token_str))
}
}
let this_token_str = self.this_token_to_string();
self.fatal(&format!("expected `{}`, found `{}`",
gt_str,
- this_token_str)[])
+ this_token_str))
}
}
}
let (inner_attrs, body) =
p.parse_inner_attrs_and_block();
let mut attrs = attrs;
- attrs.push_all(&inner_attrs[]);
+ attrs.push_all(&inner_attrs[..]);
ProvidedMethod(P(ast::Method {
attrs: attrs,
id: ast::DUMMY_NODE_ID,
_ => {
let token_str = p.this_token_to_string();
p.fatal(&format!("expected `;` or `{{`, found `{}`",
- token_str)[])
+ token_str)[..])
}
}
}
} else {
let this_token_str = self.this_token_to_string();
let msg = format!("expected type, found `{}`", this_token_str);
- self.fatal(&msg[]);
+ self.fatal(&msg[..]);
};
let sp = mk_sp(lo, self.last_span.hi);
token::StrRaw(s, n) => {
(true,
LitStr(
- token::intern_and_get_ident(&parse::raw_str_lit(s.as_str())[]),
+ token::intern_and_get_ident(&parse::raw_str_lit(s.as_str())),
ast::RawStr(n)))
}
token::Binary(i) =>
(true, LitBinary(parse::binary_lit(i.as_str()))),
token::BinaryRaw(i, _) =>
(true,
- LitBinary(Rc::new(i.as_str().as_bytes().iter().map(|&x| x).collect()))),
+ LitBinary(Rc::new(i.as_str().as_bytes().iter().cloned().collect()))),
};
if suffix_illegal {
};
}
_ => {
- self.fatal(&format!("expected a lifetime name")[]);
+ self.fatal(&format!("expected a lifetime name"));
}
}
}
let msg = format!("expected `,` or `>` after lifetime \
name, found `{}`",
this_token_str);
- self.fatal(&msg[]);
+ self.fatal(&msg[..]);
}
}
}
let last_span = self.last_span;
let fstr = n.as_str();
self.span_err(last_span,
- &format!("unexpected token: `{}`", n.as_str())[]);
+ &format!("unexpected token: `{}`", n.as_str()));
if fstr.chars().all(|x| "0123456789.".contains_char(x)) {
let float = match fstr.parse::<f64>().ok() {
Some(f) => f,
self.span_help(last_span,
&format!("try parenthesizing the first index; e.g., `(foo.{}){}`",
float.trunc() as usize,
- &float.fract().to_string()[1..])[]);
+ &float.fract().to_string()[1..]));
}
self.abort_if_errors();
parameters: ast::PathParameters::none(),
}
}).collect();
+ let span = mk_sp(lo, hi);
let path = ast::Path {
- span: mk_sp(lo, hi),
+ span: span,
global: true,
segments: segments,
};
let ix = self.mk_expr(bracket_pos, hi, range);
let index = self.mk_index(e, ix);
e = self.mk_expr(lo, hi, index);
- // Enable after snapshot.
- // self.span_warn(e.span, "deprecated slicing syntax: `[]`");
- // self.span_note(e.span,
- // "use `&expr[..]` to construct a slice of the whole of expr");
+
+ self.obsolete(span, ObsoleteSyntax::EmptyIndex);
} else {
let ix = self.parse_expr();
hi = self.span.hi;
match self.token {
token::SubstNt(name, _) =>
self.fatal(&format!("unknown macro variable `{}`",
- token::get_ident(name))[]),
+ token::get_ident(name))),
_ => {}
}
}
};
let token_str = p.this_token_to_string();
p.fatal(&format!("incorrect close delimiter: `{}`",
- token_str)[])
+ token_str))
},
/* we ought to allow different depths of unquotation */
token::Dollar | token::SubstNt(..) if p.quote_depth > 0 => {
let this_token_to_string = self.this_token_to_string();
self.span_err(span,
&format!("expected expression, found `{}`",
- this_token_to_string)[]);
+ this_token_to_string));
let box_span = mk_sp(lo, self.last_span.hi);
self.span_help(box_span,
"perhaps you meant `box() (foo)` instead?");
if self.token != token::CloseDelim(token::Brace) {
let token_str = self.this_token_to_string();
self.fatal(&format!("expected `{}`, found `{}`", "}",
- token_str)[])
+ token_str))
}
etc = true;
break;
let span = self.span;
let tok_str = self.this_token_to_string();
self.span_fatal(span,
- &format!("expected identifier, found `{}`", tok_str)[]);
+ &format!("expected identifier, found `{}`", tok_str));
}
let ident = self.parse_ident();
let last_span = self.last_span;
let lo = self.span.lo;
if self.check_keyword(keywords::Let) {
- check_expected_item(self, &item_attrs[]);
+ check_expected_item(self, &item_attrs[..]);
self.expect_keyword(keywords::Let);
let decl = self.parse_let();
P(spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID)))
&& self.look_ahead(1, |t| *t == token::Not) {
// it's a macro invocation:
- check_expected_item(self, &item_attrs[]);
+ check_expected_item(self, &item_attrs[..]);
// Potential trouble: if we allow macros with paths instead of
// idents, we'd need to look ahead past the whole path here...
let tok_str = self.this_token_to_string();
self.fatal(&format!("expected {}`(` or `{{`, found `{}`",
ident_str,
- tok_str)[])
+ tok_str))
},
};
}
} else {
let found_attrs = !item_attrs.is_empty();
- let item_err = Parser::expected_item_err(&item_attrs[]);
+ let item_err = Parser::expected_item_err(&item_attrs[..]);
match self.parse_item_(item_attrs, false) {
Ok(i) => {
let hi = i.span.hi;
let sp = self.span;
let tok = self.this_token_to_string();
self.span_fatal_help(sp,
- &format!("expected `{{`, found `{}`", tok)[],
+ &format!("expected `{{`, found `{}`", tok),
"place this code inside a block");
}
while self.token != token::CloseDelim(token::Brace) {
// parsing items even when they're not allowed lets us give
// better error messages and recover more gracefully.
- attributes_box.push_all(&self.parse_outer_attributes()[]);
+ attributes_box.push_all(&self.parse_outer_attributes());
match self.token {
token::Semi => {
if !attributes_box.is_empty() {
let last_span = self.last_span;
self.span_err(last_span,
- Parser::expected_item_err(&attributes_box[]));
+ Parser::expected_item_err(&attributes_box[..]));
attributes_box = Vec::new();
}
self.bump(); // empty
if !attributes_box.is_empty() {
let last_span = self.last_span;
self.span_err(last_span,
- Parser::expected_item_err(&attributes_box[]));
+ Parser::expected_item_err(&attributes_box[..]));
}
let hi = self.span.hi;
_ => {
let token_str = self.this_token_to_string();
self.fatal(&format!("expected `self`, found `{}`",
- token_str)[])
+ token_str))
}
}
}
_ => {
let token_str = self.this_token_to_string();
self.fatal(&format!("expected `Self`, found `{}`",
- token_str)[])
+ token_str))
}
}
}
_ => {
let token_str = self.this_token_to_string();
self.fatal(&format!("expected `,` or `)`, found `{}`",
- token_str)[])
+ token_str))
}
}
}
let (inner_attrs, body) = self.parse_inner_attrs_and_block();
let body_span = body.span;
let mut new_attrs = attrs;
- new_attrs.push_all(&inner_attrs[]);
+ new_attrs.push_all(&inner_attrs[..]);
(ast::MethDecl(ident,
generics,
abi,
if fields.len() == 0 {
self.fatal(&format!("unit-like struct definition should be \
written as `struct {};`",
- token::get_ident(class_name.clone()))[]);
+ token::get_ident(class_name.clone())));
}
self.bump();
let token_str = self.this_token_to_string();
self.fatal(&format!("expected `where`, or `{}` after struct \
name, found `{}`", "{",
- token_str)[]);
+ token_str));
}
fields
if fields.len() == 0 {
self.fatal(&format!("unit-like struct definition should be \
written as `struct {};`",
- token::get_ident(class_name.clone()))[]);
+ token::get_ident(class_name.clone())));
}
self.parse_where_clause(generics);
} else {
let token_str = self.this_token_to_string();
self.fatal(&format!("expected `where`, `{}`, `(`, or `;` after struct \
- name, found `{}`", "{", token_str)[]);
+ name, found `{}`", "{", token_str));
}
}
let token_str = self.this_token_to_string();
self.span_fatal_help(span,
&format!("expected `,`, or `}}`, found `{}`",
- token_str)[],
+ token_str),
"struct fields should be separated by commas")
}
}
// Parse all of the items up to closing or an attribute.
let mut attrs = first_item_attrs;
- attrs.push_all(&self.parse_outer_attributes()[]);
+ attrs.push_all(&self.parse_outer_attributes());
let mut items = vec![];
loop {
while self.token != term {
let mut attrs = mem::replace(&mut attrs, vec![]);
- attrs.push_all(&self.parse_outer_attributes()[]);
+ attrs.push_all(&self.parse_outer_attributes());
debug!("parse_mod_items: parse_item_(attrs={:?})", attrs);
match self.parse_item_(attrs, true /* macros allowed */) {
Ok(item) => items.push(item),
Err(_) => {
let token_str = self.this_token_to_string();
self.fatal(&format!("expected item, found `{}`",
- token_str)[])
+ token_str))
}
}
}
// We parsed attributes for the first item but didn't find it
let last_span = self.last_span;
self.span_err(last_span,
- Parser::expected_item_err(&attrs[]));
+ Parser::expected_item_err(&attrs[..]));
}
ast::Mod {
let mod_name = mod_string.to_string();
let default_path_str = format!("{}.rs", mod_name);
let secondary_path_str = format!("{}/mod.rs", mod_name);
- let default_path = dir_path.join(&default_path_str[]);
- let secondary_path = dir_path.join(&secondary_path_str[]);
+ let default_path = dir_path.join(&default_path_str[..]);
+ let secondary_path = dir_path.join(&secondary_path_str[..]);
let default_exists = default_path.exists();
let secondary_exists = secondary_path.exists();
&format!("maybe move this module `{0}` \
to its own directory via \
`{0}/mod.rs`",
- this_module)[]);
+ this_module));
if default_exists || secondary_exists {
self.span_note(id_sp,
&format!("... or maybe `use` the module \
`{}` instead of possibly \
redeclaring it",
- mod_name)[]);
+ mod_name));
}
self.abort_if_errors();
}
(false, false) => {
self.span_fatal_help(id_sp,
&format!("file not found for module `{}`",
- mod_name)[],
+ mod_name),
&format!("name the file either {} or {} inside \
the directory {:?}",
default_path_str,
secondary_path_str,
- dir_path.display())[]);
+ dir_path.display()));
}
(true, true) => {
self.span_fatal_help(
and {}",
mod_name,
default_path_str,
- secondary_path_str)[],
+ secondary_path_str),
"delete or rename one of them to remove the ambiguity");
}
}
let mut err = String::from_str("circular modules: ");
let len = included_mod_stack.len();
for p in &included_mod_stack[i.. len] {
- err.push_str(&p.display().as_cow()[]);
+ err.push_str(&p.display().as_cow());
err.push_str(" -> ");
}
- err.push_str(&path.display().as_cow()[]);
- self.span_fatal(id_sp, &err[]);
+ err.push_str(&path.display().as_cow());
+ self.span_fatal(id_sp, &err[..]);
}
None => ()
}
self.span_help(span,
&format!("perhaps you meant to enclose the crate name `{}` in \
a string?",
- the_ident.as_str())[]);
+ the_ident.as_str()));
None
} else {
None
self.span_fatal(span,
&format!("expected extern crate name but \
found `{}`",
- token_str)[]);
+ token_str));
}
};
self.span_err(start_span,
&format!("unit-like struct variant should be written \
without braces, as `{},`",
- token::get_ident(ident))[]);
+ token::get_ident(ident)));
}
kind = StructVariantKind(struct_def);
} else if self.check(&token::OpenDelim(token::Paren)) {
&format!("illegal ABI: expected one of [{}], \
found `{}`",
abi::all_names().connect(", "),
- the_string)[]);
+ the_string));
None
}
}
let token_str = self.this_token_to_string();
self.span_fatal(span,
&format!("expected `{}` or `fn`, found `{}`", "{",
- token_str)[]);
+ token_str));
}
if self.eat_keyword_noexpect(keywords::Virtual) {
if self.eat_keyword(keywords::Mod) {
// MODULE ITEM
let (ident, item_, extra_attrs) =
- self.parse_item_mod(&attrs[]);
+ self.parse_item_mod(&attrs[..]);
let last_span = self.last_span;
let item = self.mk_item(lo,
last_span.hi,
fn parse_foreign_items(&mut self, first_item_attrs: Vec<Attribute>)
-> Vec<P<ForeignItem>> {
let mut attrs = first_item_attrs;
- attrs.push_all(&self.parse_outer_attributes()[]);
+ attrs.push_all(&self.parse_outer_attributes());
let mut foreign_items = Vec::new();
loop {
match self.parse_foreign_item(attrs) {
if !attrs.is_empty() {
let last_span = self.last_span;
self.span_err(last_span,
- Parser::expected_item_err(&attrs[]));
+ Parser::expected_item_err(&attrs[..]));
}
foreign_items
$(init_vec.push($si_str);)*
$(init_vec.push($sk_str);)*
$(init_vec.push($rk_str);)*
- interner::StrInterner::prefill(&init_vec[])
+ interner::StrInterner::prefill(&init_vec[..])
}
}}
// of `BytesContainer`, which is itself a workaround for the lack of
// DST.
unsafe {
- let this = &self[];
+ let this = &self[..];
mem::transmute::<&[u8],&[u8]>(this.container_as_bytes())
}
}
pub fn print(&mut self, token: Token, l: isize) -> old_io::IoResult<()> {
debug!("print {} {} (remaining line space={})", tok_str(&token), l,
self.space);
- debug!("{}", buf_str(&self.token[],
- &self.size[],
+ debug!("{}", buf_str(&self.token,
+ &self.size,
self.left,
self.right,
6));
assert_eq!(l, len);
// assert!(l <= space);
self.space -= len;
- self.print_str(&s[])
+ self.print_str(&s[..])
}
Token::Eof => {
// Eof should never get here.
try!(s.print_attribute(&fake_attr));
}
- try!(s.print_mod(&krate.module, &krate.attrs[]));
+ try!(s.print_mod(&krate.module, &krate.attrs));
try!(s.print_remaining_comments());
eof(&mut s.s)
}
pub fn synth_comment(&mut self, text: String) -> IoResult<()> {
try!(word(&mut self.s, "/*"));
try!(space(&mut self.s));
- try!(word(&mut self.s, &text[]));
+ try!(word(&mut self.s, &text[..]));
try!(space(&mut self.s));
word(&mut self.s, "*/")
}
}
ast::TyTup(ref elts) => {
try!(self.popen());
- try!(self.commasep(Inconsistent, &elts[],
+ try!(self.commasep(Inconsistent, &elts[..],
|s, ty| s.print_type(&**ty)));
if elts.len() == 1 {
try!(word(&mut self.s, ","));
}
ast::TyObjectSum(ref ty, ref bounds) => {
try!(self.print_type(&**ty));
- try!(self.print_bounds("+", &bounds[]));
+ try!(self.print_bounds("+", &bounds[..]));
}
ast::TyPolyTraitRef(ref bounds) => {
- try!(self.print_bounds("", &bounds[]));
+ try!(self.print_bounds("", &bounds[..]));
}
ast::TyQPath(ref qpath) => {
try!(self.print_qpath(&**qpath, false))
item: &ast::ForeignItem) -> IoResult<()> {
try!(self.hardbreak_if_not_bol());
try!(self.maybe_print_comment(item.span.lo));
- try!(self.print_outer_attributes(&item.attrs[]));
+ try!(self.print_outer_attributes(&item.attrs));
match item.node {
ast::ForeignItemFn(ref decl, ref generics) => {
try!(self.print_fn(&**decl, None, abi::Rust, item.ident, generics,
}
ast::ForeignItemStatic(ref t, m) => {
try!(self.head(&visibility_qualified(item.vis,
- "static")[]));
+ "static")));
if m {
try!(self.word_space("mut"));
}
fn print_associated_type(&mut self, typedef: &ast::AssociatedType)
-> IoResult<()>
{
- try!(self.print_outer_attributes(&typedef.attrs[]));
+ try!(self.print_outer_attributes(&typedef.attrs));
try!(self.word_space("type"));
try!(self.print_ty_param(&typedef.ty_param));
word(&mut self.s, ";")
pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
try!(self.hardbreak_if_not_bol());
try!(self.maybe_print_comment(item.span.lo));
- try!(self.print_outer_attributes(&item.attrs[]));
+ try!(self.print_outer_attributes(&item.attrs));
try!(self.ann.pre(self, NodeItem(item)));
match item.node {
ast::ItemExternCrate(ref optional_path) => {
try!(self.head(&visibility_qualified(item.vis,
- "extern crate")[]));
+ "extern crate")));
if let Some((ref p, style)) = *optional_path {
try!(self.print_string(p, style));
try!(space(&mut self.s));
}
ast::ItemUse(ref vp) => {
try!(self.head(&visibility_qualified(item.vis,
- "use")[]));
+ "use")));
try!(self.print_view_path(&**vp));
try!(word(&mut self.s, ";"));
try!(self.end()); // end inner head-block
}
ast::ItemStatic(ref ty, m, ref expr) => {
try!(self.head(&visibility_qualified(item.vis,
- "static")[]));
+ "static")));
if m == ast::MutMutable {
try!(self.word_space("mut"));
}
}
ast::ItemConst(ref ty, ref expr) => {
try!(self.head(&visibility_qualified(item.vis,
- "const")[]));
+ "const")));
try!(self.print_ident(item.ident));
try!(self.word_space(":"));
try!(self.print_type(&**ty));
item.vis
));
try!(word(&mut self.s, " "));
- try!(self.print_block_with_attrs(&**body, &item.attrs[]));
+ try!(self.print_block_with_attrs(&**body, &item.attrs));
}
ast::ItemMod(ref _mod) => {
try!(self.head(&visibility_qualified(item.vis,
- "mod")[]));
+ "mod")));
try!(self.print_ident(item.ident));
try!(self.nbsp());
try!(self.bopen());
- try!(self.print_mod(_mod, &item.attrs[]));
+ try!(self.print_mod(_mod, &item.attrs));
try!(self.bclose(item.span));
}
ast::ItemForeignMod(ref nmod) => {
try!(self.head("extern"));
- try!(self.word_nbsp(&nmod.abi.to_string()[]));
+ try!(self.word_nbsp(&nmod.abi.to_string()));
try!(self.bopen());
- try!(self.print_foreign_mod(nmod, &item.attrs[]));
+ try!(self.print_foreign_mod(nmod, &item.attrs));
try!(self.bclose(item.span));
}
ast::ItemTy(ref ty, ref params) => {
try!(self.ibox(indent_unit));
try!(self.ibox(0));
- try!(self.word_nbsp(&visibility_qualified(item.vis, "type")[]));
+ try!(self.word_nbsp(&visibility_qualified(item.vis, "type")));
try!(self.print_ident(item.ident));
try!(self.print_generics(params));
try!(self.end()); // end the inner ibox
));
}
ast::ItemStruct(ref struct_def, ref generics) => {
- try!(self.head(&visibility_qualified(item.vis,"struct")[]));
+ try!(self.head(&visibility_qualified(item.vis,"struct")));
try!(self.print_struct(&**struct_def, generics, item.ident, item.span));
}
try!(space(&mut self.s));
try!(self.bopen());
- try!(self.print_inner_attributes(&item.attrs[]));
+ try!(self.print_inner_attributes(&item.attrs));
for impl_item in impl_items {
match *impl_item {
ast::MethodImplItem(ref meth) => {
try!(self.word_nbsp("trait"));
try!(self.print_ident(item.ident));
try!(self.print_generics(generics));
- let bounds: Vec<_> = bounds.iter().map(|b| b.clone()).collect();
let mut real_bounds = Vec::with_capacity(bounds.len());
- for b in bounds {
- if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = b {
+ for b in bounds.iter() {
+ if let TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = *b {
try!(space(&mut self.s));
try!(self.word_space("for ?"));
try!(self.print_trait_ref(&ptr.trait_ref));
} else {
- real_bounds.push(b);
+ real_bounds.push(b.clone());
}
}
- try!(self.print_bounds(":", &real_bounds[]));
+ try!(self.print_bounds(":", &real_bounds[..]));
try!(self.print_where_clause(generics));
try!(word(&mut self.s, " "));
try!(self.bopen());
try!(self.print_ident(item.ident));
try!(self.cbox(indent_unit));
try!(self.popen());
- try!(self.print_tts(&tts[]));
+ try!(self.print_tts(&tts[..]));
try!(self.pclose());
try!(word(&mut self.s, ";"));
try!(self.end());
generics: &ast::Generics, ident: ast::Ident,
span: codemap::Span,
visibility: ast::Visibility) -> IoResult<()> {
- try!(self.head(&visibility_qualified(visibility, "enum")[]));
+ try!(self.head(&visibility_qualified(visibility, "enum")));
try!(self.print_ident(ident));
try!(self.print_generics(generics));
try!(self.print_where_clause(generics));
try!(space(&mut self.s));
- self.print_variants(&enum_definition.variants[], span)
+ self.print_variants(&enum_definition.variants, span)
}
pub fn print_variants(&mut self,
for v in variants {
try!(self.space_if_not_bol());
try!(self.maybe_print_comment(v.span.lo));
- try!(self.print_outer_attributes(&v.node.attrs[]));
+ try!(self.print_outer_attributes(&v.node.attrs));
try!(self.ibox(indent_unit));
try!(self.print_variant(&**v));
try!(word(&mut self.s, ","));
if !struct_def.fields.is_empty() {
try!(self.popen());
try!(self.commasep(
- Inconsistent, &struct_def.fields[],
+ Inconsistent, &struct_def.fields,
|s, field| {
match field.node.kind {
ast::NamedField(..) => panic!("unexpected named field"),
ast::NamedField(ident, visibility) => {
try!(self.hardbreak_if_not_bol());
try!(self.maybe_print_comment(field.span.lo));
- try!(self.print_outer_attributes(&field.node.attrs[]));
+ try!(self.print_outer_attributes(&field.node.attrs));
try!(self.print_visibility(visibility));
try!(self.print_ident(ident));
try!(self.word_nbsp(":"));
pub fn print_tt(&mut self, tt: &ast::TokenTree) -> IoResult<()> {
match *tt {
ast::TtToken(_, ref tk) => {
- try!(word(&mut self.s, &token_to_string(tk)[]));
+ try!(word(&mut self.s, &token_to_string(tk)));
match *tk {
parse::token::DocComment(..) => {
hardbreak(&mut self.s)
}
}
ast::TtDelimited(_, ref delimed) => {
- try!(word(&mut self.s, &token_to_string(&delimed.open_token())[]));
+ try!(word(&mut self.s, &token_to_string(&delimed.open_token())));
try!(space(&mut self.s));
- try!(self.print_tts(&delimed.tts[]));
+ try!(self.print_tts(&delimed.tts));
try!(space(&mut self.s));
- word(&mut self.s, &token_to_string(&delimed.close_token())[])
+ word(&mut self.s, &token_to_string(&delimed.close_token()))
},
ast::TtSequence(_, ref seq) => {
try!(word(&mut self.s, "$("));
try!(word(&mut self.s, ")"));
match seq.separator {
Some(ref tk) => {
- try!(word(&mut self.s, &token_to_string(tk)[]));
+ try!(word(&mut self.s, &token_to_string(tk)));
}
None => {},
}
if !args.is_empty() {
try!(self.popen());
try!(self.commasep(Consistent,
- &args[],
+ &args[..],
|s, arg| s.print_type(&*arg.ty)));
try!(self.pclose());
}
pub fn print_ty_method(&mut self, m: &ast::TypeMethod) -> IoResult<()> {
try!(self.hardbreak_if_not_bol());
try!(self.maybe_print_comment(m.span.lo));
- try!(self.print_outer_attributes(&m.attrs[]));
+ try!(self.print_outer_attributes(&m.attrs));
try!(self.print_ty_fn(m.abi,
m.unsafety,
&*m.decl,
pub fn print_method(&mut self, meth: &ast::Method) -> IoResult<()> {
try!(self.hardbreak_if_not_bol());
try!(self.maybe_print_comment(meth.span.lo));
- try!(self.print_outer_attributes(&meth.attrs[]));
+ try!(self.print_outer_attributes(&meth.attrs));
match meth.node {
ast::MethDecl(ident,
ref generics,
Some(&explicit_self.node),
vis));
try!(word(&mut self.s, " "));
- self.print_block_with_attrs(&**body, &meth.attrs[])
+ self.print_block_with_attrs(&**body, &meth.attrs)
},
ast::MethMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
..}) => {
try!(word(&mut self.s, "! "));
try!(self.cbox(indent_unit));
try!(self.popen());
- try!(self.print_tts(&tts[]));
+ try!(self.print_tts(&tts[..]));
try!(self.pclose());
try!(word(&mut self.s, ";"));
self.end()
fn print_expr_vec(&mut self, exprs: &[P<ast::Expr>]) -> IoResult<()> {
try!(self.ibox(indent_unit));
try!(word(&mut self.s, "["));
- try!(self.commasep_exprs(Inconsistent, &exprs[]));
+ try!(self.commasep_exprs(Inconsistent, &exprs[..]));
try!(word(&mut self.s, "]"));
self.end()
}
try!(word(&mut self.s, "{"));
try!(self.commasep_cmnt(
Consistent,
- &fields[],
+ &fields[..],
|s, field| {
try!(s.ibox(indent_unit));
try!(s.print_ident(field.ident.node));
fn print_expr_tup(&mut self, exprs: &[P<ast::Expr>]) -> IoResult<()> {
try!(self.popen());
- try!(self.commasep_exprs(Inconsistent, &exprs[]));
+ try!(self.commasep_exprs(Inconsistent, &exprs[..]));
if exprs.len() == 1 {
try!(word(&mut self.s, ","));
}
try!(self.print_expr_box(place, &**expr));
}
ast::ExprVec(ref exprs) => {
- try!(self.print_expr_vec(&exprs[]));
+ try!(self.print_expr_vec(&exprs[..]));
}
ast::ExprRepeat(ref element, ref count) => {
try!(self.print_expr_repeat(&**element, &**count));
}
ast::ExprStruct(ref path, ref fields, ref wth) => {
- try!(self.print_expr_struct(path, &fields[], wth));
+ try!(self.print_expr_struct(path, &fields[..], wth));
}
ast::ExprTup(ref exprs) => {
- try!(self.print_expr_tup(&exprs[]));
+ try!(self.print_expr_tup(&exprs[..]));
}
ast::ExprCall(ref func, ref args) => {
- try!(self.print_expr_call(&**func, &args[]));
+ try!(self.print_expr_call(&**func, &args[..]));
}
ast::ExprMethodCall(ident, ref tys, ref args) => {
- try!(self.print_expr_method_call(ident, &tys[], &args[]));
+ try!(self.print_expr_method_call(ident, &tys[..], &args[..]));
}
ast::ExprBinary(op, ref lhs, ref rhs) => {
try!(self.print_expr_binary(op, &**lhs, &**rhs));
try!(self.print_string(&a.asm, a.asm_str_style));
try!(self.word_space(":"));
- try!(self.commasep(Inconsistent, &a.outputs[],
+ try!(self.commasep(Inconsistent, &a.outputs,
|s, &(ref co, ref o, is_rw)| {
match co.slice_shift_char() {
Some(('=', operand)) if is_rw => {
- try!(s.print_string(&format!("+{}", operand)[],
+ try!(s.print_string(&format!("+{}", operand),
ast::CookedStr))
}
_ => try!(s.print_string(&co, ast::CookedStr))
try!(space(&mut self.s));
try!(self.word_space(":"));
- try!(self.commasep(Inconsistent, &a.inputs[],
+ try!(self.commasep(Inconsistent, &a.inputs,
|s, &(ref co, ref o)| {
try!(s.print_string(&co, ast::CookedStr));
try!(s.popen());
try!(space(&mut self.s));
try!(self.word_space(":"));
- try!(self.commasep(Inconsistent, &a.clobbers[],
+ try!(self.commasep(Inconsistent, &a.clobbers,
|s, co| {
try!(s.print_string(&co, ast::CookedStr));
Ok(())
pub fn print_ident(&mut self, ident: ast::Ident) -> IoResult<()> {
if self.encode_idents_with_hygiene {
let encoded = ident.encode_with_hygiene();
- try!(word(&mut self.s, &encoded[]))
+ try!(word(&mut self.s, &encoded[..]))
} else {
try!(word(&mut self.s, &token::get_ident(ident)))
}
}
pub fn print_usize(&mut self, i: usize) -> IoResult<()> {
- word(&mut self.s, &i.to_string()[])
+ word(&mut self.s, &i.to_string())
}
pub fn print_name(&mut self, name: ast::Name) -> IoResult<()> {
}
try!(self.commasep(
Inconsistent,
- &data.types[],
+ &data.types,
|s, ty| s.print_type(&**ty)));
comma = true;
}
try!(word(&mut self.s, "("));
try!(self.commasep(
Inconsistent,
- &data.inputs[],
+ &data.inputs,
|s, ty| s.print_type(&**ty)));
try!(word(&mut self.s, ")"));
Some(ref args) => {
if !args.is_empty() {
try!(self.popen());
- try!(self.commasep(Inconsistent, &args[],
+ try!(self.commasep(Inconsistent, &args[..],
|s, p| s.print_pat(&**p)));
try!(self.pclose());
}
try!(self.nbsp());
try!(self.word_space("{"));
try!(self.commasep_cmnt(
- Consistent, &fields[],
+ Consistent, &fields[..],
|s, f| {
try!(s.cbox(indent_unit));
if !f.node.is_shorthand {
ast::PatTup(ref elts) => {
try!(self.popen());
try!(self.commasep(Inconsistent,
- &elts[],
+ &elts[..],
|s, p| s.print_pat(&**p)));
if elts.len() == 1 {
try!(word(&mut self.s, ","));
ast::PatVec(ref before, ref slice, ref after) => {
try!(word(&mut self.s, "["));
try!(self.commasep(Inconsistent,
- &before[],
+ &before[..],
|s, p| s.print_pat(&**p)));
if let Some(ref p) = *slice {
if !before.is_empty() { try!(self.word_space(",")); }
if !after.is_empty() { try!(self.word_space(",")); }
}
try!(self.commasep(Inconsistent,
- &after[],
+ &after[..],
|s, p| s.print_pat(&**p)));
try!(word(&mut self.s, "]"));
}
}
try!(self.cbox(indent_unit));
try!(self.ibox(0));
- try!(self.print_outer_attributes(&arm.attrs[]));
+ try!(self.print_outer_attributes(&arm.attrs));
let mut first = true;
for p in &arm.pats {
if first {
ints.push(i);
}
- try!(self.commasep(Inconsistent, &ints[], |s, &idx| {
+ try!(self.commasep(Inconsistent, &ints[..], |s, &idx| {
if idx < generics.lifetimes.len() {
let lifetime = &generics.lifetimes[idx];
s.print_lifetime_def(lifetime)
pub fn print_ty_param(&mut self, param: &ast::TyParam) -> IoResult<()> {
try!(self.print_ident(param.ident));
- try!(self.print_bounds(":", ¶m.bounds[]));
+ try!(self.print_bounds(":", ¶m.bounds));
match param.default {
Some(ref default) => {
try!(space(&mut self.s));
try!(word(&mut self.s, &name));
}
ast::MetaNameValue(ref name, ref value) => {
- try!(self.word_space(&name[]));
+ try!(self.word_space(&name[..]));
try!(self.word_space("="));
try!(self.print_literal(value));
}
try!(word(&mut self.s, &name));
try!(self.popen());
try!(self.commasep(Consistent,
- &items[],
+ &items[..],
|s, i| s.print_meta_item(&**i)));
try!(self.pclose());
}
try!(self.print_path(path, false));
try!(word(&mut self.s, "::{"));
}
- try!(self.commasep(Inconsistent, &idents[], |s, w| {
+ try!(self.commasep(Inconsistent, &idents[..], |s, w| {
match w.node {
ast::PathListIdent { name, .. } => {
s.print_ident(name)
try!(self.maybe_print_comment(lit.span.lo));
match self.next_lit(lit.span.lo) {
Some(ref ltrl) => {
- return word(&mut self.s, &(*ltrl).lit[]);
+ return word(&mut self.s, &(*ltrl).lit);
}
_ => ()
}
let mut res = String::from_str("b'");
res.extend(ascii::escape_default(byte).map(|c| c as char));
res.push('\'');
- word(&mut self.s, &res[])
+ word(&mut self.s, &res[..])
}
ast::LitChar(ch) => {
let mut res = String::from_str("'");
res.extend(ch.escape_default());
res.push('\'');
- word(&mut self.s, &res[])
+ word(&mut self.s, &res[..])
}
ast::LitInt(i, t) => {
match t {
ast::SignedIntLit(st, ast::Plus) => {
word(&mut self.s,
- &ast_util::int_ty_to_string(st, Some(i as i64))[])
+ &ast_util::int_ty_to_string(st, Some(i as i64)))
}
ast::SignedIntLit(st, ast::Minus) => {
let istr = ast_util::int_ty_to_string(st, Some(-(i as i64)));
word(&mut self.s,
- &format!("-{}", istr)[])
+ &format!("-{}", istr))
}
ast::UnsignedIntLit(ut) => {
word(&mut self.s, &ast_util::uint_ty_to_string(ut, Some(i)))
}
ast::UnsuffixedIntLit(ast::Plus) => {
- word(&mut self.s, &format!("{}", i)[])
+ word(&mut self.s, &format!("{}", i))
}
ast::UnsuffixedIntLit(ast::Minus) => {
- word(&mut self.s, &format!("-{}", i)[])
+ word(&mut self.s, &format!("-{}", i))
}
}
}
&format!(
"{}{}",
&f,
- &ast_util::float_ty_to_string(t)[])[])
+ &ast_util::float_ty_to_string(t)))
}
- ast::LitFloatUnsuffixed(ref f) => word(&mut self.s, &f[]),
+ ast::LitFloatUnsuffixed(ref f) => word(&mut self.s, &f[..]),
ast::LitBool(val) => {
if val { word(&mut self.s, "true") } else { word(&mut self.s, "false") }
}
escaped.extend(ascii::escape_default(ch as u8)
.map(|c| c as char));
}
- word(&mut self.s, &format!("b\"{}\"", escaped)[])
+ word(&mut self.s, &format!("b\"{}\"", escaped))
}
}
}
comments::Mixed => {
assert_eq!(cmnt.lines.len(), 1);
try!(zerobreak(&mut self.s));
- try!(word(&mut self.s, &cmnt.lines[0][]));
+ try!(word(&mut self.s, &cmnt.lines[0]));
zerobreak(&mut self.s)
}
comments::Isolated => {
// Don't print empty lines because they will end up as trailing
// whitespace
if !line.is_empty() {
- try!(word(&mut self.s, &line[]));
+ try!(word(&mut self.s, &line[..]));
}
try!(hardbreak(&mut self.s));
}
comments::Trailing => {
try!(word(&mut self.s, " "));
if cmnt.lines.len() == 1 {
- try!(word(&mut self.s, &cmnt.lines[0][]));
+ try!(word(&mut self.s, &cmnt.lines[0]));
hardbreak(&mut self.s)
} else {
try!(self.ibox(0));
for line in &cmnt.lines {
if !line.is_empty() {
- try!(word(&mut self.s, &line[]));
+ try!(word(&mut self.s, &line[..]));
}
try!(hardbreak(&mut self.s));
}
string=st))
}
};
- word(&mut self.s, &st[])
+ word(&mut self.s, &st[..])
}
pub fn next_comment(&mut self) -> Option<comments::Comment> {
Some(abi::Rust) => Ok(()),
Some(abi) => {
try!(self.word_nbsp("extern"));
- self.word_nbsp(&abi.to_string()[])
+ self.word_nbsp(&abi.to_string())
}
None => Ok(())
}
match opt_abi {
Some(abi) => {
try!(self.word_nbsp("extern"));
- self.word_nbsp(&abi.to_string()[])
+ self.word_nbsp(&abi.to_string())
}
None => Ok(())
}
if abi != abi::Rust {
try!(self.word_nbsp("extern"));
- try!(self.word_nbsp(&abi.to_string()[]));
+ try!(self.word_nbsp(&abi.to_string()));
}
word(&mut self.s, "fn")
}
}
+#[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> {
+ fn hash<H: Hasher>(&self, state: &mut H) {
+ (**self).hash(state);
+ }
+}
impl<T: 'static + Decodable> Decodable for P<T> {
fn decode<D: Decoder>(d: &mut D) -> Result<P<T>, D::Error> {
attr::contains_name(attrs, "no_implicit_prelude")
}
-struct StandardLibraryInjector<'a> {
- alt_std_name: Option<String>
+struct StandardLibraryInjector {
+ alt_std_name: Option<String>,
}
-impl<'a> fold::Folder for StandardLibraryInjector<'a> {
+impl fold::Folder for StandardLibraryInjector {
fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
// The name to use in `extern crate "name" as std;`
let actual_crate_name = match self.alt_std_name {
- Some(ref s) => token::intern_and_get_ident(&s[]),
+ Some(ref s) => token::intern_and_get_ident(&s[..]),
None => token::intern_and_get_ident("std"),
};
fold.fold_crate(krate)
}
-struct PreludeInjector<'a>;
+struct PreludeInjector;
-impl<'a> fold::Folder for PreludeInjector<'a> {
+
+impl fold::Folder for PreludeInjector {
fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
// only add `use std::prelude::*;` if there wasn't a
// `#![no_implicit_prelude]` at the crate level.
self.cx.path.push(ident);
}
debug!("current path: {}",
- ast_util::path_name_i(&self.cx.path[]));
+ ast_util::path_name_i(&self.cx.path));
if is_test_fn(&self.cx, &*i) || is_bench_fn(&self.cx, &*i) {
match i.node {
// When not compiling with --test we should not compile the
// #[test] functions
config::strip_items(krate, |attrs| {
- !attr::contains_name(&attrs[], "test") &&
- !attr::contains_name(&attrs[], "bench")
+ !attr::contains_name(&attrs[..], "test") &&
+ !attr::contains_name(&attrs[..], "bench")
})
}
fn is_test_crate(krate: &ast::Crate) -> bool {
match attr::find_crate_name(&krate.attrs[]) {
- Some(ref s) if "test" == &s[] => true,
+ Some(ref s) if "test" == &s[..] => true,
_ => false
}
}
// creates $name: $expr
let field = |name, expr| ecx.field_imm(span, ecx.ident_of(name), expr);
- debug!("encoding {}", ast_util::path_name_i(&path[]));
+ debug!("encoding {}", ast_util::path_name_i(&path[..]));
// path to the #[test] function: "foo::bar::baz"
- let path_string = ast_util::path_name_i(&path[]);
- let name_expr = ecx.expr_str(span, token::intern_and_get_ident(&path_string[]));
+ let path_string = ast_util::path_name_i(&path[..]);
+ let name_expr = ecx.expr_str(span, token::intern_and_get_ident(&path_string[..]));
// self::test::StaticTestName($name_expr)
let name_expr = ecx.expr_call(span,
use ast::Name;
-use std::borrow::BorrowFrom;
+use std::borrow::Borrow;
use std::cell::RefCell;
use std::cmp::Ordering;
use std::collections::HashMap;
+#[cfg(stage0)] use std::collections::hash_map::Hasher;
use std::fmt;
use std::hash::Hash;
-use std::collections::hash_map::Hasher;
use std::ops::Deref;
use std::rc::Rc;
}
// 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 {
}
pub fn find<Q: ?Sized>(&self, val: &Q) -> Option<Name>
- where Q: BorrowFrom<T> + Eq + Hash<Hasher> {
+ 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> {
+ 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 {
let map = self.map.borrow();
match (*map).get(val) {
Some(v) => Some(*v),
impl Ord for RcStr {
fn cmp(&self, other: &RcStr) -> Ordering {
- self[].cmp(&other[])
+ self[..].cmp(&other[..])
}
}
impl fmt::Debug for RcStr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use std::fmt::Debug;
- self[].fmt(f)
+ self[..].fmt(f)
}
}
impl fmt::Display for RcStr {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use std::fmt::Display;
- self[].fmt(f)
+ self[..].fmt(f)
}
}
-impl BorrowFrom<RcStr> for str {
- fn borrow_from(owned: &RcStr) -> &str {
- &owned.string[]
+impl Borrow<str> for RcStr {
+ fn borrow(&self) -> &str {
+ &self.string[..]
}
}
impl Deref for RcStr {
type Target = str;
- fn deref(&self) -> &str { &self.string[] }
+ fn deref(&self) -> &str { &self.string[..] }
}
/// A StrInterner differs from Interner<String> in that it accepts
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>
- where Q: BorrowFrom<RcStr> + Eq + Hash<Hasher> {
+ where RcStr: Borrow<Q>, Q: Eq + Hash {
match (*self.map.borrow()).get(val) {
Some(v) => Some(*v),
None => None,
use self::SmallVectorRepr::*;
use self::IntoIterRepr::*;
-use std::iter::FromIterator;
+use std::iter::{IntoIterator, FromIterator};
use std::mem;
use std::slice;
use std::vec;
}
impl<T> FromIterator<T> for SmallVector<T> {
- fn from_iter<I: Iterator<Item=T>>(iter: I) -> SmallVector<T> {
+ fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> SmallVector<T> {
let mut v = SmallVector::zero();
v.extend(iter);
v
}
impl<T> Extend<T> for SmallVector<T> {
- fn extend<I: Iterator<Item=T>>(&mut self, iter: I) {
+ fn extend<I: IntoIterator<Item=T>>(&mut self, iter: I) {
for val in iter {
self.push(val);
}
html_playground_url = "http://play.rust-lang.org/")]
#![deny(missing_docs)]
-#![feature(core)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(int_uint)]
}
};
- let entry = open(&term[]);
+ let entry = open(&term[..]);
if entry.is_err() {
if env::var("MSYSCON").ok().map_or(false, |s| {
"mintty.exe" == s
Result<Vec<u8>, String>
{
let mut u8v: Vec<_> = fmt.bytes().collect();
- u8v.extend(cap.as_bytes().iter().map(|&b| b));
+ u8v.extend(cap.bytes());
expand(&u8v, params, vars)
}
for p in &dirs_to_search {
if p.exists() {
let f = first_char.to_string();
- let newp = p.join_many(&[&f[], term]);
+ let newp = p.join_many(&[&f[..], term]);
if newp.exists() {
return Some(box newp);
}
// on some installations the dir is named after the hex of the char (e.g. OS X)
let f = format!("{:x}", first_char as uint);
- let newp = p.join_many(&[&f[], term]);
+ let newp = p.join_many(&[&f[..], term]);
if newp.exists() {
return Some(box newp);
}
#![feature(collections)]
#![feature(core)]
#![feature(env)]
-#![feature(hash)]
#![feature(int_uint)]
#![feature(old_io)]
#![feature(old_path)]
st.write_failures().unwrap();
let s = match st.out {
- Raw(ref m) => String::from_utf8_lossy(&m[]),
+ Raw(ref m) => String::from_utf8_lossy(&m[..]),
Pretty(_) => unreachable!()
};
None => filtered,
Some(ref filter) => {
filtered.into_iter().filter(|test| {
- test.desc.name.as_slice().contains(&filter[])
+ test.desc.name.as_slice().contains(&filter[..])
}).collect()
}
};
use std::cmp::Ordering::{self, Less, Greater, Equal};
use std::collections::hash_map::Entry::{Occupied, Vacant};
-use std::collections::hash_map::{self, Hasher};
+use std::collections::hash_map;
use std::hash::Hash;
use std::mem;
use std::num::{Float, FromPrimitive};
/// Returns a HashMap with the number of occurrences of every element in the
/// sequence that the iterator exposes.
pub fn freq_count<T, U>(iter: T) -> hash_map::HashMap<U, uint>
- where T: Iterator<Item=U>, U: Eq + Clone + Hash<Hasher>
+ where T: Iterator<Item=U>, U: Eq + Clone + Hash
{
let mut map: hash_map::HashMap<U,uint> = hash_map::HashMap::new();
for elem in iter {
-Subproject commit 2089cab13e7f92b487ba0dc1df9f6c05116b004a
+Subproject commit 4891e6382e3e8aa89d530aa18427836428c47157
{
let urls = markdown_data.replace(".md)", ".html)");
try!(File::create(&preprocessed_path)
- .write_str(&urls[]));
+ .write_str(&urls[..]));
}
// write the prelude to a temporary HTML file for rustdoc inclusion
impl Error for String {
fn description<'a>(&'a self) -> &'a str {
- &self[]
+ &self[..]
}
}
self.desc
}
fn detail(&self) -> Option<&str> {
- self.detail.as_ref().map(|s| &s[])
+ self.detail.as_ref().map(|s| &s[..])
}
}
}
Err(errors) => {
for err in errors {
- term.err(&err[]);
+ term.err(&err[..]);
}
return Err(box "There was an error." as Box<Error>);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub trait TheTrait<T> {
+pub trait TheTrait<T> : ::std::marker::PhantomFn<T> {
fn the_fn(&self);
}
pub struct FakeHeap;
-pub struct FakeVec<T, A = FakeHeap>;
+pub struct FakeVec<T, A = FakeHeap> { pub f: Option<(T,A)> }
+
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub struct A<T>;
-pub struct B<T>;
+pub struct A<T> { pub v: T }
+pub struct B<T> { pub v: T }
pub mod test {
- pub struct A<T>;
+ pub struct A<T> { pub v: T }
impl<T> A<T> {
pub fn foo(&self) -> int {
}
pub fn foo() -> int {
- let a = A::<()>;
- let b = B::<()>;
- let c = test::A::<()>;
+ let a = A { v: () };
+ let b = B { v: () };
+ let c = test::A { v: () };
return a.foo() + a.bar() +
b.foo() + b.bar() +
c.foo() + c.bar();
#![crate_type="lib"]
#![deny(warnings)]
+#![allow(dead_code)]
pub use src::aliases::B;
pub use src::hidden_core::make;
pub mod hidden_core {
use super::aliases::B;
- pub struct A<T>;
+ pub struct A<T> { t: T }
- pub fn make() -> B { A }
+ pub fn make() -> B { A { t: 1.0 } }
impl<T> A<T> {
pub fn foo(&mut self) { println!("called foo"); }
#![crate_type = "lib"]
-pub struct TreeBuilder<H>;
+pub struct TreeBuilder<H> { pub h: H }
impl<H> TreeBuilder<H> {
pub fn process_token(&mut self) {
#![crate_type = "lib"]
pub trait Foo<'a, T> {
- fn foo(&self) -> T;
+ fn foo(&'a self) -> T;
}
pub fn foo<'a, T>(x: &'a Foo<'a, T>) -> T {
#![allow(unknown_features)]
#![feature(box_syntax)]
-pub trait i<T> { }
+pub trait i<T>
+{
+ fn dummy(&self, t: T) -> T { panic!() }
+}
pub fn f<T>() -> Box<i<T>+'static> {
impl<T> i<T> for () { }
#![feature(unsafe_destructor)]
+use std::marker;
+
struct arc_destruct<T> {
- _data: int,
+ _data: int,
+ _marker: marker::PhantomData<T>
}
#[unsafe_destructor]
fn arc_destruct<T: Sync>(data: int) -> arc_destruct<T> {
arc_destruct {
- _data: data
+ _data: data,
+ _marker: marker::PhantomData
}
}
pub trait T {
type C;
+ fn dummy(&self) { }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub trait Foo {
+use std::marker::MarkerTrait;
+
+pub trait Foo : MarkerTrait {
fn bar();
}
use std::mem;
-trait A {}
+trait A {
+ fn dummy(&self) { }
+}
struct B;
impl A for B {}
fn f() { }
f();
}
+ fn dummy(&self) { }
}
#![no_std]
#![feature(lang_items)]
+#[lang="phantom_fn"]
+pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
+impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
+
#[lang="sized"]
-pub trait Sized {}
+pub trait Sized : PhantomFn<Self> {}
#[lang="panic"]
fn panic(_: &(&'static str, &'static str, uint)) -> ! { loop {} }
extern fn eh_personality() {}
#[lang="copy"]
-pub trait Copy {}
+pub trait Copy : PhantomFn<Self> {
+ // Empty.
+}
fn check_item(&mut self, cx: &Context, it: &ast::Item) {
let name = token::get_ident(it.ident);
- if &name[] == "lintme" {
+ if &name[..] == "lintme" {
cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
- } else if &name[] == "pleaselintme" {
+ } else if &name[..] == "pleaselintme" {
cx.span_lint(PLEASE_LINT, it.span, "item is named 'pleaselintme'");
}
}
fn check_item(&mut self, cx: &Context, it: &ast::Item) {
let name = token::get_ident(it.ident);
- if &name[] == "lintme" {
+ if &name[..] == "lintme" {
cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
}
}
impl Trait for MethodTester {}
#[unstable(feature = "test_feature")]
-pub trait UnstableTrait {}
+pub trait UnstableTrait { fn dummy(&self) { } }
#[stable(feature = "test_feature", since = "1.0.0")]
#[deprecated(since = "1.0.0")]
}
// issue 8134
-pub struct Parser<T>;
+pub struct Parser<T>(T);
impl<T: std::iter::Iterator<Item=char>> Parser<T> {
fn in_doctype(&mut self) {
static DOCTYPEPattern: [char; 6] = ['O', 'C', 'T', 'Y', 'P', 'E'];
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub trait RemoteTrait {}
+pub trait RemoteTrait { fn dummy(&self) { } }
use std::ops::Deref;
struct DerefWithHelper<H, T> {
- pub helper: H
+ pub helper: H,
+ pub value: Option<T>
}
trait Helper<T> {
// Test cross-crate autoderef + vtable.
pub fn check<T: PartialEq>(x: T, y: T) -> bool {
- let d: DerefWithHelper<Option<T>, T> = DerefWithHelper { helper: Some(x) };
+ let d: DerefWithHelper<Option<T>, T> = DerefWithHelper { helper: Some(x), value: None };
d.eq(&y)
}
_: &[ast::TokenTree]) -> Box<MacResult+'cx> {
let args = self.args.iter().map(|i| pprust::meta_item_to_string(&*i))
.collect::<Vec<_>>().connect(", ");
- let interned = token::intern_and_get_ident(&args[]);
+ let interned = token::intern_and_get_ident(&args[..]);
MacExpr::new(ecx.expr_str(sp, interned))
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Foo {}
+trait Foo : ::std::marker::MarkerTrait {}
#![crate_name = "a"]
+use std::marker::MarkerTrait;
+
macro_rules! three {
() => { 3 }
}
-pub trait U {}
-pub trait V {}
+pub trait U : MarkerTrait {}
+pub trait V : MarkerTrait {}
impl U for () {}
impl V for () {}
#![crate_name = "a"]
+use std::marker::MarkerTrait;
+
macro_rules! three {
() => { 3 }
}
-pub trait U {}
-pub trait V {}
+pub trait U : MarkerTrait {}
+pub trait V : MarkerTrait {}
impl U for () {}
impl V for () {}
#![crate_name = "a"]
+use std::marker::MarkerTrait;
+
macro_rules! three {
() => { 3 }
}
-pub trait U {}
-pub trait V {}
+pub trait U : MarkerTrait {}
+pub trait V : MarkerTrait {}
impl U for () {}
impl V for () {}
#![crate_name = "a"]
+use std::marker::MarkerTrait;
+
macro_rules! three {
() => { 3 }
}
-pub trait U {}
-pub trait V {}
+pub trait U : MarkerTrait {}
+pub trait V : MarkerTrait {}
impl U for () {}
impl V for () {}
#![crate_name = "a"]
+use std::marker::MarkerTrait;
+
macro_rules! three {
() => { 3 }
}
-pub trait U {}
-pub trait V {}
+pub trait U : MarkerTrait {}
+pub trait V : MarkerTrait {}
impl U for () {}
impl V for () {}
#![crate_name = "a"]
+use std::marker::MarkerTrait;
+
macro_rules! three {
() => { 3 }
}
-pub trait U {}
-pub trait V {}
+pub trait U : MarkerTrait {}
+pub trait V : MarkerTrait {}
impl U for () {}
impl V for () {}
#![crate_name = "a"]
+use std::marker::MarkerTrait;
+
macro_rules! three {
() => { 3 }
}
-pub trait U {}
-pub trait V {}
+pub trait U : MarkerTrait {}
+pub trait V : MarkerTrait {}
impl U for () {}
impl V for () {}
#![crate_name = "a"]
+use std::marker::MarkerTrait;
+
macro_rules! three {
() => { 3 }
}
-pub trait U {}
-pub trait V {}
+pub trait U : MarkerTrait {}
+pub trait V : MarkerTrait {}
impl U for () {}
impl V for () {}
#![crate_name = "a"]
+use std::marker::MarkerTrait;
+
macro_rules! three {
() => { 3 }
}
-pub trait U {}
-pub trait V {}
+pub trait U : MarkerTrait {}
+pub trait V : MarkerTrait {}
impl U for () {}
impl V for () {}
#![crate_name = "a"]
+use std::marker::MarkerTrait;
+
macro_rules! three {
() => { 3 }
}
-pub trait U {}
-pub trait V {}
+pub trait U : MarkerTrait {}
+pub trait V : MarkerTrait {}
impl U for () {}
impl V for () {}
#![crate_name = "a"]
+use std::marker::MarkerTrait;
+
macro_rules! three {
() => { 3 }
}
-pub trait U {}
-pub trait V {}
+pub trait U : MarkerTrait {}
+pub trait V : MarkerTrait {}
impl U for () {}
impl V for () {}
#![crate_name = "a"]
+use std::marker::MarkerTrait;
+
macro_rules! three {
() => { 3 }
}
-pub trait U {}
-pub trait V {}
+pub trait U : MarkerTrait {}
+pub trait V : MarkerTrait {}
impl U for () {}
impl V for () {}
#![crate_name = "a"]
+use std::marker::MarkerTrait;
+
macro_rules! three {
() => { 3 }
}
-pub trait U {}
-pub trait V {}
+pub trait U : MarkerTrait {}
+pub trait V : MarkerTrait {}
impl U for () {}
impl V for () {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub trait Trait {}
+pub trait Trait {
+ fn dummy(&self) { }
+}
pub struct Foo<T:Trait> {
pub x: T,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub trait Foo {
+pub trait Foo : ::std::marker::MarkerTrait {
}
impl Foo for int {
pub use self::sub::{Bar, Baz};
pub trait Trait {
- fn foo();
+ fn foo(&self);
}
struct Foo;
extern crate rand;
use std::collections::BTreeSet;
-use std::collections::BitvSet;
+use std::collections::BitSet;
use std::collections::HashSet;
-use std::collections::hash_map::Hasher;
use std::hash::Hash;
use std::env;
use std::time::Duration;
fn contains(&self, k: &T) -> bool;
}
-impl<T: Hash<Hasher> + Eq> MutableSet<T> for HashSet<T> {
+impl<T: Hash + Eq> MutableSet<T> for HashSet<T> {
fn insert(&mut self, k: T) { self.insert(k); }
fn remove(&mut self, k: &T) -> bool { self.remove(k) }
fn contains(&self, k: &T) -> bool { self.contains(k) }
fn remove(&mut self, k: &T) -> bool { self.remove(k) }
fn contains(&self, k: &T) -> bool { self.contains(k) }
}
-impl MutableSet<usize> for BitvSet {
+impl MutableSet<usize> for BitSet {
fn insert(&mut self, k: usize) { self.insert(k); }
fn remove(&mut self, k: &usize) -> bool { self.remove(k) }
fn contains(&self, k: &usize) -> bool { self.contains(k) }
{
let mut rng: rand::IsaacRng = rand::SeedableRng::from_seed(seed);
let mut results = empty_results();
- results.bench_int(&mut rng, num_keys, max, || BitvSet::new());
- write_results("collections::bitv::BitvSet", &results);
+ results.bench_int(&mut rng, num_keys, max, || BitSet::new());
+ write_results("collections::bit_vec::BitSet", &results);
}
}
('t', 0.3015094502008)];
try!(make_fasta(writer, ">ONE Homo sapiens alu\n",
- alu.as_bytes().iter().cycle().map(|c| *c), n * 2));
+ alu.as_bytes().iter().cycle().cloned(), n * 2));
try!(make_fasta(writer, ">TWO IUB ambiguity codes\n",
AAGen::new(rng, iub), n * 3));
try!(make_fasta(writer, ">THREE Homo sapiens frequency\n",
for i in 0..masks.len() {
for j in 0..(*masks)[i].len() {
masks[i][j] =
- (*masks)[i][j].iter().map(|&m| m)
+ (*masks)[i][j].iter().cloned()
.filter(|&m| !is_board_unfeasible(m, masks))
.collect();
}
// reverse order, i.e. the board rotated by half a turn.
data.nb += 2;
let sol1 = to_vec(raw_sol);
- let sol2: Vec<u8> = sol1.iter().rev().map(|x| *x).collect();
+ let sol2: Vec<u8> = sol1.iter().rev().cloned().collect();
if data.nb == 2 {
data.min = sol1.clone();
+++ /dev/null
-// 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.
-
-fn main() {
- let x = "\x80"; //~ ERROR may only be used
- let y = "\xff"; //~ ERROR may only be used
- let z = "\xe2"; //~ ERROR may only be used
- let a = b"\x00e2"; // ok because byte literal
-}
-
#![feature(no_std)]
#![no_std]
+#[lang="phantom_fn"]
+pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
+impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
+
#[lang="sized"]
-pub trait Sized {
+pub trait Sized : PhantomFn<Self> {
// Empty.
}
// Test that coherence detects overlap when some of the types in the
// impls are projections of associated type. Issue #20624.
+use std::marker::PhantomData;
use std::ops::Deref;
-pub struct Cow<'a, B: ?Sized>;
+pub struct Cow<'a, B: ?Sized>(PhantomData<(&'a (),B)>);
/// Trait for moving into a `Cow`
pub trait IntoCow<'a, B: ?Sized> {
// Check that an associated type cannot be bound in an expression path.
-trait Foo {
+trait Foo : ::std::marker::MarkerTrait {
type A;
fn bar() -> isize;
}
// Test that we do not ICE when an impl is missing an associated type (and that we report
// a useful error, of course).
-trait Trait {
+trait Trait : ::std::marker::MarkerTrait {
type Type;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Foo {
+trait Foo : ::std::marker::MarkerTrait {
type X;
type Y;
}
// Check that we get an error when you use `<Self as Get>::Value` in
// the trait definition but `Self` does not, in fact, implement `Get`.
-trait Get {
+trait Get : ::std::marker::MarkerTrait {
type Value;
}
pub trait Foo {
type A;
+
+ fn dummy(&self) { }
}
impl Foo for i32 {
// Check that an associated type cannot be bound in an expression path.
-trait Foo {
+trait Foo : ::std::marker::MarkerTrait {
type A;
fn bar() -> isize;
}
+++ /dev/null
-// Copyright 2012 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.
-
-#[derive(Debug)] //~ERROR expected item after attributes
+++ /dev/null
-// Copyright 2012 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.
-
-fn main() {
- #[attr] //~ ERROR expected item after attributes
- println!("hi");
-}
+++ /dev/null
-// Copyright 2012 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.
-
-fn main() {
- #[attr] //~ ERROR expected item
- let __isize = 0;
-}
+++ /dev/null
-// Copyright 2012 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.
-
-// error-pattern:expected item
-
-fn f() {
- #[foo = "bar"]
- let x = 10;
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2012 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.
-
-// error-pattern:expected item
-
-fn f() {
- #[foo = "bar"]
-}
-
-fn main() {
-}
+++ /dev/null
-// Copyright 2012 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.
-
-// error-pattern:expected item
-
-fn main() {
-}
-
-#[foo = "bar"]
+++ /dev/null
-// 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.
-
-#![feature(lang_items)]
-
-fn main() {}
-
-#![lang(foo)] //~ ERROR an inner attribute is not permitted in this context
-fn foo() {}
+++ /dev/null
-// Copyright 2013 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.
-
-// Constants (static variables) can be used to match in patterns, but mutable
-// statics cannot. This ensures that there's some form of error if this is
-// attempted.
-
-extern crate libc;
-
-extern {
- static mut rust_dbg_static_mut: libc::c_int;
- pub fn rust_dbg_static_mut_check_four();
- #[cfg(stage37)] //~ ERROR expected item after attributes
-}
-
-pub fn main() {}
+++ /dev/null
-// Copyright 2013 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.
-
-// ignore-tidy-cr
-// ignore-tidy-tab
-fn main() {
- // these literals are just silly.
- ''';
- //~^ ERROR: character constant must be escaped: \'
-
- // note that this is a literal "\n" byte
- '
-';
- //~^^ ERROR: character constant must be escaped: \n
-
- // note that this is a literal "\r" byte
- '\r'; //~ ERROR: character constant must be escaped: \r
-
- // note that this is a literal tab character here
- ' ';
- //~^ ERROR: character constant must be escaped: \t
-}
+++ /dev/null
-// 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.
-
-
-extern crate
- "foo"suffix //~ ERROR extern crate name with a suffix is illegal
- as foo;
-
-extern
- "C"suffix //~ ERROR ABI spec with a suffix is illegal
- fn foo() {}
-
-extern
- "C"suffix //~ ERROR ABI spec with a suffix is illegal
-{}
-
-fn main() {
- ""suffix; //~ ERROR str literal with a suffix is illegal
- b""suffix; //~ ERROR binary str literal with a suffix is illegal
- r#""#suffix; //~ ERROR str literal with a suffix is illegal
- br#""#suffix; //~ ERROR binary str literal with a suffix is illegal
- 'a'suffix; //~ ERROR char literal with a suffix is illegal
- b'a'suffix; //~ ERROR byte literal with a suffix is illegal
-
- 1234u1024; //~ ERROR illegal width `1024` for integer literal
- 1234i1024; //~ ERROR illegal width `1024` for integer literal
- 1234f1024; //~ ERROR illegal width `1024` for float literal
- 1234.5f1024; //~ ERROR illegal width `1024` for float literal
-
- 1234suffix; //~ ERROR illegal suffix `suffix` for numeric literal
- 0b101suffix; //~ ERROR illegal suffix `suffix` for numeric literal
- 1.0suffix; //~ ERROR illegal suffix `suffix` for float literal
- 1.0e10suffix; //~ ERROR illegal suffix `suffix` for float literal
-}
// ignore-tidy-linelength
-#![feature(no_std)]
-#![no_std]
-#![feature(lang_items)]
-
-#[lang="sized"]
-pub trait Sized {}
-
struct S<T> {
contents: T,
}
use std::cell::RefCell;
-trait Trait {}
+trait Trait : ::std::marker::MarkerTrait {}
pub fn main() {
let x: Vec<Trait + Sized> = Vec::new();
+++ /dev/null
-// Copyright 2012 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.
-
-fn false() { } //~ ERROR expected identifier, found keyword `false`
-fn main() { }
+++ /dev/null
-// Copyright 2012 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.
-
-fn true() { } //~ ERROR expected identifier, found keyword `true`
-fn main() { }
use std::fmt::Show;
use std::default::Default;
+use std::marker::MarkerTrait;
// Test that two blanket impls conflict (at least without negative
// bounds). After all, some other crate could implement Even or Odd
fn get(&self) -> usize;
}
-trait Even { }
+trait Even : MarkerTrait { }
-trait Odd { }
+trait Odd : MarkerTrait { }
impl Even for isize { }
fn get(&self) -> usize;
}
-trait Even { }
+trait Even : ::std::marker::MarkerTrait { }
-trait Odd { }
+trait Odd : ::std::marker::MarkerTrait { }
impl<T:Even> MyTrait for T { //~ ERROR E0119
fn get(&self) -> usize { 0 }
#![feature(optin_builtin_traits)]
-trait MyTrait {}
+trait MyTrait : ::std::marker::MarkerTrait {}
-struct TestType<T>;
+struct TestType<T>(::std::marker::PhantomData<T>);
-unsafe impl<T: MyTrait> Send for TestType<T> {}
+unsafe impl<T: MyTrait+'static> Send for TestType<T> {}
//~^ ERROR conflicting implementations for trait `core::marker::Send`
//~^^ ERROR conflicting implementations for trait `core::marker::Send`
impl<T: MyTrait> !Send for TestType<T> {}
//~^ ERROR conflicting implementations for trait `core::marker::Send`
-unsafe impl<T> Send for TestType<T> {}
+unsafe impl<T:'static> Send for TestType<T> {}
//~^ ERROR error: conflicting implementations for trait `core::marker::Send`
impl !Send for TestType<i32> {}
--- /dev/null
+// Copyright 2015 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.
+
+// Test that two distinct impls which match subtypes of one another
+// yield coherence errors (or not) depending on the variance.
+
+trait Contravariant {
+ fn foo(&self) { }
+}
+
+impl Contravariant for for<'a,'b> fn(&'a u8, &'b u8) {
+ //~^ ERROR E0119
+}
+
+impl Contravariant for for<'a> fn(&'a u8, &'a u8) {
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+trait Covariant {
+ fn foo(&self) { }
+}
+
+impl Covariant for for<'a,'b> fn(&'a u8, &'b u8) {
+ //~^ ERROR E0119
+}
+
+impl Covariant for for<'a> fn(&'a u8, &'a u8) {
+}
+
+///////////////////////////////////////////////////////////////////////////
+
+trait Invariant {
+ fn foo(&self) -> Self { }
+}
+
+impl Invariant for for<'a,'b> fn(&'a u8, &'b u8) {
+}
+
+impl Invariant for for<'a> fn(&'a u8, &'a u8) {
+}
+
+fn main() { }
#![feature(box_syntax)]
struct Foo;
-trait Trait {}
+trait Trait { fn foo(&self) {} }
impl Trait for Foo {}
pub fn main() {
#![feature(box_patterns)]
#![feature(box_syntax)]
-trait T {}
+trait T { fn foo(&self) {} }
impl T for isize {}
fn main() {
+++ /dev/null
-// Copyright 2012 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.
-
-/// hi
-#[derive(Debug)] //~ERROR expected item after attributes
+++ /dev/null
-// Copyright 2012 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.
-
-/// hi //~ERROR expected item after doc comment
+++ /dev/null
-// Copyright 2012 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.
-
-extern {
- /// hi
-}
-//~^^ ERROR expected item after doc comment
+++ /dev/null
-// Copyright 2012 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.
-
-fn main() {
- /// hi
- println!("hi");
- //~^^ ERROR expected item after doc comment
-}
+++ /dev/null
-// Copyright 2012 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.
-
-fn main() {
- println!("Hi"); /// hi
- //~^ ERROR expected item after doc comment
-}
+++ /dev/null
-// Copyright 2012 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.
-
-fn main() {
- /// hi
- ;
- //~^^ ERROR expected item after doc comment
-}
}
struct Foo;
-trait Bar {}
+trait Bar { fn bar(&self) {} }
pub fn main() {
// With a vec of isize.
}
struct Foo;
-trait Bar {}
+trait Bar : ::std::marker::MarkerTrait {}
impl Bar for Foo {}
pub fn main() {
}
struct Foo;
-trait Bar {}
+trait Bar { fn bar(&self) {} }
impl Bar for Foo {}
fn baz<'a>() {
// Test implicit coercions involving DSTs and raw pointers.
+use std::marker::MarkerTrait;
+
struct S;
-trait T {}
+trait T : MarkerTrait {}
impl T for S {}
struct Foo<T: ?Sized> {
// Test that we cannot create objects from unsized types.
-trait Foo {}
+trait Foo { fn foo(&self) {} }
impl Foo for str {}
fn test1<T: ?Sized + Foo>(t: &T) {
}
#[derive(Copy)] //~ ERROR the trait `Copy` may not be implemented
-struct Bar<T>;
+struct Bar<T>(::std::marker::PhantomData<T>);
#[unsafe_destructor]
impl<T> Drop for Bar<T> {
+++ /dev/null
-// 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.
-
-// Tests that the proper help is displayed in the error message
-
-extern crate foo as bar;
-//~^ ERROR expected `;`, found `as`
-//~^^ HELP perhaps you meant to enclose the crate name `foo` in a string?
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-struct Foo<A, B, C = (A, B)>;
+use std::marker;
+
+struct Foo<A, B, C = (A, B)>(
+ marker::PhantomData<(A,B,C)>);
impl<A, B, C = (A, B)> Foo<A, B, C> {
- fn new() -> Foo<A, B, C> {Foo}
+ fn new() -> Foo<A, B, C> {Foo(marker::PhantomData)}
}
fn main() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::marker;
+
struct Heap;
-struct Vec<T, A = Heap>;
+struct Vec<T, A = Heap>(
+ marker::PhantomData<(T,A)>);
impl<T, A = Heap> Vec<T, A> {
- fn new() -> Vec<T, A> {Vec}
+ fn new() -> Vec<T, A> {Vec(marker::PhantomData)}
}
fn main() {
//
// Regression test for issue #16218.
-trait Bar<'a> {}
+trait Bar<'a> {
+ fn dummy(&'a self);
+}
trait Foo<'a> {
+ fn dummy(&'a self) { }
fn bar<'b, T: Bar<'b>>(self) -> &'b str;
}
+++ /dev/null
-// 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.
-
-struct Heap;
-
-struct Vec<A = Heap, T>; //~ ERROR type parameters with a default must be trailing
-
-struct Foo<A, B = Vec<C>, C>; //~ ERROR type parameters with a default must be trailing
-
-fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::marker;
+
struct Heap;
-struct Vec<T, A = Heap>;
+struct Vec<T, A = Heap>(
+ marker::PhantomData<(T,A)>);
fn main() {
let _: Vec; //~ ERROR wrong number of type arguments: expected at least 1, found 0
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::marker;
+
struct Heap;
-struct Vec<T, A = Heap>;
+struct Vec<T, A = Heap>(
+ marker::PhantomData<(T,A)>);
fn main() {
let _: Vec<isize, Heap, bool>;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::marker;
+
struct A;
struct B;
struct C;
-struct Foo<T = A, U = B, V = C>;
+struct Foo<T = A, U = B, V = C>(marker::PhantomData<(T,U,V)>);
-struct Hash<T>;
-struct HashMap<K, V, H = Hash<K>>;
+struct Hash<T>(marker::PhantomData<T>);
+struct HashMap<K, V, H = Hash<K>>(marker::PhantomData<(K,V,H)>);
fn main() {
// Ensure that the printed type doesn't include the default type params...
+++ /dev/null
-// 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.
-
-// issue #17123
-
-fn main() {
- 100000000000000000000000000000000 //~ ERROR int literal is too large
-
- ; // the span shouldn't point to this.
-}
+++ /dev/null
-// Copyright 2013 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.
-
-
-trait Serializable<'self, T> { //~ ERROR no longer a special lifetime
- fn serialize(val : &'self T) -> Vec<u8> ; //~ ERROR no longer a special lifetime
- fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR no longer a special lifetime
-}
-
-impl<'self> Serializable<str> for &'self str { //~ ERROR no longer a special lifetime
- //~^ ERROR no longer a special lifetime
- fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR no longer a special lifetime
- vec!(1)
- }
- fn deserialize(repr: &[u8]) -> &'self str { //~ ERROR no longer a special lifetime
- "hi"
- }
-}
-
-fn main() {
- println!("hello");
- let x = "foo".to_string();
- let y = x;
- println!("{}", y);
-}
#![feature(box_syntax)]
-struct Test<'s> {
+struct Test {
func: Box<FnMut()+'static>
}
+++ /dev/null
-// 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.
-
-// For style and consistency reasons, non-parametrized enum variants must
-// be used simply as `ident` instead of `ident ()`.
-// This test-case covers enum declaration.
-
-enum Foo {
- Bar(), //~ ERROR nullary enum variants are written with no trailing `( )`
- Baz(), //~ ERROR nullary enum variants are written with no trailing `( )`
- Bazar
-}
-
-fn main() {
- println!("{}", match Bar { Bar => 1, Baz => 2, Bazar => 3 })
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait FromStructReader<'a> { }
+use std::marker::PhantomFn;
+
+trait FromStructReader<'a> : PhantomFn<(Self,&'a ())> { }
trait ResponseHook {
fn get<'a, T: FromStructReader<'a>>(&'a self);
}
#![crate_type = "lib"]
+use std::marker::PhantomData;
+
enum NodeContents<'a> {
Children(Vec<Node<'a>>),
}
struct Node<'a> {
contents: NodeContents<'a>,
+ marker: PhantomData<&'a ()>,
}
impl<'a> Node<'a> {
fn noName(contents: NodeContents<'a>) -> Node<'a> {
- Node{ contents: contents,}
+ Node { contents: contents, marker: PhantomData }
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Node {
+use std::marker::MarkerTrait;
+
+trait Node : MarkerTrait {
fn zomg();
}
+++ /dev/null
-// 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.
-
-// ignore-test FIXME(japari) remove test
-
-struct Foo {
- f: for <'b> |&'b isize|:
- 'b -> &'b isize //~ ERROR use of undeclared lifetime name `'b`
-}
-
-fn main() {
- let mut x: Vec< for <'a> ||
- :'a //~ ERROR use of undeclared lifetime name `'a`
- > = Vec::new();
- x.push(|| {});
-
- let foo = Foo {
- f: |x| x
- };
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Foo {}
+trait Foo {
+ fn dummy(&self) { }
+}
struct A;
// except according to those terms.
use std::fmt::Debug;
+use std::marker::MarkerTrait;
-trait Str {}
+trait Str : MarkerTrait {}
trait Something {
fn yay<T: Debug>(_: Option<Self>, thing: &[T]);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait ListItem<'a> {
+use std::marker::MarkerTrait;
+
+trait ListItem<'a> : MarkerTrait {
fn list_name() -> &'a str;
}
+++ /dev/null
-// 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.
-
-enum X {
- A =
- b'a' //~ ERROR discriminator values can only be used with a c-like enum
- ,
- B(isize)
-}
-
-fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-struct Foo<T> { foo: Option<Option<Foo<T>>> }
+use std::marker;
+
+struct Foo<T> { foo: Option<Option<Foo<T>>>, marker: marker::PhantomData<T> }
//~^ ERROR illegal recursive struct type; wrap the inner value in a box to make it representable
impl<T> Foo<T> { fn bar(&self) {} }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::marker;
+
struct Foo { foo: Bar<Foo> }
-struct Bar<T> { x: Bar<Foo> }
+struct Bar<T> { x: Bar<Foo> , marker: marker::PhantomData<T> }
//~^ ERROR illegal recursive struct type; wrap the inner value in a box to make it representable
impl Foo { fn foo(&self) {} }
#![feature(unboxed_closures)]
-struct B<T>;
+use std::marker;
+
+struct B<T>(marker::PhantomData<T>);
fn main() {
- let foo = B; //~ ERROR: unable to infer enough type information
+ let foo = B(marker::PhantomData); //~ ERROR unable to infer enough type information
let closure = || foo;
}
+++ /dev/null
-// 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.
-
-const
-mut //~ ERROR: const globals cannot be mutable
-//~^ HELP did you mean to declare a static?
-FOO: usize = 3;
-
-fn main() {
-}
-
--- /dev/null
+// 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.
+
+// Test that we can parse a unit struct with a where clause, even if
+// it leads to a error later on since `T` is unused.
+
+struct Foo<T> where T: Copy; //~ ERROR parameter `T` is never used
+
+fn main() {}
+++ /dev/null
-// Copyright 2012 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.
-
-// error-pattern:no valid digits found for number
-fn main() {
- log(error, 0b_usize);
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::marker::MarkerTrait;
-
-pub trait AbstractRenderer {}
+pub trait AbstractRenderer : MarkerTrait {}
fn _create_render(_: &()) ->
AbstractRenderer
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::marker::MarkerTrait;
+
fn add_state(op: <isize as HasState>::State) {
//~^ ERROR the trait `HasState` is not implemented for the type `isize`
}
-trait HasState {
+trait HasState : MarkerTrait {
type State;
}
Push::push(&c, box || y = 0);
Push::push(&c, box || y = 0);
+//~^ ERROR cannot borrow `y` as mutable more than once at a time
}
trait Push<'c> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Foo {
+use std::marker::MarkerTrait;
+
+trait Foo : MarkerTrait {
type Item;
}
#![feature(lang_items, start, no_std)]
#![no_std]
+#[lang="phantom_fn"]
+trait PhantomFn<A:?Sized,R:?Sized=()> { }
+impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
+
#[lang = "sized"]
-trait Sized {}
+trait Sized : PhantomFn<Self> {}
#[start]
fn main(_: int, _: *const *const u8) -> int {
// cause compiler to loop. Note that no instances
// of such a type could ever be constructed.
+use std::marker::MarkerTrait;
struct t(Box<t>); //~ ERROR this type cannot be instantiated
-trait to_str_2 {
+trait to_str_2 : MarkerTrait {
fn my_to_string() -> String;
}
// below. Note that changing to a named lifetime made the problem go
// away.
-use std::ops::{Shl, Shr};
use std::cell::RefCell;
+use std::marker::MarkerTrait;
+use std::ops::{Shl, Shr};
-pub trait Subscriber {
+pub trait Subscriber : MarkerTrait {
type Input;
}
#[derive(Hash)]
struct Foo(Bar);
-//~^ error: the trait `core::hash::Hash<_>` is not implemented for the type `Bar`
+//~^ error: the trait `core::hash::Hash` is not implemented for the type `Bar`
fn main() {}
// than the trait method it's implementing
trait A {
- fn b<C,D>(x: C) -> C;
+ fn b<C,D>(&self, x: C) -> C;
}
struct E {
}
impl A for E {
- fn b<F: Sync, G>(_x: F) -> F { panic!() }
+ fn b<F: Sync, G>(&self, _x: F) -> F { panic!() }
//~^ ERROR `F : core::marker::Sync` appears on the impl method
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::marker;
+
enum E1 { V1(E2<E1>), }
-enum E2<T> { V2(E2<E1>), }
+enum E2<T> { V2(E2<E1>, marker::PhantomData<T>), }
//~^ ERROR illegal recursive enum type; wrap the inner value in a box to make it representable
impl E1 { fn foo(&self) {} }
#![feature(box_patterns)]
#![feature(box_syntax)]
-trait MyTrait { }
+trait MyTrait {
+ fn dummy(&self) {}
+}
pub enum TraitWrapper {
A(Box<MyTrait+'static>),
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait I {}
+use std::marker::MarkerTrait;
+
+trait I : MarkerTrait {}
type K = I+'static;
fn foo(_x: K) {} //~ ERROR: the trait `core::marker::Sized` is not implemented
#![feature(box_syntax)]
-trait Foo {}
+trait Foo { fn foo(&self) {} }
impl Foo for u8 {}
fn main() {
+++ /dev/null
-// Copyright 2013 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.
-
-fn main() {
- let __isize = 18446744073709551616; // 2^64
- //~^ ERROR int literal is too large
-}
+++ /dev/null
-// Copyright 2013 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.
-
-fn main() {
- let __isize = 0xff_ffff_ffff_ffff_ffff__isize;
- //~^ ERROR int literal is too large
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait A {}
+use std::marker::MarkerTrait;
+
+trait A : MarkerTrait {}
struct Struct {
r: A+'static
Struct { r: r }
}
-trait Curve {}
+trait Curve : MarkerTrait {}
enum E {X(Curve+'static)}
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub struct TypeWithState<State>;
+use std::marker;
+
+pub struct TypeWithState<State>(marker::PhantomData<State>);
pub struct MyState;
pub fn foo<State>(_: TypeWithState<State>) {}
pub fn bar() {
- foo(TypeWithState); //~ ERROR type annotations required
+ foo(TypeWithState(marker::PhantomData)); //~ ERROR type annotations required
}
fn main() {
// Test the mechanism for warning about possible missing `self` declarations.
+use std::marker::MarkerTrait;
+
trait CtxtFn {
fn f8(self, usize) -> usize;
fn f9(usize) -> usize; //~ NOTE candidate
}
-trait OtherTrait {
+trait OtherTrait : MarkerTrait {
fn f9(usize) -> usize; //~ NOTE candidate
}
// declaration to match against, so we wind up prisizeing it as a
// candidate. This seems not unreasonable -- perhaps the user meant to
// implement it, after all.
-trait UnusedTrait {
+trait UnusedTrait : MarkerTrait {
fn f9(usize) -> usize; //~ NOTE candidate
}
}
}
-trait ManyImplTrait {
+trait ManyImplTrait : MarkerTrait {
fn is_str() -> bool { //~ NOTE candidate
false
}
+++ /dev/null
-// 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.
-
-pub extern
- "invalid-ab_isize" //~ ERROR illegal ABI
-fn foo() {}
-
-fn main() {}
// Verify the compiler fails with an error on infinite function
// recursions.
-struct Data(Box<Option<Data>>);
-
-fn generic<T>( _ : Vec<(Data,T)> ) {
- let rec : Vec<(Data,(bool,T))> = Vec::new();
- generic( rec );
+fn generic<T>() {
+ generic::<Option<T>>();
}
fn main () {
// Use generic<T> at least once to trigger instantiation.
- let input : Vec<(Data,())> = Vec::new();
- generic(input);
+ generic::<i32>();
}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py as'
-
-fn main() {
- let as = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py break'
-
-fn main() {
- let break = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py else'
-
-fn main() {
- let else = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py enum'
-
-fn main() {
- let enum = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py extern'
-
-fn main() {
- let extern = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py fn'
-
-fn main() {
- let fn = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py for'
-
-fn main() {
- let for = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py if'
-
-fn main() {
- let if = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py impl'
-
-fn main() {
- let impl = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py let'
-
-fn main() {
- let let = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py loop'
-
-fn main() {
- let loop = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py match'
-
-fn main() {
- let match = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py mod'
-
-fn main() {
- let mod = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py pub'
-
-fn main() {
- let pub = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py return'
-
-fn main() {
- let return = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py self'
-
-fn main() {
- let self = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py static'
-
-fn main() {
- let static = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py struct'
-
-fn main() {
- let struct = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py super'
-
-fn main() {
- let super = "foo"; //~ error: ident
-}
+++ /dev/null
-// 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.
-
-fn main() {
- let super: isize; //~ ERROR expected identifier, found keyword `super`
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py trait'
-
-fn main() {
- let trait = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py type'
-
-fn main() {
- let type = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py unsafe'
-
-fn main() {
- let unsafe = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py use'
-
-fn main() {
- let use = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// This file was auto-generated using 'src/etc/generate-keyword-tests.py while'
-
-fn main() {
- let while = "foo"; //~ error: ident
-}
+++ /dev/null
-// Copyright 2012 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.
-
-pub mod break {
- //~^ ERROR expected identifier, found keyword `break`
-}
+++ /dev/null
-// 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.
-
-fn main() {
- struct::foo(); //~ ERROR expected identifier
- mut::baz(); //~ ERROR expected identifier
-}
-
// Test which of the builtin types are considered POD.
-
+use std::marker::MarkerTrait;
use std::rc::Rc;
fn assert_copy<T:Copy>() { }
-trait Dummy { }
+trait Dummy : MarkerTrait { }
#[derive(Copy)]
struct MyStruct {
#![feature(box_syntax)]
-trait Foo {
+use std::marker::MarkerTrait;
+
+trait Foo : MarkerTrait {
}
impl<T:Copy> Foo for T {
#![feature(box_syntax)]
-struct S<T>;
+use std::marker;
-trait Gettable<T> {}
+struct S<T>(marker::PhantomData<T>);
+
+trait Gettable<T> {
+ fn get(&self) -> T { panic!() }
+}
impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
fn f<T>(val: T) {
- let t: S<T> = S;
+ let t: S<T> = S(marker::PhantomData);
let a = &t as &Gettable<T>;
//~^ ERROR the trait `core::marker::Send` is not implemented
//~^^ ERROR the trait `core::marker::Copy` is not implemented
}
fn g<T>(val: T) {
- let t: S<T> = S;
+ let t: S<T> = S(marker::PhantomData);
let a: &Gettable<T> = &t;
//~^ ERROR the trait `core::marker::Send` is not implemented
//~^^ ERROR the trait `core::marker::Copy` is not implemented
}
fn foo<'a>() {
- let t: S<&'a isize> = S;
+ let t: S<&'a isize> = S(marker::PhantomData);
let a = &t as &Gettable<&'a isize>;
- //~^ ERROR the type `&'a isize` does not fulfill the required lifetime
+ //~^ ERROR cannot infer
}
fn foo2<'a>() {
- let t: Box<S<String>> = box S;
+ let t: Box<S<String>> = box S(marker::PhantomData);
let a = t as Box<Gettable<String>>;
//~^ ERROR the trait `core::marker::Copy` is not implemented
}
fn foo3<'a>() {
- let t: Box<S<String>> = box S;
+ let t: Box<S<String>> = box S(marker::PhantomData);
let a: Box<Gettable<String>> = t;
//~^ ERROR the trait `core::marker::Copy` is not implemented
}
use std::any::Any;
trait Foo : Copy {
+ fn foo(&self) {}
}
impl<T:Copy> Foo for T {
// in this file all test the "kind" violates detected during kindck.
// See all `regions-bounded-by-send.rs`
+use std::marker::MarkerTrait;
+
fn assert_send<T:Send>() { }
-trait Dummy { }
+trait Dummy : MarkerTrait { }
trait Message : Send { }
// careful with object types, who knows what they close over...
// is broken into two parts because some errors occur in distinct
// phases in the compiler. See kindck-send-object2.rs as well!
+use std::marker::MarkerTrait;
+
fn assert_send<T:Send+'static>() { }
-trait Dummy { }
+trait Dummy : MarkerTrait { }
// careful with object types, who knows what they close over...
fn test51<'a>() {
// Continue kindck-send-object1.rs.
+use std::marker::MarkerTrait;
+
fn assert_send<T:Send>() { }
-trait Dummy { }
+trait Dummy : MarkerTrait { }
fn test50() {
assert_send::<&'static Dummy>(); //~ ERROR the trait `core::marker::Sync` is not implemented
+++ /dev/null
-// 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.
-
-fn main() {
- 0o1.0; //~ ERROR: octal float literal is not supported
- 0o2f32; //~ ERROR: octal float literal is not supported
- 0o3.0f32; //~ ERROR: octal float literal is not supported
- 0o4e4; //~ ERROR: octal float literal is not supported
- 0o5.0e5; //~ ERROR: octal float literal is not supported
- 0o6e6f32; //~ ERROR: octal float literal is not supported
- 0o7.0e7f64; //~ ERROR: octal float literal is not supported
- 0x8.0e+9; //~ ERROR: hexadecimal float literal is not supported
- 0x9.0e-9; //~ ERROR: hexadecimal float literal is not supported
- 0o; //~ ERROR: no valid digits
- 1e+; //~ ERROR: expected at least one digit in exponent
- 0x539.0; //~ ERROR: hexadecimal float literal is not supported
- 99999999999999999999999999999999; //~ ERROR: int literal is too large
- 99999999999999999999999999999999u32; //~ ERROR: int literal is too large
- 0x; //~ ERROR: no valid digits
- 0xu32; //~ ERROR: no valid digits
- 0ou32; //~ ERROR: no valid digits
- 0bu32; //~ ERROR: no valid digits
- 0b; //~ ERROR: no valid digits
- 0o123f64; //~ ERROR: octal float literal is not supported
- 0o123.456; //~ ERROR: octal float literal is not supported
- 0b101f64; //~ ERROR: binary float literal is not supported
- 0b111.101; //~ ERROR: binary float literal is not supported
-}
+++ /dev/null
-// 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.
-
-// ignore-tidy-cr
-
-/// doc comment with bare CR: '\r'
-pub fn foo() {}
-//~^^ ERROR: bare CR not allowed in doc-comment
-
-/** block doc comment with bare CR: '\r' */
-pub fn bar() {}
-//~^^ ERROR: bare CR not allowed in block doc-comment
-
-fn main() {
- // the following string literal has a bare CR in it
- let _s = "foo\rbar"; //~ ERROR: bare CR not allowed in string
-
- // the following string literal has a bare CR in it
- let _s = r"bar\rfoo"; //~ ERROR: bare CR not allowed in raw string
-
- // the following string literal has a bare CR in it
- let _s = "foo\\rbar"; //~ ERROR: unknown character escape: \r
-}
// ignore-tidy-linelength
-struct Bar<'x, 'y, 'z> { bar: &'y i32, baz: i32 }
+use std::marker::PhantomData;
+
+struct Bar<'x, 'y, 'z> { bar: &'y i32, baz: i32, marker: PhantomData<(&'x(),&'y(),&'z())> }
fn bar1<'a>(x: &Bar) -> (&'a i32, &'a i32, &'a i32) {
//~^ HELP: consider using an explicit lifetime parameter as shown: fn bar1<'b, 'c, 'a>(x: &'a Bar<'b, 'a, 'c>) -> (&'a i32, &'a i32, &'a i32)
(x.bar, &x.baz, &x.baz)
// ignore-tidy-linelength
-struct Foo<'x> { bar: isize }
+use std::marker::PhantomData;
+
+struct Foo<'x> { bar: isize, marker: PhantomData<&'x ()> }
fn foo1<'a>(x: &Foo) -> &'a isize {
//~^ HELP: consider using an explicit lifetime parameter as shown: fn foo1<'a>(x: &'a Foo) -> &'a isize
&x.bar //~ ERROR: cannot infer
+++ /dev/null
-// Copyright 2013 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.
-
-fn foo<'a>(a: &'a isize) { }
-fn bar(a: &'static isize) { }
-fn baz(a: &'let isize) { } //~ ERROR invalid lifetime name
-
-fn main() { }
+++ /dev/null
-// Copyright 2013 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.
-
-fn baz(a: &'self isize) { } //~ ERROR invalid lifetime name: 'self is no longer a special lifetime
-
-fn main() { }
/// dox
pub trait A {
/// dox
- fn foo();
+ fn foo(&self);
/// dox
- fn foo_with_impl() {}
+ fn foo_with_impl(&self) {}
}
+
#[allow(missing_docs)]
trait B {
- fn foo();
- fn foo_with_impl() {}
+ fn foo(&self);
+ fn foo_with_impl(&self) {}
}
+
pub trait C { //~ ERROR: missing documentation
- fn foo(); //~ ERROR: missing documentation
- fn foo_with_impl() {} //~ ERROR: missing documentation
+ fn foo(&self); //~ ERROR: missing documentation
+ fn foo_with_impl(&self) {} //~ ERROR: missing documentation
+}
+
+#[allow(missing_docs)]
+pub trait D {
+ fn dummy(&self) { }
}
-#[allow(missing_docs)] pub trait D {}
impl Foo {
pub fn foo() {}
}
trait foo6 { //~ ERROR trait `foo6` should have a camel case name such as `Foo6`
+ fn dummy(&self) { }
}
fn f<ty>(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name such as `Ty`
#[unstable(feature = "test_feature")]
#[deprecated(since = "1.0.0")]
- pub trait DeprecatedTrait {}
+ pub trait DeprecatedTrait {
+ fn dummy(&self) { }
+ }
struct S;
#![allow(dead_code)]
#![crate_type="lib"]
-struct Private<T>;
-pub struct Public<T>;
+use std::marker;
+
+struct Private<T>(marker::PhantomData<T>);
+pub struct Public<T>(marker::PhantomData<T>);
impl Private<Public<isize>> {
pub fn a(&self) -> Private<isize> { panic!() }
fn bar(&self) -> Private<isize> { panic!() }
}
-pub trait ParamTrait<T> {
+pub trait ParamTrait<T> : marker::MarkerTrait {
fn foo() -> T;
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::marker;
+
fn send<T:Send + std::fmt::Debug>(ch: _chan<T>, data: T) {
println!("{:?}", ch);
println!("{:?}", data);
}
#[derive(Debug)]
-struct _chan<T>(isize);
+struct _chan<T>(isize, marker::PhantomData<T>);
// Tests that "log(debug, message);" is flagged as using
// message after the send deinitializes it
+++ /dev/null
-// 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.
-
-macro_rules! foo() //~ ERROR semicolon
-
-fn main() {
-}
use std::collections::HashMap;
-trait Map<K, V> {}
+trait Map<K, V>
+{
+ fn get(&self, k: K) -> V { panic!() }
+}
impl<K, V> Map<K, V> for HashMap<K, V> {}
+++ /dev/null
-// Copyright 2012 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.
-
-// Test that when we pick a trait based on coercion, versus subtyping,
-// we consider all possible coercions equivalent and don't try to pick
-// a best one.
-
-trait Object { }
-
-trait foo {
- fn foo(self) -> isize;
-}
-
-impl foo for Box<Object+'static> {
- fn foo(self) -> isize {1}
-}
-
-impl foo for Box<Object+Send> {
- fn foo(self) -> isize {2}
-}
-
-fn test1(x: Box<Object+Send+Sync>) {
- // FIXME(#18737) -- we ought to consider this to be ambiguous,
- // since we could coerce to either impl. However, what actually
- // happens is that we consider both impls applicable because of
- // incorrect subtyping relation. We then decide to call this a
- // call to the `foo` trait, leading to the following error
- // message.
-
- x.foo(); //~ ERROR `foo` is not implemented
-}
-
-fn test2(x: Box<Object+Send>) {
- // Not ambiguous because it is a precise match:
- x.foo();
-}
-
-fn test3(x: Box<Object+'static>) {
- // Not ambiguous because it is a precise match:
- x.foo();
-}
-
-fn main() { }
--- /dev/null
+// Copyright 2012 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.
+
+mod mod_file_disambig_aux; //~ ERROR file for module `mod_file_disambig_aux` found at both
+
+fn main() {
+ assert_eq!(mod_file_aux::bar(), 10);
+}
--- /dev/null
+// 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.
+
+// error-pattern: cannot declare a new module at this location
+
+mod mod_file_not_owning_aux1;
+
+fn main() {}
+++ /dev/null
-// Copyright 2013 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.
-
-// error-pattern:binary float literal is not supported
-
-fn main() {
- 0b101010f64;
- 0b101.010;
- 0b101p4f64;
-}
+++ /dev/null
-// Copyright 2013 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.
-
-// error-pattern:hexadecimal float literal is not supported
-
-fn main() {
- 0xABC.Df;
- 0x567.89;
- 0xDEAD.BEEFp-2f;
-}
+++ /dev/null
-// Copyright 2013 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.
-
-trait A {
- fn foo(*mut self); //~ ERROR cannot pass self by unsafe pointer
- fn bar(*self); //~ ERROR cannot pass self by unsafe pointer
-}
-
-struct X;
-impl A for X {
- fn foo(*mut self) { } //~ ERROR cannot pass self by unsafe pointer
- fn bar(*self) { } //~ ERROR cannot pass self by unsafe pointer
-}
-
-fn main() { }
+++ /dev/null
-// Copyright 2012 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.
-
-// Issue #623 - non-string meta items are not serialized correctly;
-// for now just forbid them
-
-#[foo = 1] //~ ERROR: non-string literals are not allowed in meta-items
-fn main() { }
// Test that an object type `Box<Foo>` is not considered to implement the
// trait `Foo`. Issue #5087.
+use std::marker::MarkerTrait;
-trait Foo {}
+trait Foo : MarkerTrait {}
fn take_foo<F:Foo>(f: F) {}
fn take_object(f: Box<Foo>) { take_foo(f); }
//~^ ERROR the trait `Foo` is not implemented
a
//~^ ERROR cannot infer
//~| ERROR mismatched types
- //~| ERROR mismatched types
}
fn main() {
--- /dev/null
+// Copyright 2015 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.
+
+// Regression test for #22040.
+
+use std::fmt::Debug;
+
+trait Expr: Debug + PartialEq {
+ fn print_element_count(&self);
+}
+
+//#[derive(PartialEq)]
+#[derive(Debug)]
+struct SExpr<'x> {
+ elements: Vec<Box<Expr+ 'x>>,
+}
+
+impl<'x> PartialEq for SExpr<'x> {
+ fn eq(&self, other:&SExpr<'x>) -> bool {
+ println!("L1: {} L2: {}", self.elements.len(), other.elements.len());
+ let result = self.elements.len() == other.elements.len();
+
+ println!("Got compare {}", result);
+ return result;
+ }
+}
+
+impl <'x> SExpr<'x> {
+ fn new() -> SExpr<'x> { return SExpr{elements: Vec::new(),}; }
+}
+
+impl <'x> Expr for SExpr<'x> {
+ fn print_element_count(&self) {
+ println!("element count: {}", self.elements.len());
+ }
+}
+
+fn main() {
+ let a: Box<Expr> = Box::new(SExpr::new()); //~ ERROR trait `Expr` is not object-safe
+ let b: Box<Expr> = Box::new(SExpr::new()); //~ ERROR trait `Expr` is not object-safe
+
+ assert_eq!(a , b);
+}
// Check that we correctly prevent users from making trait objects
// from traits with static methods.
-trait Foo {
+trait Foo : ::std::marker::MarkerTrait {
fn foo();
}
--- /dev/null
+// 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.
+
+// Check that `Self` appearing in a phantom fn does not make a trait not object safe.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
+
+use std::marker::PhantomFn;
+
+trait Baz : PhantomFn<Self> {
+}
+
+trait Bar<T> : PhantomFn<(Self, T)> {
+}
+
+fn make_bar<T:Bar<u32>>(t: &T) -> &Bar<u32> {
+ t
+}
+
+fn make_baz<T:Baz>(t: &T) -> &Baz {
+ t
+}
+
+#[rustc_error]
+fn main() { //~ ERROR compilation successful
+}
--- /dev/null
+// 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.
+
+// Check that we correctly prevent users from making trait objects
+// form traits that make use of `Self` in an argument or return position.
+
+trait Bar<T> {
+ fn bar(&self, x: &T);
+}
+
+trait Baz : Bar<Self> {
+}
+
+fn make_bar<T:Bar<u32>>(t: &T) -> &Bar<u32> {
+ t
+}
+
+fn make_baz<T:Baz>(t: &T) -> &Baz {
+ t
+ //~^ ERROR `Baz` is not object-safe
+ //~| NOTE the trait cannot use `Self` as a type parameter in the supertrait listing
+}
+
+fn main() {
+}
+++ /dev/null
-// Copyright 2015 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.
-
-// Test that we generate obsolete syntax errors around usages of `for Sized?`
-
-trait Foo for Sized? {} //~ ERROR obsolete syntax: for Sized?
-
-trait Bar for ?Sized {} //~ ERROR obsolete syntax: for Sized?
-
-fn main() { }
+++ /dev/null
-// 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.
-
-// Test that we generate obsolete syntax errors around usages of `proc`.
-
-fn foo(p: proc()) { } //~ ERROR obsolete syntax: the `proc` type
-
-fn bar() { proc() 1; } //~ ERROR obsolete syntax: `proc` expression
-
-fn main() { }
#![allow(unused)]
+use std::marker;
+
#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"]
-trait Foo<Bar, Baz, Quux>{}
+trait Foo<Bar, Baz, Quux>
+ : marker::PhantomFn<(Self,Bar,Baz,Quux)>
+{}
#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"]
trait MyFromIterator<A> {
}
#[rustc_on_unimplemented] //~ ERROR this attribute must have a value
-trait BadAnnotation1 {}
+trait BadAnnotation1
+ : marker::MarkerTrait
+{}
#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
//~^ ERROR there is no type parameter C on trait BadAnnotation2
-trait BadAnnotation2<A,B> {}
+trait BadAnnotation2<A,B>
+ : marker::PhantomFn<(Self,A,B)>
+{}
#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"]
//~^ only named substitution parameters are allowed
-trait BadAnnotation3<A,B> {}
+trait BadAnnotation3<A,B>
+ : marker::PhantomFn<(Self,A,B)>
+{}
pub fn main() {
}
#![feature(on_unimplemented)]
+use std::marker;
+
#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"]
-trait Foo<Bar, Baz, Quux>{}
+trait Foo<Bar, Baz, Quux>
+ : marker::PhantomFn<(Self,Bar,Baz,Quux)>
+{}
fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T {
use orphan_check_diagnostics::RemoteTrait;
-trait LocalTrait {}
+trait LocalTrait { fn dummy(&self) { } }
impl<T> RemoteTrait for T where T: LocalTrait {}
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
}
trait A {
- fn foo() {}
+ fn foo(&self) {}
}
struct B;
pub impl B {} //~ ERROR: unnecessary visibility
pub impl A for B { //~ ERROR: unnecessary visibility
- pub fn foo() {} //~ ERROR: unnecessary visibility
+ pub fn foo(&self) {} //~ ERROR: unnecessary visibility
}
pub fn main() {}
// public type, private value
pub mod foo1 {
- pub trait Bar {
+ use std::marker::MarkerTrait;
+
+ pub trait Bar : MarkerTrait {
}
pub struct Baz;
// private type, public value
pub mod foo2 {
- trait Bar {
+ trait Bar : ::std::marker::MarkerTrait {
}
pub struct Baz;
// neither public
pub mod foo3 {
- trait Bar {
+ trait Bar : ::std::marker::MarkerTrait {
}
pub struct Baz;
#![feature(lang_items, start, no_std)]
#![no_std] // makes debugging this test *a lot* easier (during resolve)
+#[lang="phantom_fn"]
+pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
+impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
+
#[lang="sized"]
-pub trait Sized {}
+pub trait Sized : PhantomFn<Self> {}
#[lang="copy"]
-pub trait Copy {}
+pub trait Copy : PhantomFn<Self> {}
mod bar {
// shouldn't bring in too much
#![feature(lang_items, start, no_std)]
#![no_std] // makes debugging this test *a lot* easier (during resolve)
-#[lang = "sized"] pub trait Sized {}
-#[lang="copy"] pub trait Copy {}
+#[lang="phantom_fn"]
+pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
+impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
+
+#[lang = "sized"] pub trait Sized : PhantomFn<Self> {}
+#[lang="copy"] pub trait Copy : PhantomFn<Self> {}
// Test to make sure that private items imported through globs remain private
// when they're used.
+++ /dev/null
-// Copyright 2012-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.
-
-// ignore-test Can't use syntax crate here
-
-#![feature(quote)]
-
-extern crate syntax;
-
-use io::*;
-
-use syntax::diagnostic;
-use syntax::ast;
-use syntax::codemap;
-use syntax::parse;
-use syntax::print::*;
-
-
-trait fake_ext_ctxt {
- fn cfg() -> ast::CrateConfig;
- fn parse_sess() -> parse::parse_sess;
- fn call_site() -> span;
- fn ident_of(st: &str) -> ast::ident;
-}
-
-type fake_session = parse::parse_sess;
-
-impl fake_ext_ctxt for fake_session {
- fn cfg() -> ast::CrateConfig { Vec::new() }
- fn parse_sess() -> parse::parse_sess { self }
- fn call_site() -> span {
- codemap::span {
- lo: codemap::BytePos(0),
- hi: codemap::BytePos(0),
- expn_id: NO_EXPANSION
- }
- }
- fn ident_of(st: &str) -> ast::ident {
- self.interner.intern(st)
- }
-}
-
-fn mk_ctxt() -> fake_ext_ctxt {
- parse::new_parse_sess(None) as fake_ext_ctxt
-}
-
-
-
-fn main() {
- let cx = mk_ctxt();
-
- let abc = quote_expr!(cx, 23);
- check_pp(abc, pprust::print_expr, "23");
-
- let expr3 = quote_expr!(cx, 2 - $abcd + 7); //~ ERROR unresolved name: abcd
- check_pp(expr3, pprust::print_expr, "2 - 23 + 7");
-}
-
-fn check_pp<T>(expr: T, f: |pprust::ps, T|, expect: str) {
- panic!();
-}
+++ /dev/null
-// Copyright 2012-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.
-
-// ignore-test Can't use syntax crate here
-
-#![feature(quote)]
-
-extern crate syntax;
-
-use syntax::diagnostic;
-use syntax::ast;
-use syntax::codemap;
-use syntax::parse::parser;
-use syntax::print::*;
-
-trait fake_ext_ctxt {
- fn cfg() -> ast::CrateConfig;
- fn parse_sess() -> parse::parse_sess;
- fn call_site() -> span;
- fn ident_of(st: &str) -> ast::ident;
-}
-
-type fake_session = parse::parse_sess;
-
-impl fake_ext_ctxt for fake_session {
- fn cfg() -> ast::CrateConfig { Vec::new() }
- fn parse_sess() -> parse::parse_sess { self }
- fn call_site() -> span {
- codemap::span {
- lo: codemap::BytePos(0),
- hi: codemap::BytePos(0),
- expn_id: codemap::NO_EXPANSION
- }
- }
- fn ident_of(st: &str) -> ast::ident {
- self.interner.intern(st)
- }
-}
-
-fn mk_ctxt() -> fake_ext_ctxt {
- parse::new_parse_sess(None) as fake_ext_ctxt
-}
-
-
-fn main() {
- let cx = mk_ctxt();
-
- let stmt = quote_stmt!(cx, let x isize = 20;); //~ ERROR expected end-of-string
- check_pp(*stmt, pprust::print_stmt, "");
-}
-
-fn check_pp<T>(expr: T, f: |pprust::ps, T|, expect: str) {
- panic!();
-}
#![feature(box_syntax)]
-trait Foo {}
+trait Foo : ::std::marker::MarkerTrait {}
impl<'a> Foo for &'a [u8] {}
fn a(v: &[u8]) -> Box<Foo + 'static> {
#![allow(dead_code)]
-use std::mem::transmute;
-use std::ops::Deref;
+use std::marker::PhantomFn;
///////////////////////////////////////////////////////////////////////////
-pub trait TheTrait {
+pub trait TheTrait: PhantomFn<Self, Self> {
type TheAssocType;
-
- fn dummy(&self) { }
}
pub trait TheSubTrait : TheTrait {
#![allow(dead_code)]
#![feature(rustc_attrs)]
+use std::marker::PhantomFn;
+
///////////////////////////////////////////////////////////////////////////
-pub trait TheTrait<'b> {
+pub trait TheTrait<'b> : PhantomFn<&'b Self,Self> {
type TheAssocType;
-
- fn dummy(&'b self) { }
}
pub struct TheType<'b> {
#![allow(dead_code)]
-use std::mem::transmute;
-use std::ops::Deref;
+use std::marker::PhantomFn;
///////////////////////////////////////////////////////////////////////////
-pub trait TheTrait {
+pub trait TheTrait: PhantomFn<Self, Self> {
type TheAssocType;
-
- fn dummy(&self) { }
}
pub struct TheType<'b> {
// outlive the location in which the type appears. Issue #22246.
#![allow(dead_code)]
+#![feature(rustc_attrs)]
-use std::mem::transmute;
-use std::ops::Deref;
+use std::marker::PhantomFn;
///////////////////////////////////////////////////////////////////////////
-pub trait TheTrait {
+pub trait TheTrait: PhantomFn<Self, Self> {
type TheAssocType;
-
- fn dummy(&self) { }
}
pub struct TheType<'b> {
// Test that the compiler checks that arbitrary region bounds declared
// in the trait must be satisfied on the impl. Issue #20890.
-trait Foo<'a> { type Value: 'a; }
+trait Foo<'a> {
+ type Value: 'a;
+ fn dummy(&'a self) { }
+}
impl<'a> Foo<'a> for &'a i16 {
// OK.
// Test that the compiler checks that the 'static bound declared in
// the trait must be satisfied on the impl. Issue #20890.
-trait Foo { type Value: 'static; }
+trait Foo {
+ type Value: 'static;
+ fn dummy(&self) { }
+}
impl<'a> Foo for &'a i32 {
//~^ ERROR cannot infer
fn has_bound<'b:'a>(self, b: Inv<'b>);
fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
fn okay_bound<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
- fn another_bound<'x: 'a>(self, x: Inv<'x>);
+ fn another_bound<'x: 'a>(self, x: Inv<'x>, y: Inv<'t>);
}
-
impl<'a, 't> Foo<'a, 't> for &'a isize {
fn no_bound<'b:'a>(self, b: Inv<'b>) {
//~^ ERROR lifetime parameters or bounds on method `no_bound` do not match
fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) {
}
- fn another_bound<'x: 't>(self, x: Inv<'x>) {}
+ fn another_bound<'x: 't>(self, x: Inv<'x>, y: Inv<'t>) {}
}
fn main() { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(lang_items, no_std)]
-#![no_std]
-
// Check that explicit region bounds are allowed on the various
// nominal types (but not on other types) and that they are type
// checked.
-#[lang="sized"]
-trait Sized { }
-
struct Inv<'a> { // invariant w/r/t 'a
x: &'a mut &'a isize
}
#![feature(box_syntax)]
-trait X {}
+use std::marker::MarkerTrait;
+
+trait X : MarkerTrait {}
trait Iter {
type Item: X;
#![feature(box_syntax)]
#![allow(warnings)]
-trait A<T> {}
+use std::marker::PhantomFn;
+
+trait A<T> : PhantomFn<(Self,T)> { }
struct B<'a, T>(&'a (A<T>+'a));
-trait X {}
+trait X : ::std::marker::MarkerTrait {}
+
impl<'a, T> X for B<'a, T> {}
-fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+fn f<'a, T:'static, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
box B(&*v) as Box<X> //~ ERROR `*v` does not live long enough
}
#![feature(box_syntax)]
-trait A<T> {}
+use std::marker::PhantomFn;
+
+trait A<T> : PhantomFn<(Self,T)> { }
struct B<'a, T>(&'a (A<T>+'a));
-trait X {}
+trait X : PhantomFn<Self> {}
impl<'a, T> X for B<'a, T> {}
fn g<'a, T: 'static>(v: Box<A<T>+'a>) -> Box<X+'static> {
#![feature(box_syntax)]
#![allow(warnings)]
-trait A<T> {}
+use std::marker::PhantomFn;
+
+trait A<T> : PhantomFn<(Self,T)> {}
struct B<'a, T>(&'a (A<T>+'a));
-trait X {}
+trait X : PhantomFn<Self> {}
impl<'a, T> X for B<'a, T> {}
fn h<'a, T, U>(v: Box<A<U>+'static>) -> Box<X+'static> {
#![feature(box_syntax)]
-trait A<T> {}
+use std::marker::PhantomFn;
+
+trait A<T> : PhantomFn<(Self,T)> {}
struct B<'a, T>(&'a (A<T>+'a));
-trait X {}
+trait X : PhantomFn<Self> {}
impl<'a, T> X for B<'a, T> {}
fn i<'a, T, U>(v: Box<A<U>+'a>) -> Box<X+'static> {
--- /dev/null
+// 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.
+
+#![feature(box_syntax)]
+#![allow(warnings)]
+
+trait A<T>
+{
+ fn get(&self) -> T { panic!() }
+}
+
+struct B<'a, T>(&'a (A<T>+'a));
+
+trait X { fn foo(&self) {} }
+
+impl<'a, T> X for B<'a, T> {}
+
+fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
+ box B(&*v) as Box<X> //~ ERROR the parameter type `T` may not live long enough
+}
+
+fn main() {}
+
#![feature(box_syntax)]
-trait Foo { }
+use std::marker::MarkerTrait;
+
+trait Foo : MarkerTrait { }
impl<'a> Foo for &'a isize { }
#![feature(box_syntax)]
-trait X {}
+trait X { fn foo(&self) {} }
fn p1<T>(v: T) -> Box<X+'static>
where T : X
+++ /dev/null
-// 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.
-
-// ignore-test
-// ignored because the first error does not show up.
-
-// Copyright 2012 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.
-
-fn of<T>() -> |T| { panic!(); }
-fn subtype<T>(x: |T|) { panic!(); }
-
-fn test_fn<'x, 'y, 'z, T>(_x: &'x T, _y: &'y T, _z: &'z T) {
- // Here, x, y, and z are free. Other letters
- // are bound. Note that the arrangement
- // subtype::<T1>(of::<T2>()) will typecheck
- // iff T1 <: T2.
-
- // should be the default:
- subtype::< ||:'static>(of::<||>());
- subtype::<||>(of::< ||:'static>());
-
- //
- subtype::< <'x> ||>(of::<||>()); //~ ERROR mismatched types
- subtype::< <'x> ||>(of::< <'y> ||>()); //~ ERROR mismatched types
-
- subtype::< <'x> ||>(of::< ||:'static>()); //~ ERROR mismatched types
- subtype::< ||:'static>(of::< <'x> ||>());
-
-}
-
-fn main() {}
// Contravariant<'foo> <: Contravariant<'static> because
// 'foo <= 'static
struct Contravariant<'a> {
- marker: marker::ContravariantLifetime<'a>
+ marker: marker::PhantomData<&'a()>
}
fn use_<'short,'long>(c: Contravariant<'short>,
use std::marker;
struct Covariant<'a> {
- marker: marker::CovariantLifetime<'a>
+ marker: marker::PhantomData<fn(&'a ())>
}
fn use_<'short,'long>(c: Covariant<'long>,
use std::marker;
struct invariant<'a> {
- marker: marker::InvariantLifetime<'a>
+ marker: marker::PhantomData<*mut &'a()>
}
fn to_same_lifetime<'r>(b_isize: invariant<'r>) {
+++ /dev/null
-// Copyright 2015 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.
-
-fn f<T>() {}
-
-fn main() {
- false == false == false;
- //~^ ERROR: chained comparison operators require parentheses
-
- false == 0 < 2;
- //~^ ERROR: chained comparison operators require parentheses
-
- f<X>();
- //~^ ERROR: chained comparison operators require parentheses
- //~^^ HELP: use `::<...>` instead of `<...>`
-}
#![feature(lang_items, no_std)]
#![no_std]
-#[lang="sized"] pub trait Sized {}
+#[lang="phantom_fn"]
+pub trait PhantomFn<T:?Sized> { }
+impl<T:?Sized, U:?Sized> PhantomFn<T> for U { }
+
+#[lang="sized"] pub trait Sized : PhantomFn<Self> {}
// error-pattern:requires `start` lang_item
#![feature(box_syntax)]
-struct Foo<T>;
+struct Foo<T>(T);
impl<T> Foo<T> {
fn shadow_in_method<T>(&self) {}
//~^ ERROR type parameter `T` shadows another type parameter
fn not_shadow_in_item<U>(&self) {
- struct Bar<T, U>; // not a shadow, separate item
+ struct Bar<T, U>(T,U); // not a shadow, separate item
fn foo<T, U>() {} // same
}
}
trait Bar<T> {
+ fn dummy(&self) -> T;
+
fn shadow_in_required<T>(&self);
//~^ ERROR type parameter `T` shadows another type parameter
// except according to those terms.
// Test slicing &expr[] is deprecated and gives a helpful error message.
-//
-// ignore-test
struct Foo;
fn main() {
let x = Foo;
- &x[]; //~ WARNING deprecated slicing syntax: `[]`
- //~^ NOTE use `&expr[..]` to construct a slice of the whole of expr
- //~^^ ERROR cannot index a value of type `Foo`
+ &x[];
+ //~^ WARN obsolete syntax
+ //~| ERROR cannot index
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-struct Foo<T,U>(T);
+use std::marker;
+
+struct Foo<T,U>(T, marker::PhantomData<U>);
fn main() {
- match Foo(1.1) {
+ match Foo(1.1, marker::PhantomData) {
1 => {}
//~^ ERROR mismatched types
//~| expected `Foo<_, _>`
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
trait foo {
+ fn dummy(&self) { }
fn bar();
}
+++ /dev/null
-// Copyright 2013 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.
-
-struct Foo;
-
-fn f2() {
- let _end_stmt = Foo { };
- //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
+++ /dev/null
-// Copyright 2013 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.
-
-struct Foo;
-
-fn g3() {
- let _mid_tuple = (Foo { }, 2);
- //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
+++ /dev/null
-// Copyright 2013 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.
-
-struct Foo;
-
-fn h4() {
- let _end_of_tuple = (3, Foo { });
- //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
+++ /dev/null
-// Copyright 2013 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.
-
-struct Foo;
-
-fn i5() {
- let _end_of_block = { Foo { } };
- //~^ ERROR: structure literal must either have at least one field
-}
-
-fn main() {}
+++ /dev/null
-// 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.
-
-enum Foo {
- Bar {} //~ ERROR unit-like struct variant should be written without braces, as `Bar,`
-}
+++ /dev/null
-// 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.
-
-enum Foo {
- Bar {
- pub a: isize //~ ERROR: `pub` is not allowed here
- }
-}
-
-fn main() {}
+++ /dev/null
-// 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.
-
-#![feature(optin_builtin_traits)]
-
-use std::marker::Send;
-
-struct TestType;
-
-impl !TestType {}
-//~^ ERROR inherent implementation can't be negated
-
-trait TestTrait {}
-
-unsafe impl !Send for TestType {}
-impl !TestTrait for TestType {}
-
-struct TestType2<T>;
-
-impl<T> !TestType2<T> {}
-//~^ ERROR inherent implementation can't be negated
-
-unsafe impl<T> !Send for TestType2<T> {}
-impl<T> !TestTrait for TestType2<T> {}
-
-fn main() {}
+++ /dev/null
-// Copyright 2012 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.
-
-//error-pattern: discriminator values can only be used with a c-like enum
-
-enum color {
- red = 0xff0000,
- green = 0x00ff00,
- blue = 0x0000ff,
- black = 0x000000,
- white = 0xffffff,
- other (str),
-}
+++ /dev/null
-// 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.
-
-// ignore-tidy-cr
-// Issue #11669
-
-fn main() {
- // \r\n
- let ok = "This is \
- a test";
- // \r only
- let bad = "This is \\r a test";
- //~^ ERROR unknown character escape: \r
- //~^^ HELP this is an isolated carriage return
-
-}
+++ /dev/null
-// Copyright 2012 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.
-
-use std::fmt::Show;
-
-fn main() {
- let x: Box<Show+> = box 3 as Box<Show+>;
- //~^ ERROR at least one type parameter bound must be specified
- //~^^ ERROR at least one type parameter bound must be specified
-}
-
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait TraitNotAStruct { }
+trait TraitNotAStruct : ::std::marker::MarkerTrait { }
fn main() {
TraitNotAStruct{ value: 0 };
trait Foo {
+ fn dummy(&self) { }
}
fn a(_x: Box<Foo+Send>) {
// Make sure rustc checks the type parameter bounds in implementations of traits,
// see #2687
-trait A {}
+use std::marker;
+
+trait A : marker::PhantomFn<Self> {
+}
trait B: A {}
//~^ ERROR the requirement `T : C` appears on the impl
}
-
-trait Getter<T> { }
+trait Getter<T> {
+ fn get(&self) -> T { loop { } }
+}
trait Trait {
- fn method<G:Getter<isize>>();
+ fn method<G:Getter<isize>>(&self);
}
impl Trait for usize {
- fn method<G: Getter<usize>>() {}
+ fn method<G: Getter<usize>>(&self) {}
//~^ G : Getter<usize>` appears on the impl method but not on the corresponding trait method
}
fn next(&mut self) -> Option<A>;
}
-trait IteratorUtil<A> {
+trait IteratorUtil<A>
+ : ::std::marker::PhantomFn<(),A>
+{
fn zip<B, U: Iterator<U>>(self, other: U) -> ZipIterator<Self, U>;
}
// except according to those terms.
trait Foo {
+ fn dummy(&self) { }
}
// This should emit the less confusing error, not the more confusing one.
+++ /dev/null
-// Copyright 2013 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.
-
-trait Foo {
-}
-
-struct Bar;
-
-impl Foo + Owned for Bar { //~ ERROR not a trait
-}
-
-fn main() { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Trait {}
+trait Trait {
+ fn dummy(&self) { }
+}
struct Foo<T:Trait> {
x: T,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Trait {}
+trait Trait {
+ fn dummy(&self) { }
+}
struct Foo<T:Trait> {
x: T,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Trait {}
+use std::marker::MarkerTrait;
+
+trait Trait : MarkerTrait {}
struct Foo<T:Trait> {
x: T,
EvenMoreBadness(Bar<V>),
}
-trait PolyTrait<T> {
- fn whatever() {}
+trait PolyTrait<T>
+{
+ fn whatever(&self, t: T) {}
}
struct Struct;
impl PolyTrait<Foo<usize>> for Struct {
//~^ ERROR not implemented
- fn whatever() {}
}
fn main() {
// Tests for "default" bounds inferred for traits with no bounds list.
+use std::marker::MarkerTrait;
-trait Foo {}
+trait Foo : MarkerTrait {}
fn a(_x: Box<Foo+Send>) {
}
// trait impl is only applied to a trait object, not concrete types which implement
// the trait.
-trait T {}
+use std::marker::MarkerTrait;
+
+trait T : MarkerTrait {}
impl<'a> T+'a {
fn foo(&self) {}
trait Tr {
fn foo();
+ fn bar(&self) { }
}
struct St;
mod base {
pub trait HasNew<T> {
fn new() -> T;
+ fn dummy(&self) { }
}
pub struct Foo {
--- /dev/null
+// Copyright 2015 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.
+
+// Test a default that references `Self` which is then used in an
+// object type. Issue #18956. In this case, the value is supplied by
+// the user, but pretty-printing the type during the error message
+// caused an ICE.
+
+trait MyAdd<Rhs=Self> { fn add(&self, other: &Rhs) -> Self; }
+
+impl MyAdd for i32 {
+ fn add(&self, other: &i32) -> i32 { *self + *other }
+}
+
+fn main() {
+ let x = 5;
+ let y = x as MyAdd<i32>;
+ //~^ ERROR as `MyAdd<i32>`
+}
--- /dev/null
+// Copyright 2015 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.
+
+// Test a default that references `Self` which is then used in an object type.
+// Issue #18956.
+
+#![feature(default_type_params)]
+
+trait Foo<T=Self> {
+ fn method(&self);
+}
+
+fn foo(x: &Foo) { }
+//~^ ERROR the type parameter `T` must be explicitly specified
+
+fn main() { }
+++ /dev/null
-// 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.
-
-struct Foo {
- x: isize,
- y: isize,
-}
-
-fn main() {
- let f = Foo {
- x: 1,
- y: 2,
- };
- f.x::<isize>;
- //~^ ERROR field expressions may not have type parameters
-}
-
struct TestType;
-trait TestTrait {}
+trait TestTrait {
+ fn dummy(&self) { }
+}
impl !TestTrait for TestType {}
//~^ ERROR negative impls are currently allowed just for `Send` and `Sync`
// This test checks that genuine type errors with partial
// type hints are understandable.
-struct Foo<T>;
-struct Bar<U>;
+use std::marker::PhantomData;
+
+struct Foo<T>(PhantomData<T>);
+struct Bar<U>(PhantomData<U>);
pub fn main() {
}
fn test1() {
- let x: Foo<_> = Bar::<usize>;
+ let x: Foo<_> = Bar::<usize>(PhantomData);
//~^ ERROR mismatched types
//~| expected `Foo<_>`
//~| found `Bar<usize>`
}
fn test2() {
- let x: Foo<_> = Bar::<usize>;
+ let x: Foo<_> = Bar::<usize>(PhantomData);
//~^ ERROR mismatched types
//~| expected `Foo<_>`
//~| found `Bar<usize>`
fn main() {
<String as IntoCow>::into_cow("foo".to_string());
- //~^ ERROR wrong number of type arguments: expected 2, found 0
+ //~^ ERROR wrong number of type arguments: expected 1, found 0
}
-
// Check that parenthetical notation is feature-gated except with the
// `Fn` traits.
+use std::marker;
+
trait Foo<A> {
type Output;
+
+ fn dummy(&self, a: A) { }
}
fn main() {
fn dummy(&self, t: T, v: V);
}
-trait Eq<X: ?Sized> { }
+trait Eq<X: ?Sized> { fn same_types(&self, x: &X) -> bool { true } }
impl<X: ?Sized> Eq<X> for X { }
fn eq<A: ?Sized,B: ?Sized>() where A : Eq<B> { }
#![feature(unboxed_closures)]
#![allow(dead_code)]
+use std::marker::PhantomFn;
+
trait Foo<T> {
type Output;
fn dummy(&self, t: T, u: Self::Output);
}
-trait Eq<X: ?Sized> { }
+trait Eq<X: ?Sized> : PhantomFn<(Self,X)> { }
impl<X: ?Sized> Eq<X> for X { }
fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
#![feature(unboxed_closures)]
#![allow(dead_code)]
+use std::marker;
+
trait Foo<T> {
type Output;
fn dummy(&self, t: T);
}
-trait Eq<X: ?Sized> { }
+trait Eq<X: ?Sized> : marker::PhantomFn<(Self, X)> { }
impl<X: ?Sized> Eq<X> for X { }
fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
fn dummy(&'a self) -> &'a (T,Self::Output);
}
-trait Eq<X: ?Sized> { }
+trait Eq<X: ?Sized> { fn is_of_eq_type(&self, x: &X) -> bool { true } }
impl<X: ?Sized> Eq<X> for X { }
fn eq<A: ?Sized,B: ?Sized +Eq<A>>() { }
#![feature(core,unboxed_closures)]
-use std::marker::CovariantType;
+use std::marker::PhantomData;
// A erroneous variant of `run-pass/unboxed_closures-infer-recursive-fn.rs`
// where we attempt to perform mutation in the recursive function. This fails to compile
struct YCombinator<F,A,R> {
func: F,
- marker: CovariantType<(A,R)>,
+ marker: PhantomData<(A,R)>,
}
impl<F,A,R> YCombinator<F,A,R> {
fn new(f: F) -> YCombinator<F,A,R> {
- YCombinator { func: f, marker: CovariantType }
+ YCombinator { func: f, marker: PhantomData }
}
}
pub struct A; //~ ERROR: visibility has no effect
pub enum B {} //~ ERROR: visibility has no effect
pub trait C { //~ ERROR: visibility has no effect
- pub fn foo() {} //~ ERROR: visibility has no effect
+ pub fn foo(&self) {} //~ ERROR: visibility has no effect
}
impl A {
- pub fn foo() {} //~ ERROR: visibility has no effect
+ pub fn foo(&self) {} //~ ERROR: visibility has no effect
}
struct D {
// impl - struct
-struct S5<Y>;
+struct S5<Y>(Y);
impl<X: ?Sized> S5<X> { //~ ERROR not implemented
}
// impl - struct
trait T3<Z: ?Sized> {
+ fn foo(&self, z: &Z);
}
-struct S5<Y>;
+struct S5<Y>(Y);
impl<X: ?Sized> T3<X> for S5<X> { //~ ERROR not implemented
}
// impl - unbounded
trait T2<Z> {
+ fn foo(&self, z: Z);
}
-struct S4<Y: ?Sized>;
+struct S4<Y: ?Sized>(Box<Y>);
impl<X: ?Sized> T2<X> for S4<X> {
//~^ ERROR `core::marker::Sized` is not implemented for the type `X`
}
+++ /dev/null
-// 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.
-
-// Test syntax checks for `type` keyword.
-
-fn f<X>() {}
-
-pub fn main() {
- f<type>();
- //~^ ERROR expected identifier, found keyword `type`
- //~^^ ERROR: chained comparison
- //~^^^ HELP: use `::<
-}
// Test sized-ness checking in substitution within fn bodies..
+use std::marker;
// Unbounded.
fn f1<X: ?Sized>(x: &X) {
}
// Bounded.
-trait T {}
+trait T {
+ fn foo(&self) { }
+}
fn f3<X: ?Sized + T>(x: &X) {
f4::<X>(x);
//~^ ERROR the trait `core::marker::Sized` is not implemented
// Test `?Sized` local variables.
+use std::marker;
-trait T {}
+trait T : marker::MarkerTrait { }
fn f1<X: ?Sized>(x: &X) {
let _: X; // <-- this is OK, no bindings created, no initializer.
// Test sized-ness checking in substitution in impls.
-trait T {}
+use std::marker::MarkerTrait;
+
+trait T : MarkerTrait {}
// I would like these to fail eventually.
// impl - bounded
trait T1<Z: T> {
+ fn dummy(&self) -> Z;
}
-struct S3<Y: ?Sized>;
+
+struct S3<Y: ?Sized>(Box<Y>);
impl<X: ?Sized + T> T1<X> for S3<X> {
//~^ ERROR `core::marker::Sized` is not implemented for the type `X`
}
#[foo] //~ ERROR unused attribute
trait Baz {
#[foo] //~ ERROR unused attribute
- fn blah();
+ fn blah(&self);
#[foo] //~ ERROR unused attribute
- fn blah2() {}
+ fn blah2(&self) {}
}
fn main() {}
pub enum C { pub Variant } //~ ERROR: unnecessary `pub`
pub trait E {
- pub fn foo() {} //~ ERROR: unnecessary visibility
+ pub fn foo(&self) {} //~ ERROR: unnecessary visibility
+}
+trait F {
+ pub fn foo(&self) {} //~ ERROR: unnecessary visibility
}
-trait F { pub fn foo() {} } //~ ERROR: unnecessary visibility
impl E for A {
- pub fn foo() {} //~ ERROR: unnecessary visibility
+ pub fn foo(&self) {} //~ ERROR: unnecessary visibility
}
fn main() {}
// except according to those terms.
pub trait E {
- pub fn foo(); //~ ERROR: unnecessary visibility
+ pub fn foo(&self); //~ ERROR: unnecessary visibility
+}
+trait F {
+ pub fn foo(&self); //~ ERROR: unnecessary visibility
}
-trait F { pub fn foo(); } //~ ERROR: unnecessary visibility
fn main() {}
--- /dev/null
+// Copyright 2015 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.
+
+#![allow(dead_code)]
+
+trait Get<T> : 'static {
+ fn get(&self, t: T);
+}
+
+fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+ -> Box<Get<&'min i32>>
+ where 'max : 'min
+{
+ v //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+ -> Box<Get<&'max i32>>
+ where 'max : 'min
+{
+ v
+}
+
+fn main() { }
--- /dev/null
+// Copyright 2015 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.
+
+#![allow(dead_code)]
+
+trait Get<T> {
+ fn get(&self, t: T);
+}
+
+fn get_min_from_max<'min, 'max, G>()
+ where 'max : 'min, G : Get<&'max i32>
+{
+ impls_get::<G,&'min i32>() //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>()
+ where 'max : 'min, G : Get<&'min i32>
+{
+ impls_get::<G,&'max i32>()
+}
+
+fn impls_get<G,T>() where G : Get<T> { }
+
+fn main() { }
--- /dev/null
+// Copyright 2015 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.
+
+#![allow(dead_code)]
+
+trait Get {
+ fn get(&self);
+}
+
+fn get_min_from_max<'min, 'max, G>()
+ where 'max : 'min, G : 'max, &'max G : Get
+{
+ impls_get::<&'min G>(); //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>()
+ where 'max : 'min, G : 'max, &'min G : Get
+{
+ impls_get::<&'max G>();
+}
+
+fn impls_get<G>() where G : Get { }
+
+fn main() { }
--- /dev/null
+// Copyright 2015 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.
+
+#![allow(dead_code)]
+
+trait Get<T> : 'static {
+ fn get(&self) -> T;
+}
+
+fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+ -> Box<Get<&'min i32>>
+ where 'max : 'min
+{
+ v
+}
+
+fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+ -> Box<Get<&'max i32>>
+ where 'max : 'min
+{
+ v //~ ERROR mismatched types
+}
+
+fn main() { }
--- /dev/null
+// Copyright 2015 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.
+
+#![allow(dead_code)]
+
+trait Get<T> {
+ fn get(&self) -> T;
+}
+
+fn get_min_from_max<'min, 'max, G>()
+ where 'max : 'min, G : Get<&'max i32>
+{
+ impls_get::<G,&'min i32>()
+}
+
+fn get_max_from_min<'min, 'max, G>()
+ where 'max : 'min, G : Get<&'min i32>
+{
+ impls_get::<G,&'max i32>() //~ ERROR mismatched types
+}
+
+fn impls_get<G,T>() where G : Get<T> { }
+
+fn main() { }
--- /dev/null
+// Copyright 2015 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.
+
+#![allow(dead_code)]
+
+trait Get {
+ fn get() -> Self;
+}
+
+fn get_min_from_max<'min, 'max, G>()
+ where 'max : 'min, G : 'max, &'max G : Get
+{
+ impls_get::<&'min G>();
+}
+
+fn get_max_from_min<'min, 'max, G>()
+ where 'max : 'min, G : 'max, &'min G : Get
+{
+ impls_get::<&'max G>(); //~ ERROR mismatched types
+}
+
+fn impls_get<G>() where G : Get { }
+
+fn main() { }
--- /dev/null
+// Copyright 2015 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.
+
+// Test that the deprecated markers still have their old effect.
+
+#![feature(rustc_attrs)]
+
+use std::marker;
+
+#[rustc_variance]
+struct A<T>(marker::CovariantType<T>); //~ ERROR types=[[+];[];[]]
+
+#[rustc_variance]
+struct B<T>(marker::ContravariantType<T>); //~ ERROR types=[[-];[];[]]
+
+#[rustc_variance]
+struct C<T>(marker::InvariantType<T>); //~ ERROR types=[[o];[];[]]
+
+#[rustc_variance]
+struct D<'a>(marker::CovariantLifetime<'a>); //~ ERROR regions=[[+];[];[]]
+
+#[rustc_variance]
+struct E<'a>(marker::ContravariantLifetime<'a>); //~ ERROR regions=[[-];[];[]]
+
+#[rustc_variance]
+struct F<'a>(marker::InvariantLifetime<'a>); //~ ERROR regions=[[o];[];[]]
+
+fn main() { }
--- /dev/null
+// Copyright 2015 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.
+
+#![allow(dead_code)]
+
+trait Get<T> : 'static {
+ fn get(&self, t: T) -> T;
+}
+
+fn get_min_from_max<'min, 'max>(v: Box<Get<&'max i32>>)
+ -> Box<Get<&'min i32>>
+ where 'max : 'min
+{
+ v //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>(v: Box<Get<&'min i32>>)
+ -> Box<Get<&'max i32>>
+ where 'max : 'min
+{
+ v //~ ERROR mismatched types
+}
+
+fn main() { }
--- /dev/null
+// Copyright 2015 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.
+
+#![allow(dead_code)]
+
+trait Get<T> {
+ fn get(&self, t: T) -> T;
+}
+
+fn get_min_from_max<'min, 'max, G>()
+ where 'max : 'min, G : Get<&'max i32>
+{
+ impls_get::<G,&'min i32>() //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>()
+ where 'max : 'min, G : Get<&'min i32>
+{
+ impls_get::<G,&'max i32>() //~ ERROR mismatched types
+}
+
+fn impls_get<G,T>() where G : Get<T> { }
+
+fn main() { }
--- /dev/null
+// Copyright 2015 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.
+
+#![allow(dead_code)]
+
+trait Get {
+ fn get(&self) -> Self;
+}
+
+fn get_min_from_max<'min, 'max, G>()
+ where 'max : 'min, &'max G : Get
+{
+ impls_get::<&'min G>(); //~ ERROR mismatched types
+}
+
+fn get_max_from_min<'min, 'max, G>()
+ where 'max : 'min, &'min G : Get
+{
+ impls_get::<&'max G>(); //~ ERROR mismatched types
+}
+
+fn impls_get<G>() where G : Get { }
+
+fn main() { }
--- /dev/null
+// Copyright 2015 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.
+
+// Regression test for issue #20533. At some point, only 1 out of the
+// 3 errors below were being reported.
+
+use std::marker::PhantomData;
+
+fn foo<'a, T>(_x: &'a T) -> PhantomData<&'a ()> {
+ PhantomData
+}
+
+struct Wrap<T>(T);
+
+fn bar<'a, T>(_x: &'a T) -> Wrap<PhantomData<&'a ()>> {
+ Wrap(PhantomData)
+}
+
+struct Baked<'a>(PhantomData<&'a ()>);
+
+fn baz<'a, T>(_x: &'a T) -> Baked<'a> {
+ Baked(PhantomData)
+}
+
+struct AffineU32(u32);
+
+fn main() {
+ {
+ let a = AffineU32(1_u32);
+ let x = foo(&a);
+ drop(a); //~ ERROR cannot move out of `a`
+ drop(x);
+ }
+ {
+ let a = AffineU32(1_u32);
+ let x = bar(&a);
+ drop(a); //~ ERROR cannot move out of `a`
+ drop(x);
+ }
+ {
+ let a = AffineU32(1_u32);
+ let x = baz(&a);
+ drop(a); //~ ERROR cannot move out of `a`
+ drop(x);
+ }
+}
+
#[rustc_variance]
struct Test7<'a> { //~ ERROR regions=[[*];[];[]]
+ //~^ ERROR parameter `'a` is never used
x: isize
}
#[rustc_variance]
enum Base<'a, 'b, 'c:'b, 'd> { //~ ERROR regions=[[+, -, o, *];[];[]]
+ //~^ ERROR parameter `'d` is never used
Test8A(extern "Rust" fn(&'a isize)),
Test8B(&'b [isize]),
Test8C(&'b mut &'c str),
#[rustc_variance]
struct Derived1<'w, 'x:'y, 'y, 'z> { //~ ERROR regions=[[*, o, -, +];[];[]]
+ //~^ ERROR parameter `'w` is never used
f: Base<'z, 'y, 'x, 'w>
}
#[rustc_variance] // Combine - and + to yield o
struct Derived2<'a, 'b:'a, 'c> { //~ ERROR regions=[[o, o, *];[];[]]
+ //~^ ERROR parameter `'c` is never used
f: Base<'a, 'a, 'b, 'c>
}
#[rustc_variance] // Combine + and o to yield o (just pay attention to 'a here)
struct Derived3<'a:'b, 'b, 'c> { //~ ERROR regions=[[o, -, *];[];[]]
+ //~^ ERROR parameter `'c` is never used
f: Base<'a, 'b, 'a, 'c>
}
--- /dev/null
+// Copyright 2012 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.
+
+// Test that disallow lifetime parameters that are unused.
+
+use std::marker;
+
+struct Bivariant<'a>; //~ ERROR parameter `'a` is never used
+
+struct Struct<'a, 'd> { //~ ERROR parameter `'d` is never used
+ field: &'a [i32]
+}
+
+trait Trait<'a, 'd> { //~ ERROR parameter `'d` is never used
+ fn method(&'a self);
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2012 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.
+
+// Test that disallow lifetime parameters that are unused.
+
+enum Foo<'a> { //~ ERROR parameter `'a` is never used
+ Foo1(Bar<'a>)
+}
+
+enum Bar<'a> { //~ ERROR parameter `'a` is never used
+ Bar1(Foo<'a>)
+}
+
+fn main() {}
--- /dev/null
+// 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.
+
+#![deny(bivariance)]
+#![allow(dead_code)]
+#![feature(rustc_attrs)]
+
+// Check that bounds on type parameters (other than `Self`) do not
+// influence variance.
+
+#[rustc_variance]
+trait Getter<T> { //~ ERROR types=[[+];[-];[]]
+ fn get(&self) -> T;
+}
+
+#[rustc_variance]
+trait Setter<T> { //~ ERROR types=[[-];[-];[]]
+ fn get(&self, T);
+}
+
+#[rustc_variance]
+struct TestStruct<U,T:Setter<U>> { //~ ERROR types=[[+, +];[];[]]
+ t: T, u: U
+}
+
+#[rustc_variance]
+enum TestEnum<U,T:Setter<U>> {//~ ERROR types=[[*, +];[];[]]
+ //~^ ERROR parameter `U` is never used
+ Foo(T)
+}
+
+#[rustc_variance]
+trait TestTrait<U,T:Setter<U>> { //~ ERROR types=[[-, +];[-];[]]
+ fn getter(&self, u: U) -> T;
+}
+
+#[rustc_variance]
+trait TestTrait2<U> : Getter<U> { //~ ERROR types=[[+];[-];[]]
+}
+
+#[rustc_variance]
+trait TestTrait3<U> { //~ ERROR types=[[-];[-];[]]
+ fn getter<T:Getter<U>>(&self);
+}
+
+#[rustc_variance]
+struct TestContraStruct<U,T:Setter<U>> { //~ ERROR types=[[*, +];[];[]]
+ //~^ ERROR parameter `U` is never used
+ t: T
+}
+
+#[rustc_variance]
+struct TestBox<U,T:Getter<U>+Setter<U>> { //~ ERROR types=[[*, +];[];[]]
+ //~^ ERROR parameter `U` is never used
+ t: T
+}
+
+pub fn main() { }
use std::mem;
-trait T { fn foo(); }
+trait T { fn foo(&self); }
#[rustc_variance]
struct TOption<'a> { //~ ERROR regions=[[-];[];[]]
--- /dev/null
+// Copyright 2012 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.
+
+// Test that we correctly infer variance for type parameters in
+// various types and traits.
+
+#![feature(rustc_attrs)]
+
+#[rustc_variance]
+struct TestImm<A, B> { //~ ERROR types=[[+, +];[];[]]
+ x: A,
+ y: B,
+}
+
+#[rustc_variance]
+struct TestMut<A, B:'static> { //~ ERROR types=[[+, o];[];[]]
+ x: A,
+ y: &'static mut B,
+}
+
+#[rustc_variance]
+struct TestIndirect<A:'static, B:'static> { //~ ERROR types=[[+, o];[];[]]
+ m: TestMut<A, B>
+}
+
+#[rustc_variance]
+struct TestIndirect2<A:'static, B:'static> { //~ ERROR types=[[o, o];[];[]]
+ n: TestMut<A, B>,
+ m: TestMut<B, A>
+}
+
+#[rustc_variance]
+trait Getter<A> { //~ ERROR types=[[+];[-];[]]
+ fn get(&self) -> A;
+}
+
+#[rustc_variance]
+trait Setter<A> { //~ ERROR types=[[-];[o];[]]
+ fn set(&mut self, a: A);
+}
+
+#[rustc_variance]
+trait GetterSetter<A> { //~ ERROR types=[[o];[o];[]]
+ fn get(&self) -> A;
+ fn set(&mut self, a: A);
+}
+
+#[rustc_variance]
+trait GetterInTypeBound<A> { //~ ERROR types=[[-];[-];[]]
+ // Here, the use of `A` in the method bound *does* affect
+ // variance. Think of it as if the method requested a dictionary
+ // for `T:Getter<A>`. Since this dictionary is an input, it is
+ // contravariant, and the Getter is covariant w/r/t A, yielding an
+ // overall contravariant result.
+ fn do_it<T:Getter<A>>(&self);
+}
+
+#[rustc_variance]
+trait SetterInTypeBound<A> { //~ ERROR types=[[+];[-];[]]
+ fn do_it<T:Setter<A>>(&self);
+}
+
+#[rustc_variance]
+struct TestObject<A, R> { //~ ERROR types=[[-, +];[];[]]
+ n: Box<Setter<A>+Send>,
+ m: Box<Getter<R>+Send>,
+}
+
+fn main() {}
--- /dev/null
+// 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.
+
+#![deny(bivariance)]
+#![allow(dead_code)]
+#![feature(rustc_attrs)]
+
+use std::cell::Cell;
+
+// Check that a type parameter which is only used in a trait bound is
+// not considered bivariant.
+
+#[rustc_variance]
+struct InvariantMut<'a,A:'a,B:'a> { //~ ERROR types=[[o, o];[];[]], regions=[[-];[];[]]
+ t: &'a mut (A,B)
+}
+
+#[rustc_variance]
+struct InvariantCell<A> { //~ ERROR types=[[o];[];[]]
+ t: Cell<A>
+}
+
+#[rustc_variance]
+struct InvariantIndirect<A> { //~ ERROR types=[[o];[];[]]
+ t: InvariantCell<A>
+}
+
+#[rustc_variance]
+struct Covariant<A> { //~ ERROR types=[[+];[];[]]
+ t: A, u: fn() -> A
+}
+
+#[rustc_variance]
+struct Contravariant<A> { //~ ERROR types=[[-];[];[]]
+ t: fn(A)
+}
+
+#[rustc_variance]
+enum Enum<A,B,C> { //~ ERROR types=[[+, -, o];[];[]]
+ Foo(Covariant<A>),
+ Bar(Contravariant<B>),
+ Zed(Covariant<C>,Contravariant<C>)
+}
+
+pub fn main() { }
--- /dev/null
+// Copyright 2012 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.
+
+// Test that we report an error for unused type parameters in types.
+
+struct SomeStruct<'a> { x: u32 } //~ ERROR parameter `'a` is never used
+enum SomeEnum<'a> { Nothing } //~ ERROR parameter `'a` is never used
+trait SomeTrait<'a> { fn foo(&self); } //~ ERROR parameter `'a` is never used
+
+fn main() {}
--- /dev/null
+// Copyright 2012 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.
+
+#![allow(dead_code)]
+
+// Test that we report an error for unused type parameters in types and traits,
+// and that we offer a helpful suggestion.
+
+struct SomeStruct<A> { x: u32 }
+//~^ ERROR parameter `A` is never used
+//~| HELP PhantomData
+
+enum SomeEnum<A> { Nothing }
+//~^ ERROR parameter `A` is never used
+//~| HELP PhantomData
+
+trait SomeTrait<A> { fn foo(&self); }
+//~^ ERROR parameter `A` is never used
+//~| HELP PhantomFn
+
+// Here T might *appear* used, but in fact it isn't.
+enum ListCell<T> {
+//~^ ERROR parameter `T` is never used
+//~| HELP PhantomData
+ Cons(Box<ListCell<T>>),
+ Nil
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2015 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.
+
+// Test various uses of structs with distint variances to make sure
+// they permit lifetimes to be approximated as expected.
+
+#![feature(rustc_attrs)]
+
+struct SomeStruct<T>(fn(T));
+
+fn foo<'min,'max>(v: SomeStruct<&'max ()>)
+ -> SomeStruct<&'min ()>
+ where 'max : 'min
+{
+ v //~ ERROR mismatched types
+}
+
+#[rustc_error]
+fn main() { }
--- /dev/null
+// Copyright 2015 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.
+
+// Test various uses of structs with distint variances to make sure
+// they permit lifetimes to be approximated as expected.
+
+#![allow(dead_code)]
+#![feature(rustc_attrs)]
+
+struct SomeStruct<T>(fn(T));
+
+fn bar<'min,'max>(v: SomeStruct<&'min ()>)
+ -> SomeStruct<&'max ()>
+ where 'max : 'min
+{
+ v
+}
+
+#[rustc_error]
+fn main() { } //~ ERROR compilation successful
--- /dev/null
+// Copyright 2015 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.
+
+// Test that a covariant struct does not permit the lifetime of a
+// reference to be enlarged.
+
+struct SomeStruct<T>(T);
+
+fn foo<'min,'max>(v: SomeStruct<&'min ()>)
+ -> SomeStruct<&'max ()>
+ where 'max : 'min
+{
+ v //~ ERROR mismatched types
+}
+
+fn main() { }
--- /dev/null
+// Copyright 2015 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.
+
+// Test that a covariant struct permits the lifetime of a reference to
+// be shortened.
+
+#![allow(dead_code)]
+#![feature(rustc_attrs)]
+
+struct SomeStruct<T>(T);
+
+fn foo<'min,'max>(v: SomeStruct<&'max ()>)
+ -> SomeStruct<&'min ()>
+ where 'max : 'min
+{
+ v
+}
+
+#[rustc_error] fn main() { } //~ ERROR compilation successful
--- /dev/null
+// Copyright 2015 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.
+
+// Test various uses of structs with distint variances to make sure
+// they permit lifetimes to be approximated as expected.
+
+#![feature(rustc_attrs)]
+
+struct SomeStruct<T>(*mut T);
+
+fn foo<'min,'max>(v: SomeStruct<&'max ()>)
+ -> SomeStruct<&'min ()>
+ where 'max : 'min
+{
+ v //~ ERROR mismatched types
+}
+
+fn bar<'min,'max>(v: SomeStruct<&'min ()>)
+ -> SomeStruct<&'max ()>
+ where 'max : 'min
+{
+ v //~ ERROR mismatched types
+}
+
+#[rustc_error]
+fn main() { }
+++ /dev/null
-// 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.
-
-// Test diagnostics for the removed struct inheritance feature.
-#![feature(struct_inherit)]
-
-virtual struct SuperStruct { //~ ERROR `virtual` structs have been removed from the language
- f1: isize,
-}
-
-struct Struct : SuperStruct; //~ ERROR `virtual` structs have been removed from the language
-
-pub fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Foo {}
+trait Foo {
+ fn dummy(&self) { }
+}
pub fn f<
T
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Foo {}
+trait Foo {
+ fn dummy(&self) { }
+}
pub trait Bar : Foo {} //~ ERROR private trait in exported type
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Foo<T> {}
+trait Foo<T> {
+ fn dummy(&self, t: T) { }
+}
trait Bar<A> {
fn method<B>(&self) where A: Foo<B>;
+++ /dev/null
-// 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.
-
-fn equal1<T>(_: &T, _: &T) -> bool where {
-//~^ ERROR a `where` clause must have at least one predicate in it
- true
-}
-
-fn equal2<T>(_: &T, _: &T) -> bool where T: {
-//~^ ERROR each predicate in a `where` clause must have at least one bound
- true
-}
-
-fn main() {
-}
-
#[derive(PartialEq)]
//~^ ERROR cannot bound type `isize`, where clause bounds
-enum Foo<T> where isize : Eq { MkFoo }
+enum Foo<T> where isize : Eq { MkFoo(T) }
//~^ ERROR cannot bound type `isize`, where clause bounds
fn test3<T: Eq>() -> bool where Option<Foo<T>> : Eq {}
trait Baz<T> where isize : Eq {
//~^ ERROR cannot bound type `isize`, where clause bounds may only
- fn baz() where String : Eq; //~ ERROR cannot bound type `collections::string::String`
+ fn baz(&self, t: T) where String : Eq; //~ ERROR cannot bound type `collections::string::String`
//~^ ERROR cannot bound type `isize`, where clause
}
#![omit_gdb_pretty_printer_section]
use self::Enum1::{Variant1_1, Variant1_2};
+use std::marker::PhantomData;
use std::ptr;
struct Struct1;
-struct GenericStruct<T1, T2>;
+struct GenericStruct<T1, T2>(PhantomData<(T1,T2)>);
enum Enum1 {
Variant1_1,
}
}
-trait Trait1 { }
-trait Trait2<T1, T2> { }
+trait Trait1 { fn dummy(&self) { } }
+trait Trait2<T1, T2> { fn dummy(&self, _: T1, _:T2) { } }
impl Trait1 for isize {}
impl<T1, T2> Trait2<T1, T2> for isize {}
// Structs
let simple_struct = Struct1;
- let generic_struct1: GenericStruct<Mod1::Struct2, Mod1::Mod2::Struct3> = GenericStruct;
- let generic_struct2: GenericStruct<Struct1, extern "fastcall" fn(isize) -> usize> = GenericStruct;
+ let generic_struct1: GenericStruct<Mod1::Struct2, Mod1::Mod2::Struct3> =
+ GenericStruct(PhantomData);
+ let generic_struct2: GenericStruct<Struct1, extern "fastcall" fn(isize) -> usize> =
+ GenericStruct(PhantomData);
let mod_struct = Mod1::Struct2;
// Enums
// References
let ref1 = (&Struct1, 0i32);
- let ref2 = (&GenericStruct::<char, Struct1>, 0i32);
+ let ref2 = (&GenericStruct::<char, Struct1>(PhantomData), 0i32);
let mut mut_struct1 = Struct1;
- let mut mut_generic_struct = GenericStruct::<Mod1::Enum2, f64>;
+ let mut mut_generic_struct = GenericStruct::<Mod1::Enum2, f64>(PhantomData);
let mut_ref1 = (&mut mut_struct1, 0i32);
let mut_ref2 = (&mut mut_generic_struct, 0i32);
--- /dev/null
+// 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.
+
+fn main() {
+ let x = "\x80"; //~ ERROR may only be used
+ let y = "\xff"; //~ ERROR may only be used
+ let z = "\xe2"; //~ ERROR may only be used
+ let a = b"\x00e2"; // ok because byte literal
+}
+
--- /dev/null
+// Copyright 2012 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.
+
+#[derive(Debug)] //~ERROR expected item after attributes
--- /dev/null
+// Copyright 2012 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.
+
+fn main() {
+ #[attr] //~ ERROR expected item after attributes
+ println!("hi");
+}
--- /dev/null
+// Copyright 2012 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.
+
+fn main() {
+ #[attr] //~ ERROR expected item
+ let __isize = 0;
+}
--- /dev/null
+// Copyright 2012 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.
+
+// error-pattern:expected item
+
+fn f() {
+ #[foo = "bar"]
+ let x = 10;
+}
+
+fn main() {
+}
--- /dev/null
+// Copyright 2012 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.
+
+// error-pattern:expected item
+
+fn f() {
+ #[foo = "bar"]
+}
+
+fn main() {
+}
--- /dev/null
+// Copyright 2012 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.
+
+// error-pattern:expected item
+
+fn main() {
+}
+
+#[foo = "bar"]
--- /dev/null
+// 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.
+
+#![feature(lang_items)]
+
+fn main() {}
+
+#![lang(foo)] //~ ERROR an inner attribute is not permitted in this context
+fn foo() {}
--- /dev/null
+// Copyright 2013 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.
+
+// Constants (static variables) can be used to match in patterns, but mutable
+// statics cannot. This ensures that there's some form of error if this is
+// attempted.
+
+extern crate libc;
+
+extern {
+ static mut rust_dbg_static_mut: libc::c_int;
+ pub fn rust_dbg_static_mut_check_four();
+ #[cfg(stage37)] //~ ERROR expected item after attributes
+}
+
+pub fn main() {}
--- /dev/null
+// Copyright 2013 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.
+
+// ignore-tidy-cr
+// ignore-tidy-tab
+fn main() {
+ // these literals are just silly.
+ ''';
+ //~^ ERROR: character constant must be escaped: \'
+
+ // note that this is a literal "\n" byte
+ '
+';
+ //~^^ ERROR: character constant must be escaped: \n
+
+ // note that this is a literal "\r" byte
+ '\r'; //~ ERROR: character constant must be escaped: \r
+
+ // note that this is a literal tab character here
+ ' ';
+ //~^ ERROR: character constant must be escaped: \t
+}
--- /dev/null
+// 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.
+
+
+extern crate
+ "foo"suffix //~ ERROR extern crate name with a suffix is illegal
+ as foo;
+
+extern
+ "C"suffix //~ ERROR ABI spec with a suffix is illegal
+ fn foo() {}
+
+extern
+ "C"suffix //~ ERROR ABI spec with a suffix is illegal
+{}
+
+fn main() {
+ ""suffix; //~ ERROR str literal with a suffix is illegal
+ b""suffix; //~ ERROR binary str literal with a suffix is illegal
+ r#""#suffix; //~ ERROR str literal with a suffix is illegal
+ br#""#suffix; //~ ERROR binary str literal with a suffix is illegal
+ 'a'suffix; //~ ERROR char literal with a suffix is illegal
+ b'a'suffix; //~ ERROR byte literal with a suffix is illegal
+
+ 1234u1024; //~ ERROR illegal width `1024` for integer literal
+ 1234i1024; //~ ERROR illegal width `1024` for integer literal
+ 1234f1024; //~ ERROR illegal width `1024` for float literal
+ 1234.5f1024; //~ ERROR illegal width `1024` for float literal
+
+ 1234suffix; //~ ERROR illegal suffix `suffix` for numeric literal
+ 0b101suffix; //~ ERROR illegal suffix `suffix` for numeric literal
+ 1.0suffix; //~ ERROR illegal suffix `suffix` for float literal
+ 1.0e10suffix; //~ ERROR illegal suffix `suffix` for float literal
+}
--- /dev/null
+// Copyright 2012 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.
+
+fn false() { } //~ ERROR expected identifier, found keyword `false`
+fn main() { }
--- /dev/null
+// Copyright 2012 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.
+
+fn true() { } //~ ERROR expected identifier, found keyword `true`
+fn main() { }
--- /dev/null
+// Copyright 2012 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.
+
+/// hi
+#[derive(Debug)] //~ERROR expected item after attributes
--- /dev/null
+// Copyright 2012 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.
+
+/// hi //~ERROR expected item after doc comment
--- /dev/null
+// Copyright 2012 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.
+
+extern {
+ /// hi
+}
+//~^^ ERROR expected item after doc comment
--- /dev/null
+// Copyright 2012 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.
+
+fn main() {
+ /// hi
+ println!("hi");
+ //~^^ ERROR expected item after doc comment
+}
--- /dev/null
+// Copyright 2012 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.
+
+fn main() {
+ println!("Hi"); /// hi
+ //~^ ERROR expected item after doc comment
+}
--- /dev/null
+// Copyright 2012 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.
+
+fn main() {
+ /// hi
+ ;
+ //~^^ ERROR expected item after doc comment
+}
--- /dev/null
+// 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.
+
+// Tests that the proper help is displayed in the error message
+
+extern crate foo as bar;
+//~^ ERROR expected `;`, found `as`
+//~^^ HELP perhaps you meant to enclose the crate name `foo` in a string?
--- /dev/null
+// 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.
+
+struct Heap;
+
+struct Vec<A = Heap, T>; //~ ERROR type parameters with a default must be trailing
+
+struct Foo<A, B = Vec<C>, C>; //~ ERROR type parameters with a default must be trailing
+
+fn main() {}
--- /dev/null
+// 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.
+
+// issue #17123
+
+fn main() {
+ 100000000000000000000000000000000 //~ ERROR int literal is too large
+
+ ; // the span shouldn't point to this.
+}
--- /dev/null
+// Copyright 2013 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.
+
+
+trait Serializable<'self, T> { //~ ERROR no longer a special lifetime
+ fn serialize(val : &'self T) -> Vec<u8> ; //~ ERROR no longer a special lifetime
+ fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR no longer a special lifetime
+}
+
+impl<'self> Serializable<str> for &'self str { //~ ERROR no longer a special lifetime
+ //~^ ERROR no longer a special lifetime
+ fn serialize(val : &'self str) -> Vec<u8> { //~ ERROR no longer a special lifetime
+ vec!(1)
+ }
+ fn deserialize(repr: &[u8]) -> &'self str { //~ ERROR no longer a special lifetime
+ "hi"
+ }
+}
+
+fn main() {
+ println!("hello");
+ let x = "foo".to_string();
+ let y = x;
+ println!("{}", y);
+}
--- /dev/null
+// 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.
+
+// For style and consistency reasons, non-parametrized enum variants must
+// be used simply as `ident` instead of `ident ()`.
+// This test-case covers enum declaration.
+
+enum Foo {
+ Bar(), //~ ERROR nullary enum variants are written with no trailing `( )`
+ Baz(), //~ ERROR nullary enum variants are written with no trailing `( )`
+ Bazar
+}
+
+fn main() {
+ println!("{}", match Bar { Bar => 1, Baz => 2, Bazar => 3 })
+}
--- /dev/null
+// 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.
+
+// ignore-test FIXME(japari) remove test
+
+struct Foo {
+ f: for <'b> |&'b isize|:
+ 'b -> &'b isize //~ ERROR use of undeclared lifetime name `'b`
+}
+
+fn main() {
+ let mut x: Vec< for <'a> ||
+ :'a //~ ERROR use of undeclared lifetime name `'a`
+ > = Vec::new();
+ x.push(|| {});
+
+ let foo = Foo {
+ f: |x| x
+ };
+}
--- /dev/null
+// 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.
+
+enum X {
+ A =
+ b'a' //~ ERROR discriminator values can only be used with a c-like enum
+ ,
+ B(isize)
+}
+
+fn main() {}
--- /dev/null
+// 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.
+
+const
+mut //~ ERROR: const globals cannot be mutable
+//~^ HELP did you mean to declare a static?
+FOO: usize = 3;
+
+fn main() {
+}
+
--- /dev/null
+// Copyright 2012 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.
+
+// error-pattern:no valid digits found for number
+fn main() {
+ log(error, 0b_usize);
+}
--- /dev/null
+// Copyright 2013 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.
+
+fn main() {
+ let __isize = 18446744073709551616; // 2^64
+ //~^ ERROR int literal is too large
+}
--- /dev/null
+// Copyright 2013 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.
+
+fn main() {
+ let __isize = 0xff_ffff_ffff_ffff_ffff__isize;
+ //~^ ERROR int literal is too large
+}
--- /dev/null
+// 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.
+
+pub extern
+ "invalid-ab_isize" //~ ERROR illegal ABI
+fn foo() {}
+
+fn main() {}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py as'
+
+fn main() {
+ let as = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py break'
+
+fn main() {
+ let break = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py else'
+
+fn main() {
+ let else = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py enum'
+
+fn main() {
+ let enum = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py extern'
+
+fn main() {
+ let extern = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py fn'
+
+fn main() {
+ let fn = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py for'
+
+fn main() {
+ let for = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py if'
+
+fn main() {
+ let if = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py impl'
+
+fn main() {
+ let impl = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py let'
+
+fn main() {
+ let let = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py loop'
+
+fn main() {
+ let loop = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py match'
+
+fn main() {
+ let match = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py mod'
+
+fn main() {
+ let mod = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py pub'
+
+fn main() {
+ let pub = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py return'
+
+fn main() {
+ let return = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py self'
+
+fn main() {
+ let self = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py static'
+
+fn main() {
+ let static = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py struct'
+
+fn main() {
+ let struct = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py super'
+
+fn main() {
+ let super = "foo"; //~ error: ident
+}
--- /dev/null
+// 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.
+
+fn main() {
+ let super: isize; //~ ERROR expected identifier, found keyword `super`
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py trait'
+
+fn main() {
+ let trait = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py type'
+
+fn main() {
+ let type = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py unsafe'
+
+fn main() {
+ let unsafe = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py use'
+
+fn main() {
+ let use = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2013 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.
+
+// This file was auto-generated using 'src/etc/generate-keyword-tests.py while'
+
+fn main() {
+ let while = "foo"; //~ error: ident
+}
--- /dev/null
+// Copyright 2012 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.
+
+pub mod break {
+ //~^ ERROR expected identifier, found keyword `break`
+}
--- /dev/null
+// 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.
+
+fn main() {
+ struct::foo(); //~ ERROR expected identifier
+ mut::baz(); //~ ERROR expected identifier
+}
+
--- /dev/null
+// 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.
+
+fn main() {
+ 0o1.0; //~ ERROR: octal float literal is not supported
+ 0o2f32; //~ ERROR: octal float literal is not supported
+ 0o3.0f32; //~ ERROR: octal float literal is not supported
+ 0o4e4; //~ ERROR: octal float literal is not supported
+ 0o5.0e5; //~ ERROR: octal float literal is not supported
+ 0o6e6f32; //~ ERROR: octal float literal is not supported
+ 0o7.0e7f64; //~ ERROR: octal float literal is not supported
+ 0x8.0e+9; //~ ERROR: hexadecimal float literal is not supported
+ 0x9.0e-9; //~ ERROR: hexadecimal float literal is not supported
+ 0o; //~ ERROR: no valid digits
+ 1e+; //~ ERROR: expected at least one digit in exponent
+ 0x539.0; //~ ERROR: hexadecimal float literal is not supported
+ 99999999999999999999999999999999; //~ ERROR: int literal is too large
+ 99999999999999999999999999999999u32; //~ ERROR: int literal is too large
+ 0x; //~ ERROR: no valid digits
+ 0xu32; //~ ERROR: no valid digits
+ 0ou32; //~ ERROR: no valid digits
+ 0bu32; //~ ERROR: no valid digits
+ 0b; //~ ERROR: no valid digits
+ 0o123f64; //~ ERROR: octal float literal is not supported
+ 0o123.456; //~ ERROR: octal float literal is not supported
+ 0b101f64; //~ ERROR: binary float literal is not supported
+ 0b111.101; //~ ERROR: binary float literal is not supported
+}
--- /dev/null
+// 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.
+
+// ignore-tidy-cr
+
+/// doc comment with bare CR: '\r'
+pub fn foo() {}
+//~^^ ERROR: bare CR not allowed in doc-comment
+
+/** block doc comment with bare CR: '\r' */
+pub fn bar() {}
+//~^^ ERROR: bare CR not allowed in block doc-comment
+
+fn main() {
+ // the following string literal has a bare CR in it
+ let _s = "foo\rbar"; //~ ERROR: bare CR not allowed in string
+
+ // the following string literal has a bare CR in it
+ let _s = r"bar\rfoo"; //~ ERROR: bare CR not allowed in raw string
+
+ // the following string literal has a bare CR in it
+ let _s = "foo\\rbar"; //~ ERROR: unknown character escape: \r
+}
--- /dev/null
+// Copyright 2013 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.
+
+fn foo<'a>(a: &'a isize) { }
+fn bar(a: &'static isize) { }
+fn baz(a: &'let isize) { } //~ ERROR invalid lifetime name
+
+fn main() { }
--- /dev/null
+// Copyright 2013 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.
+
+fn baz(a: &'self isize) { } //~ ERROR invalid lifetime name: 'self is no longer a special lifetime
+
+fn main() { }
--- /dev/null
+// 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.
+
+macro_rules! foo() //~ ERROR semicolon
+
+fn main() {
+}
+++ /dev/null
-// Copyright 2012 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.
-
-mod mod_file_disambig_aux; //~ ERROR file for module `mod_file_disambig_aux` found at both
-
-fn main() {
- assert_eq!(mod_file_aux::bar(), 10);
-}
+++ /dev/null
-// 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.
-
-// error-pattern: cannot declare a new module at this location
-
-mod mod_file_not_owning_aux1;
-
-fn main() {}
--- /dev/null
+// Copyright 2013 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.
+
+// error-pattern:binary float literal is not supported
+
+fn main() {
+ 0b101010f64;
+ 0b101.010;
+ 0b101p4f64;
+}
--- /dev/null
+// Copyright 2013 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.
+
+// error-pattern:hexadecimal float literal is not supported
+
+fn main() {
+ 0xABC.Df;
+ 0x567.89;
+ 0xDEAD.BEEFp-2f;
+}
--- /dev/null
+// Copyright 2013 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.
+
+trait A {
+ fn foo(*mut self); //~ ERROR cannot pass self by unsafe pointer
+ fn bar(*self); //~ ERROR cannot pass self by unsafe pointer
+}
+
+struct X;
+impl A for X {
+ fn foo(*mut self) { } //~ ERROR cannot pass self by unsafe pointer
+ fn bar(*self) { } //~ ERROR cannot pass self by unsafe pointer
+}
+
+fn main() { }
--- /dev/null
+// Copyright 2012 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.
+
+// Issue #623 - non-string meta items are not serialized correctly;
+// for now just forbid them
+
+#[foo = 1] //~ ERROR: non-string literals are not allowed in meta-items
+fn main() { }
--- /dev/null
+// Copyright 2015 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.
+
+// Test that we generate obsolete syntax errors around usages of `for Sized?`
+
+trait Foo for Sized? {} //~ ERROR obsolete syntax: for Sized?
+
+trait Bar for ?Sized {} //~ ERROR obsolete syntax: for Sized?
+
+fn main() { }
--- /dev/null
+// 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.
+
+// Test that we generate obsolete syntax errors around usages of `proc`.
+
+fn foo(p: proc()) { } //~ ERROR obsolete syntax: the `proc` type
+
+fn bar() { proc() 1; } //~ ERROR obsolete syntax: `proc` expression
+
+fn main() { }
--- /dev/null
+// Copyright 2012-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.
+
+// ignore-test Can't use syntax crate here
+
+#![feature(quote)]
+
+extern crate syntax;
+
+use io::*;
+
+use syntax::diagnostic;
+use syntax::ast;
+use syntax::codemap;
+use syntax::parse;
+use syntax::print::*;
+
+
+trait fake_ext_ctxt {
+ fn cfg() -> ast::CrateConfig;
+ fn parse_sess() -> parse::parse_sess;
+ fn call_site() -> span;
+ fn ident_of(st: &str) -> ast::ident;
+}
+
+type fake_session = parse::parse_sess;
+
+impl fake_ext_ctxt for fake_session {
+ fn cfg() -> ast::CrateConfig { Vec::new() }
+ fn parse_sess() -> parse::parse_sess { self }
+ fn call_site() -> span {
+ codemap::span {
+ lo: codemap::BytePos(0),
+ hi: codemap::BytePos(0),
+ expn_id: NO_EXPANSION
+ }
+ }
+ fn ident_of(st: &str) -> ast::ident {
+ self.interner.intern(st)
+ }
+}
+
+fn mk_ctxt() -> fake_ext_ctxt {
+ parse::new_parse_sess(None) as fake_ext_ctxt
+}
+
+
+
+fn main() {
+ let cx = mk_ctxt();
+
+ let abc = quote_expr!(cx, 23);
+ check_pp(abc, pprust::print_expr, "23");
+
+ let expr3 = quote_expr!(cx, 2 - $abcd + 7); //~ ERROR unresolved name: abcd
+ check_pp(expr3, pprust::print_expr, "2 - 23 + 7");
+}
+
+fn check_pp<T>(expr: T, f: |pprust::ps, T|, expect: str) {
+ panic!();
+}
--- /dev/null
+// Copyright 2012-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.
+
+// ignore-test Can't use syntax crate here
+
+#![feature(quote)]
+
+extern crate syntax;
+
+use syntax::diagnostic;
+use syntax::ast;
+use syntax::codemap;
+use syntax::parse::parser;
+use syntax::print::*;
+
+trait fake_ext_ctxt {
+ fn cfg() -> ast::CrateConfig;
+ fn parse_sess() -> parse::parse_sess;
+ fn call_site() -> span;
+ fn ident_of(st: &str) -> ast::ident;
+}
+
+type fake_session = parse::parse_sess;
+
+impl fake_ext_ctxt for fake_session {
+ fn cfg() -> ast::CrateConfig { Vec::new() }
+ fn parse_sess() -> parse::parse_sess { self }
+ fn call_site() -> span {
+ codemap::span {
+ lo: codemap::BytePos(0),
+ hi: codemap::BytePos(0),
+ expn_id: codemap::NO_EXPANSION
+ }
+ }
+ fn ident_of(st: &str) -> ast::ident {
+ self.interner.intern(st)
+ }
+}
+
+fn mk_ctxt() -> fake_ext_ctxt {
+ parse::new_parse_sess(None) as fake_ext_ctxt
+}
+
+
+fn main() {
+ let cx = mk_ctxt();
+
+ let stmt = quote_stmt!(cx, let x isize = 20;); //~ ERROR expected end-of-string
+ check_pp(*stmt, pprust::print_stmt, "");
+}
+
+fn check_pp<T>(expr: T, f: |pprust::ps, T|, expect: str) {
+ panic!();
+}
--- /dev/null
+// 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.
+
+// ignore-test
+// ignored because the first error does not show up.
+
+// Copyright 2012 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.
+
+fn of<T>() -> |T| { panic!(); }
+fn subtype<T>(x: |T|) { panic!(); }
+
+fn test_fn<'x, 'y, 'z, T>(_x: &'x T, _y: &'y T, _z: &'z T) {
+ // Here, x, y, and z are free. Other letters
+ // are bound. Note that the arrangement
+ // subtype::<T1>(of::<T2>()) will typecheck
+ // iff T1 <: T2.
+
+ // should be the default:
+ subtype::< ||:'static>(of::<||>());
+ subtype::<||>(of::< ||:'static>());
+
+ //
+ subtype::< <'x> ||>(of::<||>()); //~ ERROR mismatched types
+ subtype::< <'x> ||>(of::< <'y> ||>()); //~ ERROR mismatched types
+
+ subtype::< <'x> ||>(of::< ||:'static>()); //~ ERROR mismatched types
+ subtype::< ||:'static>(of::< <'x> ||>());
+
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2015 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.
+
+fn f<T>() {}
+
+fn main() {
+ false == false == false;
+ //~^ ERROR: chained comparison operators require parentheses
+
+ false == 0 < 2;
+ //~^ ERROR: chained comparison operators require parentheses
+
+ f<X>();
+ //~^ ERROR: chained comparison operators require parentheses
+ //~^^ HELP: use `::<...>` instead of `<...>`
+}
--- /dev/null
+// Copyright 2013 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.
+
+struct Foo;
+
+fn f2() {
+ let _end_stmt = Foo { };
+ //~^ ERROR: structure literal must either have at least one field
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2013 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.
+
+struct Foo;
+
+fn g3() {
+ let _mid_tuple = (Foo { }, 2);
+ //~^ ERROR: structure literal must either have at least one field
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2013 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.
+
+struct Foo;
+
+fn h4() {
+ let _end_of_tuple = (3, Foo { });
+ //~^ ERROR: structure literal must either have at least one field
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2013 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.
+
+struct Foo;
+
+fn i5() {
+ let _end_of_block = { Foo { } };
+ //~^ ERROR: structure literal must either have at least one field
+}
+
+fn main() {}
--- /dev/null
+// 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.
+
+enum Foo {
+ Bar {} //~ ERROR unit-like struct variant should be written without braces, as `Bar,`
+}
--- /dev/null
+// 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.
+
+enum Foo {
+ Bar {
+ pub a: isize //~ ERROR: `pub` is not allowed here
+ }
+}
+
+fn main() {}
--- /dev/null
+// 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.
+
+#![feature(optin_builtin_traits)]
+
+use std::marker::Send;
+
+struct TestType;
+
+impl !TestType {}
+//~^ ERROR inherent implementation can't be negated
+
+trait TestTrait {}
+
+unsafe impl !Send for TestType {}
+impl !TestTrait for TestType {}
+
+struct TestType2<T>;
+
+impl<T> !TestType2<T> {}
+//~^ ERROR inherent implementation can't be negated
+
+unsafe impl<T> !Send for TestType2<T> {}
+impl<T> !TestTrait for TestType2<T> {}
+
+fn main() {}
--- /dev/null
+// Copyright 2012 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.
+
+//error-pattern: discriminator values can only be used with a c-like enum
+
+enum color {
+ red = 0xff0000,
+ green = 0x00ff00,
+ blue = 0x0000ff,
+ black = 0x000000,
+ white = 0xffffff,
+ other (str),
+}
--- /dev/null
+// 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.
+
+// ignore-tidy-cr
+// Issue #11669
+
+fn main() {
+ // \r\n
+ let ok = "This is \
+ a test";
+ // \r only
+ let bad = "This is \\r a test";
+ //~^ ERROR unknown character escape: \r
+ //~^^ HELP this is an isolated carriage return
+
+}
--- /dev/null
+// Copyright 2012 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.
+
+use std::fmt::Show;
+
+fn main() {
+ let x: Box<Show+> = box 3 as Box<Show+>;
+ //~^ ERROR at least one type parameter bound must be specified
+ //~^^ ERROR at least one type parameter bound must be specified
+}
+
--- /dev/null
+// Copyright 2013 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.
+
+trait Foo {
+}
+
+struct Bar;
+
+impl Foo + Owned for Bar { //~ ERROR not a trait
+}
+
+fn main() { }
--- /dev/null
+// 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.
+
+struct Foo {
+ x: isize,
+ y: isize,
+}
+
+fn main() {
+ let f = Foo {
+ x: 1,
+ y: 2,
+ };
+ f.x::<isize>;
+ //~^ ERROR field expressions may not have type parameters
+}
+
--- /dev/null
+// 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.
+
+// Test syntax checks for `type` keyword.
+
+fn f<X>() {}
+
+pub fn main() {
+ f<type>();
+ //~^ ERROR expected identifier, found keyword `type`
+ //~^^ ERROR: chained comparison
+ //~^^^ HELP: use `::<
+}
--- /dev/null
+// 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.
+
+// Test diagnostics for the removed struct inheritance feature.
+#![feature(struct_inherit)]
+
+virtual struct SuperStruct { //~ ERROR `virtual` structs have been removed from the language
+ f1: isize,
+}
+
+struct Struct : SuperStruct; //~ ERROR `virtual` structs have been removed from the language
+
+pub fn main() {}
--- /dev/null
+// 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.
+
+fn equal1<T>(_: &T, _: &T) -> bool where {
+//~^ ERROR a `where` clause must have at least one predicate in it
+ true
+}
+
+fn equal2<T>(_: &T, _: &T) -> bool where T: {
+//~^ ERROR each predicate in a `where` clause must have at least one bound
+ true
+}
+
+fn main() {
+}
+
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait X { }
+trait X { fn dummy(&self) { } }
impl X for uint { }
-trait Y { }
+trait Y { fn dummy(&self) { } }
impl Y for uint { }
// pp-exact
-trait Tr { }
+trait Tr {
+ fn dummy(&self) { }
+}
impl Tr for int { }
fn foo<'a>(x: Box<Tr+ Sync + 'a>) -> Box<Tr+ Sync + 'a> { x }
// except according to those terms.
// error-pattern:quux
+
+use std::marker::PhantomData;
+
fn test00_start(ch: chan_t<int>, message: int) { send(ch, message); }
type task_id = int;
struct chan_t<T> {
task: task_id,
port: port_id,
+ marker: PhantomData<*mut T>,
}
fn send<T:Send>(_ch: chan_t<T>, _data: T) { panic!(); }
}
/// *wow*
- pub trait Doge { }
+ pub trait Doge { fn dummy(&self) { } }
}
// @matches foo/struct.Alpha.html '//pre' "pub struct Alpha"
pub struct Alpha;
// @matches foo/struct.Bravo.html '//pre' "pub struct Bravo<B>"
-pub struct Bravo<B>;
+pub struct Bravo<B>(B);
// @matches foo/struct.Alpha.html '//*[@class="impl"]//code' "impl !Send for Alpha"
impl !Send for Alpha {}
}
pub trait PrivateTrait {
- fn trait_method() {} // @!has - priv_method
+ fn trait_method(&self) {} // @!has - priv_method
}
}
/// *wow*
// @has foo/bar/trait.Doge.html
- pub trait Doge { }
+ pub trait Doge { fn dummy(&self) { } }
// @has foo/bar/struct.Foo.html
pub struct Foo { x: int, y: uint }
// except according to those terms.
pub mod io {
- pub trait Reader { }
+ pub trait Reader { fn dummy(&self) { } }
}
pub enum Maybe<A> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub trait MyTrait {}
+pub trait MyTrait { fn dummy(&self) { } }
// @has foo/struct.Alpha.html '//pre' "pub struct Alpha<A> where A: MyTrait"
-pub struct Alpha<A> where A: MyTrait;
+pub struct Alpha<A>(A) where A: MyTrait;
// @has foo/trait.Bravo.html '//pre' "pub trait Bravo<B> where B: MyTrait"
-pub trait Bravo<B> where B: MyTrait {}
+pub trait Bravo<B> where B: MyTrait { fn get(&self, B: B); }
// @has foo/fn.charlie.html '//pre' "pub fn charlie<C>() where C: MyTrait"
pub fn charlie<C>() where C: MyTrait {}
-pub struct Delta<D>;
+pub struct Delta<D>(D);
+
// @has foo/struct.Delta.html '//*[@class="impl"]//code' \
// "impl<D> Delta<D> where D: MyTrait"
impl<D> Delta<D> where D: MyTrait {
pub fn delta() {}
}
-pub struct Echo<E>;
+pub struct Echo<E>(E);
+
// @has foo/struct.Echo.html '//*[@class="impl"]//code' \
// "impl<E> MyTrait for Echo<E> where E: MyTrait"
// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \
// "impl<E> MyTrait for Echo<E> where E: MyTrait"
impl<E> MyTrait for Echo<E> where E: MyTrait {}
-pub enum Foxtrot<F> {}
+pub enum Foxtrot<F> { Foxtrot1(F) }
+
// @has foo/enum.Foxtrot.html '//*[@class="impl"]//code' \
// "impl<F> MyTrait for Foxtrot<F> where F: MyTrait"
// @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \
static uni: &'static str = "Les Miséééééééérables";
static yy: usize = 25;
-static bob: Option<std::vec::CowVec<'static, isize>> = None;
+static bob: Option<&'static [isize]> = None;
// buglink test - see issue #1337.
type SF = some_fields;
trait SuperTrait {
+ fn dummy(&self) { }
}
trait SomeTrait: SuperTrait {
}
#[lang = "sized"]
-trait Sized {}
+pub trait Sized : PhantomFn<Self> {}
#[lang = "copy"]
-trait Copy {}
+pub trait Copy : PhantomFn<Self> {}
+
+#[lang="phantom_fn"]
+pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
+impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
mod core {
pub mod marker {
pub static X: &'static str = "foobarbaz";
pub static Y: &'static [u8] = include_bytes!("lib.rs");
-trait Foo {}
+trait Foo { fn dummy(&self) { } }
impl Foo for uint {}
pub fn dummy() {
#![feature(lang_items, no_std)]
#![no_std]
+#[lang="phantom_fn"]
+trait PhantomFn<A:?Sized,R:?Sized=()> { }
+impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
+
#[lang="copy"]
-trait Copy { }
+trait Copy : PhantomFn<Self> { }
#[lang="sized"]
-trait Sized { }
+trait Sized : PhantomFn<Self> { }
#[lang="start"]
fn start(_main: *const u8, _argc: int, _argv: *const *const u8) -> int { 0 }
}
-trait Trait {}
+trait Trait { fn dummy(&self) { } }
impl Trait for Foo {}
pub fn main() {
}
}
-trait Trait {}
+trait Trait { fn dummy(&self) { } }
impl Trait for Foo {}
struct Fat<T: ?Sized> {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Foo {
+use std::marker::MarkerTrait;
+
+trait Foo : MarkerTrait {
type T;
}
// `Target=[A]`, then the impl marked with `(*)` is seen to conflict
// with all the others.
+use std::marker::PhantomData;
use std::ops::Deref;
pub trait MyEq<U: ?Sized=Self> {
}
struct DerefWithHelper<H, T> {
- pub helper: H
+ pub helper: H,
+ pub marker: PhantomData<T>,
}
trait Helper<T> {
}
pub fn check<T: MyEq>(x: T, y: T) -> bool {
- let d: DerefWithHelper<Option<T>, T> = DerefWithHelper { helper: Some(x) };
+ let d: DerefWithHelper<Option<T>, T> = DerefWithHelper { helper: Some(x),
+ marker: PhantomData };
d.eq(&y)
}
// Test that we are able to have an impl that defines an associated type
// before the actual trait.
+use std::marker::MarkerTrait;
+
impl X for f64 { type Y = int; }
-trait X {type Y; }
+trait X : MarkerTrait { type Y; }
fn main() {}
panic!()
}
}
-impl <P> Parser for P {
+
+impl <P> Parser for P {
type Input = ();
}
// Test that we can resolve nested projection types. Issue #20666.
+use std::marker::MarkerTrait;
use std::slice;
-trait Bound {}
+trait Bound : MarkerTrait {}
-impl<'a> Bound for &'a int {}
+impl<'a> Bound for &'a i32 {}
trait IntoIterator {
type Iter: Iterator;
#![allow(dead_code)]
-pub trait Integral {
+use std::marker::MarkerTrait;
+
+pub trait Integral : MarkerTrait {
type Opposite;
}
pub trait FnLike<A> {
type R;
+
+ fn dummy(&self, a: A) -> Self::R { loop { } }
}
fn foo<T>()
// Test that we normalize associated types that appear in bounds; if
// we didn't, the call to `self.split2()` fails to type check.
-struct Splits<'a, T, P>;
-struct SplitsN<I>;
+use std::marker::PhantomData;
+
+struct Splits<'a, T:'a, P>(PhantomData<(&'a T, P)>);
+struct SplitsN<I>(PhantomData<I>);
trait SliceExt2 {
type Item;
fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P>
where P: FnMut(&Self::Item) -> bool;
- fn splitn2<'a, P>(&'a self, n: uint, pred: P) -> SplitsN<Splits<'a, Self::Item, P>>
+ fn splitn2<'a, P>(&'a self, n: u32, pred: P) -> SplitsN<Splits<'a, Self::Item, P>>
where P: FnMut(&Self::Item) -> bool;
}
loop {}
}
- fn splitn2<P>(&self, n: uint, pred: P) -> SplitsN<Splits<T, P>> where P: FnMut(&T) -> bool {
+ fn splitn2<P>(&self, n: u32, pred: P) -> SplitsN<Splits<T, P>> where P: FnMut(&T) -> bool {
SliceExt2::split2(self, pred);
loop {}
}
// Test that we normalize associated types that appear in bounds; if
// we didn't, the call to `self.split2()` fails to type check.
-struct Splits<'a, T, P>;
-struct SplitsN<I>;
+use std::marker::PhantomData;
+
+struct Splits<'a, T, P>(PhantomData<(&'a(),T,P)>);
+struct SplitsN<I>(PhantomData<I>);
trait SliceExt2 {
type Item;
fn split2<'a, P>(&'a self, pred: P) -> Splits<'a, Self::Item, P>
where P: FnMut(&Self::Item) -> bool;
- fn splitn2<'a, P>(&'a self, n: uint, pred: P) -> SplitsN<Splits<'a, Self::Item, P>>
+ fn splitn2<'a, P>(&'a self, n: usize, pred: P) -> SplitsN<Splits<'a, Self::Item, P>>
where P: FnMut(&Self::Item) -> bool;
}
loop {}
}
- fn splitn2<P>(&self, n: uint, pred: P) -> SplitsN<Splits<T, P>> where P: FnMut(&T) -> bool {
+ fn splitn2<P>(&self, n: usize, pred: P) -> SplitsN<Splits<T, P>> where P: FnMut(&T) -> bool {
self.split2(pred);
loop {}
}
pub trait OffsetState: Sized {}
-pub trait Offset { type State: OffsetState; }
+pub trait Offset {
+ type State: OffsetState;
+ fn dummy(&self) { }
+}
#[derive(Copy)] pub struct X;
impl Offset for X { type State = Y; }
trait Int
{
type T;
+
+ fn dummy(&self) { }
}
trait NonZero
pub trait Subscriber {
type Input;
+
+ fn dummy(&self) { }
}
pub trait Publisher<'a> {
trait A
{
type TA;
+
+ fn dummy(&self) { }
}
trait B<TB>
trait Int
{
type T;
+
+ fn dummy(&self) { }
}
trait NonZero
pub trait Foo {
type Bar;
+
+ fn dummy(&self) { }
}
impl Foo for int {
trait Trait<'a> {
type T: 'static;
type U: Get<&'a int>;
+
+ fn dummy(&'a self) { }
}
fn main() {}
pub trait UnifyKey {
type Value;
+
+ fn dummy(&self) { }
}
pub struct Node<K:UnifyKey> {
pub trait UnifyKey {
type Value;
+
+ fn dummy(&self) { }
}
pub struct Node<K:UnifyKey>(K, K::Value);
// Using a type via an impl.
trait C {
fn f();
+ fn g(&self) { }
}
-struct B<X>;
+struct B<X>(X);
impl<T: Foo> C for B<T> {
fn f() {
let x: T::A = panic!();
#![feature(box_syntax)]
extern crate collections;
-use std::collections::Bitv;
+use std::collections::BitVec;
fn bitv_test() {
- let mut v1 = box Bitv::from_elem(31, false);
- let v2 = box Bitv::from_elem(31, true);
+ let mut v1 = box BitVec::from_elem(31, false);
+ let v2 = box BitVec::from_elem(31, true);
v1.union(&*v2);
}
// to the same lifetime on a trait succeeds. See issue #10766.
#![allow(dead_code)]
+
+use std::marker;
+
fn main() {
- trait T {}
+ trait T { fn foo(&self) {} }
fn f<'a, V: T>(v: &'a V) -> &'a T {
v as &'a T
// except according to those terms.
pub trait Foo<T> {
- fn func1<U>(&self, t: U);
+ fn func1<U>(&self, t: U, w: T);
- fn func2<U>(&self, t: U) {
- self.func1(t);
+ fn func2<U>(&self, t: U, w: T) {
+ self.func1(t, w);
}
}
extern crate trait_superkinds_in_metadata;
use trait_superkinds_in_metadata::{RequiresRequiresShareAndSend, RequiresShare};
use trait_superkinds_in_metadata::{RequiresCopy};
+use std::marker;
#[derive(Copy)]
struct X<T>(T);
// super-builtin-kind of a trait, if the type parameter is never used,
// the type can implement the trait anyway.
+use std::marker;
+
trait Foo : Send { }
-struct X<T>(());
+struct X<T> { marker: marker::PhantomData<T> }
-impl <T> Foo for X<T> { }
+impl<T:Send> Foo for X<T> { }
pub fn main() { }
}
fn atol(s: String) -> int {
- let c = CString::from_slice(s.as_bytes());
+ let c = CString::new(s).unwrap();
unsafe { mlibc::atol(c.as_ptr()) as int }
}
fn atoll(s: String) -> i64 {
- let c = CString::from_slice(s.as_bytes());
+ let c = CString::new(s).unwrap();
unsafe { mlibc::atoll(c.as_ptr()) as i64 }
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::marker::PhantomData;
+
struct cat<U> {
meows : uint,
-
how_hungry : int,
+ m: PhantomData<U>
}
impl<U> cat<U> {
fn cat<U>(in_x : uint, in_y : int) -> cat<U> {
cat {
meows: in_x,
- how_hungry: in_y
+ how_hungry: in_y,
+ m: PhantomData
}
}
#![feature(macro_rules)]
use std::borrow::{Cow, IntoCow};
-use std::collections::Bitv;
+use std::collections::BitVec;
use std::default::Default;
use std::iter::FromIterator;
use std::ops::Add;
Vec::<()>::new, fn() -> Vec<()>, ();
Vec::with_capacity, fn(uint) -> Vec<()>, (5);
Vec::<()>::with_capacity, fn(uint) -> Vec<()>, (5);
- Bitv::from_fn, fn(uint, fn(uint) -> bool) -> Bitv, (5, odd);
- Bitv::from_fn::<fn(uint) -> bool>, fn(uint, fn(uint) -> bool) -> Bitv, (5, odd);
+ BitVec::from_fn, fn(uint, fn(uint) -> bool) -> BitVec, (5, odd);
+ BitVec::from_fn::<fn(uint) -> bool>, fn(uint, fn(uint) -> bool) -> BitVec, (5, odd);
// Inherent non-static method.
Vec::map_in_place, fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>, (vec![b'f', b'o', b'o'], u8_as_i8);
Add::add, fn(i32, i32) -> i32, (5, 6);
<i32 as Add<_>>::add, fn(i32, i32) -> i32, (5, 6);
<i32 as Add<i32>>::add, fn(i32, i32) -> i32, (5, 6);
- <String as IntoCow<_, _>>::into_cow, fn(String) -> Cow<'static, String, str>,
+ <String as IntoCow<_>>::into_cow, fn(String) -> Cow<'static, str>,
("foo".to_string());
- <String as IntoCow<'static, _, _>>::into_cow, fn(String) -> Cow<'static, String, str>,
+ <String as IntoCow<'static, _>>::into_cow, fn(String) -> Cow<'static, str>,
("foo".to_string());
}
phone: uint,
}
-fn hash<T: Hash<SipHasher>>(t: &T) -> u64 {
+fn hash<T: Hash>(t: &T) -> u64 {
std::hash::hash::<T, SipHasher>(t)
}
baz: int
}
-fn hash<T: Hash<SipHasher>>(_t: &T) {}
+fn hash<T: Hash>(_t: &T) {}
pub fn main() {
let a = Foo {bar: 4, baz: -3};
baz: int
}
-fn hash<T: Hash<SipHasher>>(_t: &T) {}
+fn hash<T: Hash>(_t: &T) {}
pub fn main() {
let a = Foo {bar: 4, baz: -3};
// Test coercions involving DST and/or raw pointers
struct S;
-trait T {}
+trait T { fn dummy(&self) { } }
impl T for S {}
pub fn main() {
use std::rc::Rc;
use std::sync::Arc;
-trait Trait {}
+trait Trait { fn dummy(&self) { } }
fn main() {
// Functions
struct LM { resize_at: uint, size: uint }
enum HashMap<K,V> {
- HashMap_(LM)
+ HashMap_(LM, Vec<(K,V)>)
}
-impl<K,V> Copy for HashMap<K,V> {}
-
fn linear_map<K,V>() -> HashMap<K,V> {
HashMap::HashMap_(LM{
resize_at: 32,
- size: 0})
+ size: 0}, Vec::new())
}
impl<K,V> HashMap<K,V> {
pub fn len(&mut self) -> uint {
match *self {
- HashMap::HashMap_(l) => l.size
+ HashMap::HashMap_(ref l, _) => l.size
}
}
}
+++ /dev/null
-// Copyright 2012 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.
-
-
-enum list_cell<T> { cons(Box<list_cell<T>>), nil }
-
-pub fn main() { }
fn strlen(str: String) -> uint {
// C string is terminated with a zero
- let s = CString::from_slice(str.as_bytes());
+ let s = CString::new(str).unwrap();
unsafe {
mlibc::my_strlen(s.as_ptr()) as uint
}
extern crate default_type_params_xc;
-struct Vec<T, A = default_type_params_xc::Heap>;
+struct Vec<T, A = default_type_params_xc::Heap>(Option<(T,A)>);
struct Foo;
fn main() {
- let _a = Vec::<int>;
- let _b = Vec::<int, default_type_params_xc::FakeHeap>;
- let _c = default_type_params_xc::FakeVec::<int>;
- let _d = default_type_params_xc::FakeVec::<int, Foo>;
+ let _a = Vec::<int>(None);
+ let _b = Vec::<int, default_type_params_xc::FakeHeap>(None);
+ let _c = default_type_params_xc::FakeVec::<int> { f: None };
+ let _d = default_type_params_xc::FakeVec::<int, Foo> { f: None };
}
#![allow(dead_code)]
-use std::marker;
+use std::marker::PhantomData;
#[derive(Copy)]
struct Foo<T> { x: T }
type Ty<'tcx> = &'tcx TyS<'tcx>;
enum TyS<'tcx> {
- Boop(marker::InvariantLifetime<'tcx>)
+ Boop(PhantomData<*mut &'tcx ()>)
}
#[derive(Copy)]
extern crate inner_static;
pub fn main() {
- let a = inner_static::A::<()>;
- let b = inner_static::B::<()>;
- let c = inner_static::test::A::<()>;
+ let a = inner_static::A::<()> { v: () };
+ let b = inner_static::B::<()> { v: () };
+ let c = inner_static::test::A::<()> { v: () };
assert_eq!(a.bar(), 2);
assert_eq!(b.bar(), 4);
assert_eq!(c.bar(), 6);
fn bar(&self);
}
-pub trait Baz {}
+pub trait Baz {
+ fn baz(&self) { }
+}
impl<T: Baz> Bar for T {
fn bar(&self) {}
}
}
-trait MyTrait { }
+trait MyTrait { fn dummy(&self) { } }
impl MyTrait for Box<DroppableStruct> {}
impl MyTrait for Box<DroppableEnum> {}
// except according to those terms.
pub mod two_tuple {
- pub trait T {}
+ pub trait T { fn dummy(&self) { } }
pub struct P<'a>(&'a (T + 'a), &'a (T + 'a));
pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
P(car, cdr)
}
pub mod two_fields {
- pub trait T {}
+ pub trait T { fn dummy(&self) { } }
pub struct P<'a> { car: &'a (T + 'a), cdr: &'a (T + 'a) }
pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> {
P{ car: car, cdr: cdr }
#![allow(unknown_features)]
#![feature(box_syntax)]
-trait Foo {}
+trait Foo { fn dummy(&self) { } }
impl Foo for int {}
fn foo(_: [&Foo; 2]) {}
fn foos(_: &[&Foo]) {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Common {}
+trait Common { fn dummy(&self) { } }
impl<'t, T> Common for (T, &'t T) {}
// We weren't updating the auto adjustments with all the resolved
// type information after type check.
-trait A {}
+trait A { fn dummy(&self) { } }
struct B<'a, T:'a> {
f: &'a T
// this code used to cause an ICE
-trait X<T> {}
+use std::marker;
+
+trait X<T> {
+ fn dummy(&self) -> T { panic!() }
+}
struct S<T> {f: Box<X<T>+'static>,
g: Box<X<T>+'static>}
struct F;
-impl X<int> for F {}
+impl X<int> for F {
+}
fn main() {
S {f: box F, g: box F};
extern crate collections;
-use std::collections::Bitv;
+use std::collections::BitVec;
use std::num::Float;
fn main() {
// Generate sieve of Eratosthenes for n up to 1e6
let n = 1000000_usize;
- let mut sieve = Bitv::from_elem(n+1, true);
+ let mut sieve = BitVec::from_elem(n+1, true);
let limit: uint = (n as f32).sqrt() as uint;
for i in 2..limit+1 {
if sieve[i] {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Foo {
+use std::marker::MarkerTrait;
+
+trait Foo : MarkerTrait {
fn quux(u8) {}
}
#[derive(Clone)]
struct B1;
-trait A {}
+trait A { fn foo(&self) {} }
impl A for B1 {}
fn main() {
fn main() {
send::<Box<Foo>>(box Output(0));
Test::<Box<Foo>>::foo(box Output(0));
- Test::<Box<Foo>>.send(box Output(0));
+ Test::<Box<Foo>>::new().send(box Output(0));
}
fn send<T>(_: T) {}
-struct Test<T>;
+struct Test<T> { marker: std::marker::PhantomData<T> }
impl<T> Test<T> {
+ fn new() -> Test<T> { Test { marker: ::std::marker::PhantomData } }
fn foo(_: T) {}
fn send(&self, _: T) {}
}
-trait Foo {}
+trait Foo { fn dummy(&self) { }}
struct Output(int);
impl Foo for Output {}
#![feature(unboxed_closures)]
-trait Foo {}
+trait Foo { fn dummy(&self) { }}
struct Bar;
use std::ops::Fn;
-trait Response {}
-trait Request {}
+trait Response { fn dummy(&self) { } }
+trait Request { fn dummy(&self) { } }
trait Ingot<R, S> {
fn enter(&mut self, _: &mut R, _: &mut S, a: &mut Alloy) -> Status;
}
#[allow(dead_code)]
struct HelloWorld;
-struct SendFile<'a>;
+struct SendFile;
struct Alloy;
enum Status {
Continue
}
}
-impl<'a, 'b> Fn<(&'b mut (Response+'b),)> for SendFile<'a> {
+impl<'b> Fn<(&'b mut (Response+'b),)> for SendFile {
type Output = ();
extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {}
static mut DROP_RAN: bool = false;
-trait Bar<'b> {
+trait Bar {
fn do_something(&mut self);
}
-struct BarImpl<'b>;
+struct BarImpl;
-impl<'b> Bar<'b> for BarImpl<'b> {
+impl Bar for BarImpl {
fn do_something(&mut self) {}
}
-struct Foo<B>;
+struct Foo<B>(B);
#[unsafe_destructor]
-impl<'b, B: Bar<'b>> Drop for Foo<B> {
+impl<B: Bar> Drop for Foo<B> {
fn drop(&mut self) {
unsafe {
DROP_RAN = true;
fn main() {
{
- let _x: Foo<BarImpl> = Foo;
+ let _x: Foo<BarImpl> = Foo(BarImpl);
}
unsafe {
assert_eq!(DROP_RAN, true);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait MatrixRow {}
+trait MatrixRow { fn dummy(&self) { }}
struct Mat;
extern crate "issue-16643" as i;
pub fn main() {
- i::TreeBuilder::<uint>.process_token();
+ i::TreeBuilder { h: 3u }.process_token();
}
extern crate "issue-17662" as i;
-struct Bar<'a>;
+use std::marker;
+
+struct Bar<'a> { m: marker::PhantomData<&'a ()> }
impl<'a> i::Foo<'a, uint> for Bar<'a> {
fn foo(&self) -> uint { 5_usize }
}
pub fn main() {
- assert_eq!(i::foo(&Bar), 5);
+ assert_eq!(i::foo(&Bar { m: marker::PhantomData }), 5);
}
trait Person {
type string;
+ fn dummy(&self) { }
}
-struct Someone<P: Person>;
+struct Someone<P: Person>(std::marker::PhantomData<P>);
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Aaa {}
+trait Aaa { fn dummy(&self) { } }
impl<'a> Aaa for &'a mut (Aaa + 'a) {}
#![feature(unboxed_closures)]
+use std::marker::PhantomData;
+
fn main() {
- struct Symbol<'a, F: Fn(Vec<&'a str>) -> &'a str> { function: F }
+ struct Symbol<'a, F: Fn(Vec<&'a str>) -> &'a str> { function: F, marker: PhantomData<&'a ()> }
let f = |x: Vec<&str>| -> &str "foobar";
- let sym = Symbol { function: f };
+ let sym = Symbol { function: f, marker: PhantomData };
(sym.function)(vec![]);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-struct Foo<T> where T: Copy;
+// Test that we can parse where clauses on various forms of tuple
+// structs.
+
struct Bar<T>(T) where T: Copy;
struct Bleh<T, U>(T, U) where T: Copy, U: Sized;
struct Baz<T> where T: Copy {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-struct Cursor<'a>;
+struct Cursor<'a>(::std::marker::PhantomData<&'a ()>);
trait CursorNavigator {
fn init_cursor<'a, 'b:'a>(&'a self, cursor: &mut Cursor<'b>) -> bool;
}
fn main() {
- let mut c = Cursor;
+ let mut c = Cursor(::std::marker::PhantomData);
let n = SimpleNavigator;
n.init_cursor(&mut c);
}
q.foo(k.borrow())
}
-struct MyTree<K>;
+struct MyTree<K>(K);
impl<K> MyTree<K> {
// This caused a failure in #18906
trait Foo {
type A;
+
+ fn dummy(&self) { }
}
fn bar(x: &Foo) {}
trait Trait<Input> {
type Output;
- fn method() -> bool { false }
+ fn method(&self, i: Input) -> bool { false }
}
fn main() {}
#![feature(unboxed_closures)]
+use std::marker::PhantomData;
+
#[derive(Debug)]
-struct LifetimeStruct<'a>;
+struct LifetimeStruct<'a>(PhantomData<&'a ()>);
fn main() {
takes_hrtb_closure(|lts| println!("{:?}", lts));
}
fn takes_hrtb_closure<F: for<'a>FnMut(LifetimeStruct<'a>)>(mut f: F) {
- f(LifetimeStruct);
+ f(LifetimeStruct(PhantomData));
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Trait {}
+trait Trait { fn dummy(&self) { } }
#[derive(Debug)]
struct Foo<T: Trait> {
// except according to those terms.
trait T {
- unsafe extern "Rust" fn foo();
+ unsafe extern "Rust" fn foo(&self);
}
impl T for () {
- unsafe extern "Rust" fn foo() {}
+ unsafe extern "Rust" fn foo(&self) {}
}
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Base {}
+trait Base {
+ fn dummy(&self) { }
+}
trait AssocA {
type X: Base;
+ fn dummy(&self) { }
}
trait AssocB {
type Y: Base;
+ fn dummy(&self) { }
}
impl<T: AssocA> AssocB for T {
type Y = <T as AssocA>::X;
trait PoolManager {
type C;
+ fn dummy(&self) { }
}
struct InnerPool<M> {
trait PoolManager {
type C;
+ fn dummy(&self) { }
}
struct InnerPool<M: PoolManager> {
// whichever arm is run, and subsequently dropped at the end of the
// statement surrounding the `match`.
-trait Boo { }
+trait Boo {
+ fn dummy(&self) { }
+}
impl Boo for [i8; 1] { }
impl Boo for [i8; 2] { }
struct C;
struct D;
-trait T<A> {}
+trait T<A> { fn dummy(&self, a: A) { } }
impl<A> T<A> for () {}
impl B {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait T0 { type O; }
+trait T0 {
+ type O;
+ fn dummy(&self) { }
+}
struct S<A>(A);
impl<A> T0 for S<A> { type O = A; }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait T0 { type O; }
+trait T0 {
+ type O;
+ fn dummy(&self) { }
+}
struct S<A>(A);
impl<A> T0 for S<A> { type O = A; }
trait Iterator {
type Item;
+ fn dummy(&self) { }
}
impl<'a, T> Iterator for &'a mut (Iterator<Item=T> + 'a) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait A<X> {}
+trait A<X> {
+ fn dummy(&self, arg: X);
+}
trait B {
type X;
type Y: A<Self::X>;
+
+ fn dummy(&self);
}
fn main () { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait clam<A> { }
+trait clam<A> {
+ fn get(self) -> A;
+}
+
struct foo<A> {
x: A,
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait clam<A> { }
+trait clam<A> { fn get(self) -> A; }
trait foo<A> {
fn bar<B,C:clam<A>>(&self, c: C) -> B;
}
// Testing that the B's are resolved
-trait clam<A> { }
+trait clam<A> { fn get(self) -> A; }
struct foo(int);
// except according to those terms.
extern crate collections;
-use std::collections::RingBuf;
+use std::collections::VecDeque;
pub fn main() {
- let mut q = RingBuf::new();
+ let mut q = VecDeque::new();
q.push_front(10);
}
// than the traits require.
trait A {
- fn b<C:Sync,D>(x: C) -> C;
+ fn b<C:Sync,D>(&self, x: C) -> C;
}
struct E {
}
impl A for E {
- fn b<F,G>(_x: F) -> F { panic!() }
+ fn b<F,G>(&self, _x: F) -> F { panic!() }
//~^ ERROR in method `b`, type parameter 0 has 1 bound, but
}
#![allow(unknown_features)]
#![feature(box_syntax)]
-trait hax { }
+trait hax {
+ fn dummy(&self) { }
+}
impl<A> hax for A { }
fn perform_hax<T: 'static>(x: Box<T>) -> Box<hax+'static> {
#![allow(unknown_features)]
#![feature(box_syntax)]
-trait hax { }
+trait hax {
+ fn dummy(&self) { }
+}
impl<A> hax for A { }
fn perform_hax<T: 'static>(x: Box<T>) -> Box<hax+'static> {
// except according to those terms.
pub fn main() {
- let _id: &Mat2<f64> = &Matrix::identity();
+ let _id: &Mat2<f64> = &Matrix::identity(1.0);
}
-pub trait Index<Index,Result> { }
+pub trait Index<Index,Result> { fn get(&self, Index) -> Result { panic!() } }
pub trait Dimensional<T>: Index<uint, T> { }
-pub struct Mat2<T> { x: () }
-pub struct Vec2<T> { x: () }
+pub struct Mat2<T> { x: T }
+pub struct Vec2<T> { x: T }
impl<T> Dimensional<Vec2<T>> for Mat2<T> { }
impl<T> Index<uint, Vec2<T>> for Mat2<T> { }
impl<T> Index<uint, T> for Vec2<T> { }
pub trait Matrix<T,V>: Dimensional<V> {
- fn identity() -> Self;
+ fn identity(t:T) -> Self;
}
impl<T> Matrix<T, Vec2<T>> for Mat2<T> {
- fn identity() -> Mat2<T> { Mat2{ x: () } }
+ fn identity(t:T) -> Mat2<T> { Mat2{ x: t } }
}
#![feature(box_syntax)]
pub trait EventLoop {
+ fn dummy(&self) { }
}
pub struct UvEventLoop {
// minimal
-pub trait MyTrait<T> { }
+pub trait MyTrait<T> {
+ fn dummy(&self, t: T) -> T { panic!() }
+}
pub struct MyContainer<'a, T> {
foos: Vec<&'a (MyTrait<T>+'a)> ,
trait Graph<Node, Edge> {
fn f(&self, Edge);
+ fn g(&self, Node);
}
fn f(&self, _e: E) {
panic!();
}
+ fn g(&self, _e: int) {
+ panic!();
+ }
}
pub fn main() {
A(Box<Foo+'static>)
}
-pub trait Foo {}
+pub trait Foo {
+ fn dummy(&self) { }
+}
pub struct Struct;
trait Foo {
fn new() -> bool { false }
+ fn dummy(&self) { }
}
trait Bar {
pub fn main() {}
-trait A {}
+trait A {
+ fn dummy(&self) { }
+}
+
impl<T: 'static> A for T {}
fn owned2<T: 'static>(a: Box<T>) { a as Box<A>; }
// with different mutability in macro in two methods
#![allow(unused_variable)] // unused foobar_immut + foobar_mut
-trait FooBar {}
+trait FooBar {
+ fn dummy(&self) { }
+}
struct Bar(i32);
struct Foo { bar: Bar }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait A {}
+trait A {
+ fn dummy(&self) { }
+}
struct B;
impl A for B {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait A {}
+trait A {
+ fn dummy(&self) { }
+}
struct B;
impl A for B {}
A(T),
}
- pub trait X {}
+ pub trait X {
+ fn dummy(&self) { }
+ }
impl X for int {}
pub struct Z<'a>(Enum<&'a (X+'a)>);
}
mod b {
- trait X {}
+ trait X {
+ fn dummy(&self) { }
+ }
impl X for int {}
struct Y<'a>{
x:Option<&'a (X+'a)>,
}
trait A {
- fn foo() {
+ fn foo(&self) {
unsafe {
rust_get_test_int();
}
#![allow(dead_code)]
-struct Cursor<'a>;
+use std::marker;
+
+struct Cursor<'a> {
+ m: marker::PhantomData<&'a ()>
+}
trait CursorNavigator {
fn init_cursor<'a, 'b:'a>(&'a self, cursor: &mut Cursor<'b>) -> bool;
}
fn main() {
- let mut c = Cursor;
+ let mut c = Cursor { m: marker::PhantomData };
let n = SimpleNavigator;
n.init_cursor(&mut c);
}
// Note: this must be generic for the problem to show up
trait Foo<A> {
- fn foo(&self);
+ fn foo(&self, a: A);
}
impl Foo<u8> for [u8] {
- fn foo(&self) {}
+ fn foo(&self, a: u8) {}
}
impl<'a, A, T> Foo<A> for &'a T where T: Foo<A> {
- fn foo(&self) {
- Foo::foo(*self)
+ fn foo(&self, a: A) {
+ Foo::foo(*self, a)
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+use std::marker::MarkerTrait;
-trait Serializer {
+trait Serializer : MarkerTrait {
}
trait Serializable {
use std::ops::Deref;
struct DerefWithHelper<H, T> {
- helper: H
+ helper: H,
+ value: T
}
trait Helper<T> {
}
pub fn main() {
- let x: DerefWithHelper<Option<Foo>, Foo> = DerefWithHelper { helper: Some(Foo {x: 5}) };
+ let x: DerefWithHelper<Option<Foo>, Foo> =
+ DerefWithHelper { helper: Some(Foo {x: 5}), value: Foo { x: 2 } };
assert!(x.foo() == 5);
}
#![feature(unboxed_closures)]
+use std::marker::PhantomData;
use std::ops::Fn;
use std::ops::Add;
-struct G<A>;
+struct G<A>(PhantomData<A>);
impl<'a, A: Add<i32, Output=i32>> Fn<(A,)> for G<A> {
type Output = i32;
fn main() {
// ICE trigger
- G(1_i32);
+ (G(PhantomData))(1_i32);
}
#![allow(dead_code)]
-trait A<T> {}
-trait B<T, U> {}
-trait C<'a, U> {}
+trait A<T> { fn get(self) -> T; }
+trait B<T, U> { fn get(self) -> (T,U); }
+trait C<'a, U> { fn get(self) -> &'a U; }
mod foo {
- pub trait D<'a, T> {}
+ pub trait D<'a, T> { fn get(self) -> &'a T; }
}
fn foo1<T>(_: &(A<T> + Send)) {}
// public type, private value
pub mod foo1 {
pub trait Bar {
+ fn dummy(&self) { }
}
pub struct Baz;
// private type, public value
pub mod foo2 {
trait Bar {
+ fn dummy(&self) { }
}
pub struct Baz;
// public type, public value
pub mod foo3 {
pub trait Bar {
+ fn dummy(&self) { }
}
pub struct Baz;
// Test that the compiler considers the 'static bound declared in the
// trait. Issue #20890.
-trait Foo { type Value: 'static; }
+trait Foo {
+ type Value: 'static;
+ fn dummy(&self) { }
+}
fn require_static<T: 'static>() {}
#![feature(issue_5723_bootstrap)]
-trait Foo { }
+trait Foo {
+ fn dummy(&self) { }
+}
fn foo<'a, 'b, 'c:'a+'b, 'd>() {
}
#![feature(issue_5723_bootstrap)]
-
-trait Foo { }
+trait Foo {
+ fn dummy(&self) { }
+}
fn foo<'a>(x: Box<Foo + 'a>) {
}
// lifetime parameters must be early bound in the type of the
// associated item.
+use std::marker;
+
pub enum Value<'v> {
A(&'v str),
B,
fn read(&mut self) -> Value<'v>;
}
-pub trait Decodable<'v, D: Decoder<'v>> {
+pub trait Decodable<'v, D: Decoder<'v>>
+ : marker::PhantomFn<(), &'v int>
+{
fn decode(d: &mut D) -> Self;
}
x.f.short()
}
-trait MakerTrait<'o> {
+trait MakerTrait {
fn mk() -> Self;
}
-fn make_val<'p, T:MakerTrait<'p>>() -> T {
+fn make_val<T:MakerTrait>() -> T {
MakerTrait::mk()
}
}
}
-impl<'t> MakerTrait<'t> for Box<Trait<'t>+'static> {
+impl<'t> MakerTrait for Box<Trait<'t>+'static> {
fn mk() -> Box<Trait<'t>+'static> { box() (4,5) as Box<Trait> }
}
+++ /dev/null
-// Copyright 2012 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.
-
-// Test that a type whose lifetime parameters is never used is
-// inferred to be bivariant.
-
-use std::marker;
-
-struct Bivariant<'a>;
-
-fn use1<'short,'long>(c: Bivariant<'short>,
- _where:Option<&'short &'long ()>) {
- let _: Bivariant<'long> = c;
-}
-
-fn use2<'short,'long>(c: Bivariant<'long>,
- _where:Option<&'short &'long ()>) {
- let _: Bivariant<'short> = c;
-}
-
-pub fn main() {}
--- /dev/null
+// Copyright 2015 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.
+
+// Regression test for issue #21422, which was related to failing to
+// add inference constraints that the operands of a binary operator
+// should outlive the binary operation itself.
+
+pub struct P<'a> {
+ _ptr: *const &'a u8,
+}
+
+impl <'a> PartialEq for P<'a> {
+ fn eq(&self, other: &P<'a>) -> bool {
+ (self as *const _) == (other as *const _)
+ }
+}
+
+fn main() {}
#![feature(unsafe_destructor)]
-pub struct Foo<T>;
+use std::marker;
+
+pub struct Foo<T>(marker::PhantomData<T>);
impl<T> Iterator for Foo<T> {
type Item = T;
// should not upset the variance inference for actual occurrences of
// that lifetime in type expressions.
-pub trait HasLife<'a> { }
+pub trait HasLife<'a> {
+ fn dummy(&'a self) { } // just to induce a variance on 'a
+}
trait UseLife01 {
fn refs<'a, H: HasLife<'a>>(&'a self) -> H;
}
-pub trait HasType<T> { }
+pub trait HasType<T>
+{
+ fn dummy(&self, t: T) -> T { panic!() }
+}
+
trait UseLife03<T> {
fn refs<'a, H: HasType<&'a T>>(&'a self) -> H;
#[cfg(cannot_use_this_yet)]
fn foo<'a>(map: RefCell<HashMap<&'static str, &'a [u8]>>) {
let one = [1_usize];
- assert_eq!(map.borrow().get("one"), Some(&one[]));
+ assert_eq!(map.borrow().get("one"), Some(&one[..]));
}
#[cfg(cannot_use_this_yet_either)]
let one = [1u8];
let two = [2u8];
let mut map = HashMap::new();
- map.insert("zero", &zer[]);
- map.insert("one", &one[]);
- map.insert("two", &two[]);
+ map.insert("zero", &zer[..]);
+ map.insert("one", &one[..]);
+ map.insert("two", &two[..]);
let map = RefCell::new(map);
foo(map);
}
let test_file = &old_path.join("temp.txt");
/* Write the temp input file */
- let fromp = CString::from_slice(test_file.as_vec());
- let modebuf = CString::from_slice(b"w+b");
+ let fromp = CString::new(test_file.as_vec()).unwrap();
+ let modebuf = CString::new(b"w+b").unwrap();
let ostream = libc::fopen(fromp.as_ptr(), modebuf.as_ptr());
assert!((ostream as uint != 0_usize));
let s = "hello".to_string();
- let buf = CString::from_slice(b"hello");
+ let buf = CString::new(b"hello").unwrap();
let write_len = libc::fwrite(buf.as_ptr() as *mut _,
1_usize as libc::size_t,
(s.len() + 1_usize) as libc::size_t,
trait Bar<X> {
fn bar(x: Self, y: &Self, z: Box<Self>) -> Self;
+ fn dummy(&self, x: X) { }
}
impl Bar<int> for Box<Baz<int>> {
use std::collections::HashMap;
use std::borrow::{Cow, IntoCow};
-type SendStr = Cow<'static, String, str>;
+type SendStr = Cow<'static, str>;
pub fn main() {
let mut map: HashMap<SendStr, uint> = HashMap::new();
use self::collections::BTreeMap;
use std::borrow::{Cow, IntoCow};
-type SendStr = Cow<'static, String, str>;
+type SendStr = Cow<'static, str>;
pub fn main() {
let mut map: BTreeMap<SendStr, uint> = BTreeMap::new();
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-
-
-enum opt<T> { none, }
+enum opt<T> { none, some(T) }
pub fn main() {
let x = opt::none::<int>;
- match x { opt::none::<int> => { println!("hello world"); } }
+ match x {
+ opt::none::<int> => { println!("hello world"); }
+ opt::some(_) => { }
+ }
}
#![feature(optin_builtin_traits)]
-use std::marker::Send;
+use std::marker::{MarkerTrait, Send};
struct TestType;
impl TestType {}
-trait TestTrait {}
+trait TestTrait : MarkerTrait {}
impl !Send for TestType {}
-struct TestType2<T>;
+struct TestType2<T>(T);
impl<T> TestType2<T> {}
fn f<T,>(_: T,) {}
-struct Foo<T,>;
+struct Foo<T,>(T);
struct Bar;
let [_, _, .., _,] = [1, 1, 1, 1,];
let [_, _, _.., _,] = [1, 1, 1, 1,];
- let x: Foo<int,> = Foo::<int,>;
+ let x: Foo<int,> = Foo::<int,>(1);
Bar::f(0,);
Bar.g(0,);
// except according to those terms.
-trait Foo {
+trait Foo : ::std::marker::MarkerTrait {
}
fn b(_x: Box<Foo+Send>) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait U {}
-trait T<X: U> {}
+trait U : ::std::marker::MarkerTrait {}
+trait T<X: U> { fn get(self) -> X; }
-trait S2<Y: U> {
+trait S2<Y: U> : ::std::marker::MarkerTrait {
fn m(x: Box<T<Y>+'static>) {}
}
trait I { fn i(&self) -> Self; }
-trait A<T:I> {
+trait A<T:I> : ::std::marker::MarkerTrait {
fn id(x:T) -> T { x.i() }
}
-trait J<T> { fn j(&self) -> Self; }
+trait J<T> { fn j(&self) -> T; }
-trait B<T:J<T>> {
+trait B<T:J<T>> : ::std::marker::MarkerTrait {
fn id(x:T) -> T { x.j() }
}
-trait C {
+trait C : ::std::marker::MarkerTrait {
fn id<T:J<T>>(x:T) -> T { x.j() }
}
trait A<T> {
fn g(&self, x: uint) -> uint { x }
+ fn h(&self, x: T) { }
}
impl<T> A<T> for int { }
static mut COUNT: uint = 1;
-trait T {}
+trait T {
+ fn t(&self) {}
+}
impl<'a> T+'a {
fn foo(&self) {
use std::cmp::{PartialEq, PartialOrd};
use std::num::NumCast;
-pub trait TypeExt {}
-
+pub trait TypeExt : ::std::marker::MarkerTrait { }
impl TypeExt for u8 {}
impl TypeExt for u16 {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-pub trait MyEq { }
+pub trait MyEq : ::std::marker::MarkerTrait { }
-pub trait MyNum {
+pub trait MyNum : ::std::marker::MarkerTrait {
fn from_int(int) -> Self;
}
#![allow(unknown_features)]
#![feature(box_syntax)]
+use std::marker;
+
pub trait Trait2<A> {
- fn doit(&self);
+ fn doit(&self) -> A;
}
pub struct Impl<A1, A2, A3> {
+ m1: marker::PhantomData<(A1,A2,A3)>,
/*
* With A2 we get the ICE:
* task <unnamed> failed at 'index out of bounds: the len is 1 but the index is 1',
impl<A1, A2, A3> Impl<A1, A2, A3> {
pub fn step(&self) {
- self.t.doit()
+ self.t.doit();
}
}
// test for #8601
-enum Type<T> { Constant }
+enum Type<T> { Constant(T) }
trait Trait<K,V> {
fn method(&self,Type<(K,V)>) -> int;
pub fn main() {
let a = box() () as Box<Trait<u8, u8>>;
- assert_eq!(a.method(Type::Constant), 0);
+ assert_eq!(a.method(Type::Constant((1u8, 2u8))), 0);
}
// except according to those terms.
mod base {
- pub trait HasNew<T> {
+ pub trait HasNew {
fn new() -> Self;
}
dummy: (),
}
- impl ::base::HasNew<Foo> for Foo {
+ impl ::base::HasNew for Foo {
fn new() -> Foo {
println!("Foo");
Foo { dummy: () }
dummy: (),
}
- impl ::base::HasNew<Bar> for Bar {
+ impl ::base::HasNew for Bar {
fn new() -> Bar {
println!("Bar");
Bar { dummy: () }
}
pub fn main() {
- let _f: base::Foo = base::HasNew::<base::Foo>::new();
- let _b: base::Bar = base::HasNew::<base::Bar>::new();
+ let _f: base::Foo = base::HasNew::new();
+ let _b: base::Bar = base::HasNew::new();
}
pub trait GraphWalk<'c, N> {
/// Returns all the nodes in this graph.
- fn nodes(&'c self) where [N]:ToOwned<Vec<N>>;
+ fn nodes(&'c self) where [N]:ToOwned<Owned=Vec<N>>;
}
impl<'g> GraphWalk<'g, Node<'g>> for u32
{
- fn nodes(&'g self) where [Node<'g>]:ToOwned<Vec<Node<'g>>>
+ fn nodes(&'g self) where [Node<'g>]:ToOwned<Owned=Vec<Node<'g>>>
{ loop { } }
}
impl<'h> GraphWalk<'h, Node<'h>> for u64
{
- fn nodes(&'h self) where [Node<'h>]:ToOwned<Vec<Node<'h>>>
+ fn nodes(&'h self) where [Node<'h>]:ToOwned<Owned=Vec<Node<'h>>>
{ loop { } }
}
#![feature(core,unboxed_closures)]
-use std::marker::CovariantType;
+use std::marker::PhantomData;
// Test that we are able to infer a suitable kind for a "recursive"
// closure. As far as I can tell, coding up a recursive closure
struct YCombinator<F,A,R> {
func: F,
- marker: CovariantType<(A,R)>,
+ marker: PhantomData<(A,R)>,
}
impl<F,A,R> YCombinator<F,A,R> {
fn new(f: F) -> YCombinator<F,A,R> {
- YCombinator { func: f, marker: CovariantType }
+ YCombinator { func: f, marker: PhantomData }
}
}
#![allow(unknown_features)]
#![feature(box_syntax)]
-pub trait EventLoop { }
+pub trait EventLoop { fn foo(&self) {} }
pub struct UvEventLoop {
uvio: int
// Test syntax checks for `?Sized` syntax.
-trait T1 {}
-pub trait T2 {}
-trait T3<X: T1> : T2 {}
-trait T4<X: ?Sized> {}
-trait T5<X: ?Sized, Y> {}
-trait T6<Y, X: ?Sized> {}
-trait T7<X: ?Sized, Y: ?Sized> {}
-trait T8<X: ?Sized+T2> {}
-trait T9<X: T2 + ?Sized> {}
-struct S1<X: ?Sized>;
-enum E<X: ?Sized> {}
+use std::marker::{PhantomData, PhantomFn};
+
+trait T1 : PhantomFn<Self> { }
+pub trait T2 : PhantomFn<Self> { }
+trait T3<X: T1> : T2 + PhantomFn<X> { }
+trait T4<X: ?Sized> : PhantomFn<(Self,X)> {}
+trait T5<X: ?Sized, Y> : PhantomFn<(Self,X,Y)> {}
+trait T6<Y, X: ?Sized> : PhantomFn<(Self,X,Y)> {}
+trait T7<X: ?Sized, Y: ?Sized> : PhantomFn<(Self,X,Y)> {}
+trait T8<X: ?Sized+T2> : PhantomFn<(Self,X)> {}
+trait T9<X: T2 + ?Sized> : PhantomFn<(Self,X)> {}
+struct S1<X: ?Sized>(PhantomData<X>);
+enum E<X: ?Sized> { E1(PhantomData<X>) }
impl <X: ?Sized> T1 for S1<X> {}
fn f<X: ?Sized>() {}
type TT<T: ?Sized> = T;
// Test sized-ness checking in substitution.
+use std::marker;
+
// Unbounded.
fn f1<X: ?Sized>(x: &X) {
f1::<X>(x);
}
// Bounded.
-trait T {}
+trait T { fn dummy(&self) { } }
fn f3<X: T+?Sized>(x: &X) {
f3::<X>(x);
}
}
trait T4<X> {
- fn m1(x: &T4<X>);
- fn m2(x: &T5<X>);
+ fn dummy(&self) { }
+ fn m1(x: &T4<X>, y: X);
+ fn m2(x: &T5<X>, y: X);
}
trait T5<X: ?Sized> {
+ fn dummy(&self) { }
// not an error (for now)
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
}
trait T6<X: T> {
+ fn dummy(&self) { }
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
}
trait T7<X: ?Sized+T> {
+ fn dummy(&self) { }
// not an error (for now)
fn m1(x: &T4<X>);
fn m2(x: &T5<X>);
unsafe {
// Call with just the named parameter
- let c = CString::from_slice(b"Hello World\n");
+ let c = CString::new(b"Hello World\n").unwrap();
check("Hello World\n", |s| sprintf(s, c.as_ptr()));
// Call with variable number of arguments
- let c = CString::from_slice(b"%d %f %c %s\n");
+ let c = CString::new(b"%d %f %c %s\n").unwrap();
check("42 42.500000 a %d %f %c %s\n\n", |s| {
sprintf(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr());
});
// A function that takes a function pointer
unsafe fn call(p: unsafe extern fn(*mut c_char, *const c_char, ...) -> c_int) {
// Call with just the named parameter
- let c = CString::from_slice(b"Hello World\n");
+ let c = CString::new(b"Hello World\n").unwrap();
check("Hello World\n", |s| sprintf(s, c.as_ptr()));
// Call with variable number of arguments
- let c = CString::from_slice(b"%d %f %c %s\n");
+ let c = CString::new(b"%d %f %c %s\n").unwrap();
check("42 42.500000 a %d %f %c %s\n\n", |s| {
sprintf(s, c.as_ptr(), 42, 42.5f64, 'a' as c_int, c.as_ptr());
});
--- /dev/null
+// Copyright 2015 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.
+
+// Elaborated version of the opening example from RFC 738. This failed
+// to compile before variance because invariance of `Option` prevented
+// us from approximating the lifetimes of `field1` and `field2` to a
+// common intersection.
+
+#![allow(dead_code)]
+
+struct List<'l> {
+ field1: &'l i32,
+ field2: Option<&'l i32>,
+}
+
+fn foo(field1: &i32, field2: Option<&i32>) -> i32 {
+ let list = List { field1: field1, field2: field2 };
+ *list.field1 + list.field2.cloned().unwrap_or(0)
+}
+
+fn main() {
+ let x = 22;
+ let y = Some(3);
+ let z = None;
+ assert_eq!(foo(&x, y.as_ref()), 25);
+ assert_eq!(foo(&x, z.as_ref()), 22);
+}
--- /dev/null
+// Copyright 2015 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.
+
+#![allow(dead_code)]
+
+// Get<T> is covariant in T
+trait Get<T> {
+ fn get(&self) -> T;
+}
+
+struct Cloner<T:Clone> {
+ t: T
+}
+
+impl<T:Clone> Get<T> for Cloner<T> {
+ fn get(&self) -> T {
+ self.t.clone()
+ }
+}
+
+fn get<'a, G>(get: &G) -> i32
+ where G : Get<&'a i32>
+{
+ // This call only type checks if we can use `G : Get<&'a i32>` as
+ // evidence that `G : Get<&'b i32>` where `'a : 'b`.
+ pick(get, &22)
+}
+
+fn pick<'b, G>(get: &'b G, if_odd: &'b i32) -> i32
+ where G : Get<&'b i32>
+{
+ let v = *get.get();
+ if v % 2 != 0 { v } else { *if_odd }
+}
+
+fn main() {
+ let x = Cloner { t: &23 };
+ let y = get(&x);
+ assert_eq!(y, 23);
+}
+
+
--- /dev/null
+// Copyright 2015 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.
+
+// Test that vec is now covariant in its argument type.
+
+#![allow(dead_code)]
+
+fn foo<'a,'b>(v1: Vec<&'a i32>, v2: Vec<&'b i32>) -> i32 {
+ bar(v1, v2).cloned().unwrap_or(0) // only type checks if we can intersect 'a and 'b
+}
+
+fn bar<'c>(v1: Vec<&'c i32>, v2: Vec<&'c i32>) -> Option<&'c i32> {
+ v1.get(0).cloned().or_else(|| v2.get(0).cloned())
+}
+
+fn main() {
+ let x = 22;
+ let y = 44;
+ assert_eq!(foo(vec![&x], vec![&y]), 22);
+ assert_eq!(foo(vec![&y], vec![&x]), 44);
+}
#![feature(visible_private_types)]
-trait Foo {}
+trait Foo { fn dummy(&self) { } }
pub trait Bar : Foo {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Bound {}
+trait Bound {
+ fn dummy(&self) { }
+}
trait Trait {
fn a<T>(&self, T) where T: Bound;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait TheTrait { }
+trait TheTrait { fn dummy(&self) { } }
impl TheTrait for &'static int { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-trait Foo<T> {}
+trait Foo<T> { fn dummy(&self, arg: T) { } }
trait Bar<A> {
fn method<B>(&self) where A: Foo<B>;
impl Foo<S> for X {}
-impl Bar<X> for int {
+impl Bar<X> for i32 {
fn method<U>(&self) where X: Foo<U> {
}
}
// Test that we can quantify lifetimes outside a constraint (i.e., including
// the self type) in a where clause.
+use std::marker::PhantomFn;
+
static mut COUNT: u32 = 1;
-trait Bar<'a> {
+trait Bar<'a>
+ : PhantomFn<&'a ()>
+{
fn bar(&self);
}
-trait Baz<'a> {
+trait Baz<'a>
+ : PhantomFn<&'a ()>
+{
fn baz(&self);
}