From: bors Date: Thu, 19 Feb 2015 18:36:59 +0000 (+0000) Subject: Auto merge of #22541 - Manishearth:rollup, r=Gankro X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=522d09dfecbeca1595f25ac58c6d0178bbd21d7d;hp=0b664bb8436f2cfda7f13a6f302ab486f332816f;p=rust.git Auto merge of #22541 - Manishearth:rollup, r=Gankro Continued from #22520 --- diff --git a/README.md b/README.md index 065c4ed7c7b..b6a73730d35 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,16 @@ # 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 @@ -19,22 +21,14 @@ Read ["Installing Rust"][install] from [The Book][trpl]. * `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 @@ -46,7 +40,10 @@ Read ["Installing Rust"][install] from [The Book][trpl]. 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 @@ -72,9 +69,6 @@ $ pacman -S base-devel $ ./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 @@ -94,9 +88,9 @@ supported build environments that are most likely to work. 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 @@ -114,6 +108,14 @@ The Rust community congregates in a few places: 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 diff --git a/configure b/configure index ec1e741fb9c..d1b27a96f93 100755 --- a/configure +++ b/configure @@ -1056,6 +1056,7 @@ do 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 diff --git a/mk/tests.mk b/mk/tests.mk index d8597724370..692d28bfad3 100644 --- a/mk/tests.mk +++ b/mk/tests.mk @@ -174,12 +174,12 @@ check-notidy: cleantmptestlogs cleantestlibs all check-stage2 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. @@ -291,6 +291,7 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \ 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 \ @@ -470,7 +471,8 @@ RPASS_VALGRIND_TESTS := $(RPASS_VALGRIND_RS) 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) @@ -508,6 +510,11 @@ CTEST_BUILD_BASE_cfail = compile-fail 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 @@ -630,6 +637,7 @@ CTEST_DEPS_rpass-full_$(1)-T-$(2)-H-$(3) = $$(RPASS_FULL_TESTS) $$(CSREQ$(1)_T_$ 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) @@ -698,7 +706,7 @@ endif 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), \ @@ -857,6 +865,7 @@ TEST_GROUPS = \ cfail-full \ rfail \ cfail \ + pfail \ bench \ perf \ rmake \ diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index df2981a6c83..2c046d25279 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -15,6 +15,7 @@ #[derive(Clone, Copy, PartialEq, Debug)] pub enum Mode { CompileFail, + ParseFail, RunFail, RunPass, RunPassValgrind, @@ -29,6 +30,7 @@ impl FromStr for Mode { fn from_str(s: &str) -> Result { match s { "compile-fail" => Ok(CompileFail), + "parse-fail" => Ok(ParseFail), "run-fail" => Ok(RunFail), "run-pass" => Ok(RunPass), "run-pass-valgrind" => Ok(RunPassValgrind), @@ -45,6 +47,7 @@ impl fmt::Display for Mode { 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", diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index 86710d50d8a..278ce5565d9 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -21,6 +21,7 @@ #![feature(test)] #![feature(unicode)] #![feature(env)] +#![feature(core)] #![deny(warnings)] @@ -72,7 +73,7 @@ pub fn parse_config(args: Vec ) -> Config { 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"), diff --git a/src/compiletest/runtest.rs b/src/compiletest/runtest.rs index 658c0cb3f4e..1cbb8742bbc 100644 --- a/src/compiletest/runtest.rs +++ b/src/compiletest/runtest.rs @@ -11,7 +11,7 @@ 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; @@ -66,6 +66,7 @@ pub fn run_metrics(config: Config, testfile: String, mm: &mut MetricMap) { 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), @@ -88,7 +89,7 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) { 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); } @@ -688,7 +689,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path) .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"); @@ -1133,7 +1134,7 @@ fn compile_test_(config: &Config, props: &TestProps, // 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, diff --git a/src/doc/reference.md b/src/doc/reference.md index 70baebf0d30..db940947040 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -572,7 +572,7 @@ the final namespace qualifier is omitted. Two examples of paths with type arguments: ``` -# struct HashMap; +# struct HashMap(K,V); # fn f() { # fn id(t: T) -> T { t } type T = HashMap; // Type arguments used in a type expression @@ -1599,7 +1599,7 @@ pointer values (pointing to a type for which an implementation of the given 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 = Box::new(mycircle) as Box; @@ -1630,8 +1630,8 @@ let x: f64 = Num::from_i32(42); 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 @@ -1725,7 +1725,7 @@ type parameters taken by the trait it implements. Implementation parameters are written after the `impl` keyword. ``` -# trait Seq { } +# trait Seq { fn dummy(&self, _: T) { } } impl Seq for Vec { /* ... */ } @@ -3583,7 +3583,7 @@ An example of each kind: ```{rust} let vec: Vec = 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` easily. The diff --git a/src/doc/trpl/ffi.md b/src/doc/trpl/ffi.md index f2b95f19edc..97e826579fd 100644 --- a/src/doc/trpl/ffi.md +++ b/src/doc/trpl/ffi.md @@ -435,8 +435,8 @@ extern { } 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); @@ -541,6 +541,6 @@ pub extern fn hello_rust() -> *const u8 { 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. diff --git a/src/doc/trpl/patterns.md b/src/doc/trpl/patterns.md index 122cffe3697..9e82e48fd18 100644 --- a/src/doc/trpl/patterns.md +++ b/src/doc/trpl/patterns.md @@ -180,7 +180,7 @@ If you want to match against a slice or array, you can use `&`: fn main() { let v = vec!["match_this", "1"]; - match &v[] { + match &v[..] { ["match_this", second] => println!("The second element is {}", second), _ => {}, } diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 3830d7fe295..934e6ab2159 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -73,7 +73,6 @@ use core::atomic; use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst}; -use core::borrow::BorrowFrom; use core::fmt; use core::cmp::{Ordering}; use core::default::Default; @@ -244,12 +243,6 @@ fn clone(&self) -> Arc { } } -impl BorrowFrom> for T { - fn borrow_from(owned: &Arc) -> &T { - &**owned - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Deref for Arc { type Target = T; @@ -605,11 +598,19 @@ impl Default for Arc { fn default() -> Arc { Arc::new(Default::default()) } } +#[cfg(stage0)] impl> Hash for Arc { fn hash(&self, state: &mut H) { (**self).hash(state) } } +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Arc { + fn hash(&self, state: &mut H) { + (**self).hash(state) + } +} #[cfg(test)] mod tests { diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 340a8d59612..a3516bd667b 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -10,13 +10,14 @@ //! A pointer type for heap allocation. //! -//! `Box`, 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`, 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 //! @@ -58,8 +59,8 @@ 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: /// @@ -219,12 +220,20 @@ fn cmp(&self, other: &Box) -> Ordering { #[stable(feature = "rust1", since = "1.0.0")] impl Eq for Box {} +#[cfg(stage0)] impl> Hash for Box { #[inline] fn hash(&self, state: &mut S) { (**self).hash(state); } } +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Box { + fn hash(&self, state: &mut H) { + (**self).hash(state); + } +} /// Extension methods for an owning `Any` trait object. #[unstable(feature = "alloc", diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index b3c2638f3ae..bc349ebebde 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -73,7 +73,6 @@ #![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))] diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index f361c36ec8f..9d395115431 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -144,13 +144,12 @@ #![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; @@ -349,12 +348,6 @@ pub fn make_unique(&mut self) -> &mut T { } } -impl BorrowFrom> for T { - fn borrow_from(owned: &Rc) -> &T { - &**owned - } -} - #[stable(feature = "rust1", since = "1.0.0")] impl Deref for Rc { type Target = T; @@ -599,12 +592,20 @@ fn cmp(&self, other: &Rc) -> Ordering { (**self).cmp(&**other) } } // FIXME (#18248) Make `T` `Sized?` -impl> Hash for Rc { +#[cfg(stage0)] +impl> Hash for Rc { #[inline] fn hash(&self, state: &mut S) { (**self).hash(state); } } +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for Rc { + fn hash(&self, state: &mut H) { + (**self).hash(state); + } +} #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Display for Rc { diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs index 4cd3d587580..b43f9adfb26 100644 --- a/src/libarena/lib.rs +++ b/src/libarena/lib.rs @@ -96,7 +96,7 @@ pub struct Arena<'longer_than_self> { head: RefCell, copy_head: RefCell, chunks: RefCell>, - _invariant: marker::InvariantLifetime<'longer_than_self>, + _marker: marker::PhantomData<*mut &'longer_than_self()>, } impl<'a> Arena<'a> { @@ -111,7 +111,7 @@ pub fn new_with_size(initial_size: usize) -> 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, } } } @@ -361,6 +361,8 @@ pub struct TypedArena { } struct TypedArenaChunk { + marker: marker::PhantomData, + /// Pointer to the next arena segment. next: *mut TypedArenaChunk, diff --git a/src/libcollections/binary_heap.rs b/src/libcollections/binary_heap.rs index 6196d94b5a6..9f549fd7237 100644 --- a/src/libcollections/binary_heap.rs +++ b/src/libcollections/binary_heap.rs @@ -650,8 +650,8 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {} #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for BinaryHeap { - fn from_iter>(iter: Iter) -> BinaryHeap { - BinaryHeap::from_vec(iter.collect()) + fn from_iter>(iter: I) -> BinaryHeap { + BinaryHeap::from_vec(iter.into_iter().collect()) } } @@ -677,7 +677,8 @@ fn into_iter(self) -> Iter<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl Extend for BinaryHeap { - fn extend>(&mut self, iter: Iter) { + fn extend>(&mut self, iterable: I) { + let iter = iterable.into_iter(); let (lower, _) = iter.size_hint(); self.reserve(lower); diff --git a/src/libcollections/bit.rs b/src/libcollections/bit.rs index 0b762788b20..11c576eab15 100644 --- a/src/libcollections/bit.rs +++ b/src/libcollections/bit.rs @@ -8,13 +8,13 @@ // 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 @@ -25,8 +25,8 @@ // 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. //! @@ -38,17 +38,17 @@ //! [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); @@ -62,7 +62,7 @@ //! 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 @@ -75,7 +75,7 @@ //! } //! 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); //! ``` @@ -94,7 +94,7 @@ use core::ops::Index; use core::slice; use core::{u8, u32, usize}; -use bitv_set; //so meta +use bit_set; //so meta use Vec; @@ -112,7 +112,7 @@ fn reverse_bits(byte: u8) -> u8 { // 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(); @@ -134,9 +134,9 @@ fn match_words <'a,'b>(a: &'a Bitv, b: &'b Bitv) -> (MatchWords<'a>, MatchWords< /// # 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); @@ -158,7 +158,7 @@ fn match_words <'a,'b>(a: &'a Bitv, b: &'b Bitv) -> (MatchWords<'a>, MatchWords< /// ``` #[unstable(feature = "collections", reason = "RFC 509")] -pub struct Bitv { +pub struct BitVec { /// Internal representation of the bit vector storage: Vec, /// The number of valid bits in the internal representation @@ -166,7 +166,7 @@ pub struct Bitv { } // FIXME(Gankro): NopeNopeNopeNopeNope (wait for IndexGet to be a thing) -impl Index for Bitv { +impl Index for BitVec { type Output = bool; #[inline] @@ -202,12 +202,12 @@ fn mask_for_bits(bits: usize) -> u32 { !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(&mut self, other: &Bitv, mut op: F) -> bool where F: FnMut(u32, u32) -> u32 { + fn process(&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()); @@ -235,7 +235,7 @@ fn blocks(&self) -> Blocks { } /// 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 { @@ -245,44 +245,44 @@ fn fix_last_block(&mut self) { } } - /// 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. @@ -290,38 +290,38 @@ pub fn from_elem(nbits: usize, bit: bool) -> Bitv { /// 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) | @@ -334,29 +334,29 @@ pub fn from_bytes(bytes: &[u8]) -> Bitv { 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(len: usize, mut f: F) -> Bitv where F: FnMut(usize) -> bool { - let mut bitv = Bitv::from_elem(len, false); + pub fn from_fn(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. @@ -364,9 +364,9 @@ pub fn from_fn(len: usize, mut f: F) -> Bitv where F: FnMut(usize) -> bool { /// # 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); @@ -396,9 +396,9 @@ pub fn get(&self, i: usize) -> Option { /// # 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); /// ``` @@ -420,14 +420,14 @@ pub fn set(&mut self, i: usize, x: bool) { /// # 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) { @@ -440,14 +440,14 @@ 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) { @@ -468,20 +468,20 @@ 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) } @@ -498,20 +498,20 @@ pub fn union(&mut self, other: &Bitv) -> bool { /// # 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) } @@ -528,27 +528,27 @@ pub fn intersect(&mut self, other: &Bitv) -> bool { /// # 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) } @@ -557,9 +557,9 @@ pub fn difference(&mut self, other: &Bitv) -> bool { /// # 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); @@ -581,15 +581,15 @@ pub fn all(&self) -> bool { /// # 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. @@ -597,9 +597,9 @@ pub fn iter(&self) -> Iter { /// # 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); @@ -614,9 +614,9 @@ pub fn none(&self) -> bool { /// # 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); @@ -628,33 +628,33 @@ pub fn any(&self) -> bool { } /// 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 { - 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) } } @@ -672,19 +672,19 @@ fn bit(bitv: &Bitv, byte: usize, bit: usize) -> u8 { ).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])); @@ -694,7 +694,7 @@ pub fn eq_vec(&self, v: &[bool]) -> bool { 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. @@ -702,9 +702,9 @@ pub fn eq_vec(&self, v: &[bool]) -> bool { /// # 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])); /// ``` @@ -719,7 +719,7 @@ pub fn truncate(&mut self, len: usize) { } /// 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 /// @@ -728,9 +728,9 @@ pub fn truncate(&mut self, len: usize) { /// # 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); @@ -745,7 +745,7 @@ pub fn reserve(&mut self, additional: usize) { } /// 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 @@ -758,9 +758,9 @@ pub fn reserve(&mut self, additional: usize) { /// # 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); @@ -780,9 +780,9 @@ pub fn reserve_exact(&mut self, additional: usize) { /// # 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); /// ``` @@ -792,7 +792,7 @@ pub fn capacity(&self) -> usize { 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 /// @@ -801,9 +801,9 @@ pub fn capacity(&self) -> usize { /// # 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)); @@ -846,14 +846,14 @@ pub fn grow(&mut self, n: usize, value: bool) { 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); @@ -881,9 +881,9 @@ pub fn pop(&mut self) -> Option { /// # 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])); @@ -917,24 +917,25 @@ pub fn clear(&mut self) { } #[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 for Bitv { - fn from_iter>(iterator: I) -> Bitv { - let mut ret = Bitv::new(); - ret.extend(iterator); +impl FromIterator for BitVec { + fn from_iter>(iter: I) -> BitVec { + let mut ret = BitVec::new(); + ret.extend(iter); ret } } #[stable(feature = "rust1", since = "1.0.0")] -impl Extend for Bitv { +impl Extend for BitVec { #[inline] - fn extend>(&mut self, iterator: I) { + fn extend>(&mut self, iterable: I) { + let iterator = iterable.into_iter(); let (min, _) = iterator.size_hint(); self.reserve(min); for element in iterator { @@ -944,37 +945,37 @@ fn extend>(&mut self, iterator: I) { } #[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 { + fn partial_cmp(&self, other: &BitVec) -> Option { 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 })); @@ -984,7 +985,8 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { } #[stable(feature = "rust1", since = "1.0.0")] -impl hash::Hash for Bitv { +#[cfg(stage0)] +impl hash::Hash for BitVec { fn hash(&self, state: &mut S) { self.nbits.hash(state); for elem in self.blocks() { @@ -992,11 +994,21 @@ fn hash(&self, state: &mut S) { } } } +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(stage0))] +impl hash::Hash for BitVec { + fn hash(&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; } @@ -1005,13 +1017,13 @@ fn eq(&self, other: &Bitv) -> bool { } #[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, } @@ -1025,7 +1037,7 @@ fn next(&mut self) -> Option { 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 } @@ -1043,7 +1055,7 @@ impl<'a> DoubleEndedIterator for Iter<'a> { fn next_back(&mut self) -> Option { 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 } @@ -1065,13 +1077,13 @@ fn idx(&mut self, index: usize) -> Option { 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>; @@ -1090,10 +1102,10 @@ fn into_iter(self) -> 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); @@ -1104,8 +1116,8 @@ fn into_iter(self) -> Iter<'a> { /// 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); /// @@ -1114,115 +1126,115 @@ fn into_iter(self) -> Iter<'a> { /// 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 for BitvSet { - fn from_iter>(iterator: I) -> BitvSet { - let mut ret = BitvSet::new(); - ret.extend(iterator); +impl FromIterator for BitSet { + fn from_iter>(iter: I) -> BitSet { + let mut ret = BitSet::new(); + ret.extend(iter); ret } } #[stable(feature = "rust1", since = "1.0.0")] -impl Extend for BitvSet { +impl Extend for BitSet { #[inline] - fn extend>(&mut self, iterator: I) { - for i in iterator { + fn extend>(&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 { + fn partial_cmp(&self, other: &BitSet) -> Option { 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() { @@ -1230,8 +1242,16 @@ pub fn with_capacity(nbits: usize) -> BitvSet { /// } /// ``` #[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 @@ -1240,19 +1260,19 @@ pub fn from_bitv(bitv: Bitv) -> BitvSet { /// # 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. @@ -1261,22 +1281,22 @@ pub fn capacity(&self) -> usize { /// # 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 @@ -1287,17 +1307,17 @@ pub fn reserve_len(&mut self, len: usize) { /// # 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); } } @@ -1307,19 +1327,19 @@ pub fn reserve_len_exact(&mut self, len: usize) { /// # 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. @@ -1327,44 +1347,44 @@ pub fn into_bitv(self) -> Bitv { /// # 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(&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(&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; } } @@ -1373,9 +1393,9 @@ fn other_op(&mut self, other: &BitvSet, mut f: F) where F: FnMut(u32, u32) -> /// # 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); /// @@ -1389,25 +1409,25 @@ fn other_op(&mut self, other: &BitvSet, mut f: F) where F: FnMut(u32, u32) -> #[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() { @@ -1416,7 +1436,7 @@ pub fn shrink_to_fit(&mut self) { /// ``` #[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} } @@ -1426,10 +1446,10 @@ pub fn iter(&self) -> bitv_set::Iter { /// # 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) { @@ -1438,7 +1458,7 @@ pub fn iter(&self) -> bitv_set::Iter { /// ``` #[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 { @@ -1456,10 +1476,10 @@ fn or(w1: u32, w2: u32) -> u32 { w1 | w2 } /// # 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) { @@ -1468,9 +1488,9 @@ fn or(w1: u32, w2: u32) -> u32 { w1 | w2 } /// ``` #[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, @@ -1486,10 +1506,10 @@ fn bitand(w1: u32, w2: u32) -> u32 { w1 & w2 } /// # 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) { @@ -1505,7 +1525,7 @@ fn bitand(w1: u32, w2: u32) -> u32 { w1 & w2 } /// ``` #[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 { @@ -1524,10 +1544,10 @@ fn diff(w1: u32, w2: u32) -> u32 { w1 & !w2 } /// # 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) { @@ -1536,7 +1556,7 @@ fn diff(w1: u32, w2: u32) -> u32 { w1 & !w2 } /// ``` #[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 { @@ -1553,21 +1573,21 @@ fn bitxor(w1: u32, w2: u32) -> u32 { w1 ^ w2 } /// # 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); } @@ -1576,21 +1596,21 @@ pub fn union_with(&mut self, other: &BitvSet) { /// # 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); } @@ -1600,29 +1620,29 @@ pub fn intersect_with(&mut self, other: &BitvSet) { /// # 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); } @@ -1632,21 +1652,21 @@ pub fn difference_with(&mut self, other: &BitvSet) { /// # 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); } @@ -1654,57 +1674,57 @@ pub fn symmetric_difference_with(&mut self, other: &BitvSet) { #[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) } @@ -1717,12 +1737,12 @@ pub fn insert(&mut self, value: usize) -> bool { } // 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; } @@ -1734,16 +1754,16 @@ pub fn remove(&mut self, value: &usize) -> bool { 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 { @@ -1756,27 +1776,37 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { } } -impl hash::Hash for BitvSet { +#[cfg(stage0)] +impl hash::Hash 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(&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 @@ -1796,7 +1826,7 @@ impl<'a> Iterator for SetIter<'a> { type Item = usize; fn next(&mut self) -> Option { - 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; @@ -1810,7 +1840,7 @@ fn next(&mut self) -> Option { #[inline] fn size_hint(&self) -> (usize, Option) { - (0, Some(self.set.bitv.len() - self.next_idx)) + (0, Some(self.set.bit_vec.len() - self.next_idx)) } } @@ -1819,20 +1849,20 @@ impl<'a> Iterator for TwoBitPositions<'a> { type Item = usize; fn next(&mut self) -> Option { - 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); } @@ -1847,7 +1877,7 @@ fn next(&mut self) -> Option { #[inline] fn size_hint(&self) -> (usize, Option) { - 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)) } } @@ -1885,7 +1915,7 @@ impl<'a> Iterator for SymmetricDifference<'a> { } #[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>; @@ -1899,20 +1929,20 @@ mod tests { 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()); @@ -1920,17 +1950,17 @@ fn test_0_elements() { #[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"); @@ -1942,18 +1972,18 @@ fn test_10_elements() { 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); @@ -1963,7 +1993,7 @@ fn test_10_elements() { 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); @@ -1973,7 +2003,7 @@ fn test_10_elements() { 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); @@ -1987,7 +2017,7 @@ fn test_31_elements() { 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, @@ -1995,7 +2025,7 @@ fn test_31_elements() { 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, @@ -2003,7 +2033,7 @@ fn test_31_elements() { 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); @@ -2019,7 +2049,7 @@ fn test_31_elements() { 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); @@ -2035,7 +2065,7 @@ fn test_31_elements() { 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); @@ -2050,7 +2080,7 @@ fn test_31_elements() { 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); @@ -2066,7 +2096,7 @@ fn test_32_elements() { 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, @@ -2074,7 +2104,7 @@ fn test_32_elements() { 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, @@ -2082,7 +2112,7 @@ fn test_32_elements() { 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); @@ -2098,7 +2128,7 @@ fn test_32_elements() { 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); @@ -2114,7 +2144,7 @@ fn test_32_elements() { 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); @@ -2130,7 +2160,7 @@ fn test_32_elements() { 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); @@ -2147,7 +2177,7 @@ fn test_33_elements() { 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, @@ -2155,7 +2185,7 @@ fn test_33_elements() { 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, @@ -2163,7 +2193,7 @@ fn test_33_elements() { 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); @@ -2179,7 +2209,7 @@ fn test_33_elements() { 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); @@ -2195,7 +2225,7 @@ fn test_33_elements() { 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); @@ -2211,7 +2241,7 @@ fn test_33_elements() { 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); @@ -2226,24 +2256,24 @@ fn test_33_elements() { #[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); @@ -2251,12 +2281,12 @@ fn test_equal_sneaky_small() { #[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); } @@ -2266,18 +2296,18 @@ fn test_equal_sneaky_big() { #[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)); @@ -2286,32 +2316,32 @@ fn test_to_bytes() { #[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::>(), bools); + assert_eq!(BitVec::from_bytes(&[0b00100110]).iter().collect::>(), 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::>(), bools); + assert_eq!(bit_vec.iter().collect::>(), 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::>(), long) + let bit_vec: BitVec = long.iter().map(|n| *n).collect(); + assert_eq!(bit_vec.iter().collect::>(), 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); @@ -2324,8 +2354,8 @@ fn test_small_difference() { #[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); @@ -2338,7 +2368,7 @@ fn test_big_difference() { #[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()); @@ -2346,16 +2376,16 @@ fn test_small_clear() { #[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); @@ -2370,8 +2400,8 @@ fn test_bitv_lt() { #[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); @@ -2385,26 +2415,26 @@ fn test_ord() { #[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]); @@ -2412,7 +2442,7 @@ fn test_big_bitv_tests() { 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]); @@ -2420,7 +2450,7 @@ fn test_big_bitv_tests() { 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]); @@ -2430,8 +2460,8 @@ fn test_big_bitv_tests() { } #[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); @@ -2453,29 +2483,29 @@ fn test_bitv_push_pop() { } #[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); @@ -2498,25 +2528,25 @@ fn test_bitv_reserve() { } #[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])); } } @@ -2525,14 +2555,14 @@ fn test_bitv_extend() { #[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; @@ -2544,67 +2574,67 @@ fn rng() -> rand::IsaacRng { #[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; } } @@ -2613,11 +2643,11 @@ fn bench_bitv_small_iter(b: &mut Bencher) { } #[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 @@ -2632,27 +2662,27 @@ fn bench_bitv_big_iter(b: &mut Bencher) { #[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); @@ -2660,14 +2690,14 @@ fn test_bitv_set_from_usizes() { } #[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(); @@ -2675,12 +2705,12 @@ fn test_bitv_set_iterator() { } #[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)); @@ -2689,9 +2719,9 @@ fn test_bitv_set_frombitv_init() { } #[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)); @@ -2702,8 +2732,8 @@ fn test_bitv_masking() { } #[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)); @@ -2717,9 +2747,9 @@ fn test_bitv_set_basic() { } #[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)); @@ -2740,9 +2770,9 @@ fn test_bitv_set_intersection() { } #[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)); @@ -2759,9 +2789,9 @@ fn test_bitv_set_difference() { } #[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)); @@ -2780,9 +2810,9 @@ fn test_bitv_set_symmetric_difference() { } #[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)); @@ -2805,9 +2835,9 @@ fn test_bitv_set_union() { } #[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); @@ -2831,11 +2861,11 @@ fn test_bitv_set_subset() { } #[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)); @@ -2849,19 +2879,19 @@ fn test_bitv_set_is_disjoint() { } #[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); @@ -2870,10 +2900,10 @@ fn test_bitv_set_union_with() { } #[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); @@ -2881,8 +2911,8 @@ fn test_bitv_set_intersect_with() { 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); @@ -2890,8 +2920,8 @@ fn test_bitv_set_intersect_with() { 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); @@ -2900,22 +2930,22 @@ fn test_bitv_set_intersect_with() { } #[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); @@ -2924,27 +2954,27 @@ fn test_bitv_set_difference_with() { } #[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); @@ -2953,10 +2983,10 @@ fn test_bitv_set_symmetric_difference_with() { } #[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); @@ -2967,10 +2997,10 @@ fn test_bitv_set_eq() { } #[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); @@ -2981,8 +3011,8 @@ fn test_bitv_set_cmp() { } #[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)); @@ -2996,8 +3026,8 @@ fn test_bitv_remove() { } #[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)); @@ -3020,14 +3050,14 @@ fn test_bitv_clone() { #[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; @@ -3037,36 +3067,36 @@ fn rng() -> rand::IsaacRng { } #[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 diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs new file mode 100644 index 00000000000..901d7a73b51 --- /dev/null +++ b/src/libcollections/borrow.rs @@ -0,0 +1,316 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A module for working with borrowed data. + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::clone::Clone; +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::hash::{Hash, Hasher}; +use core::marker::Sized; +use core::ops::Deref; +use core::option::Option; + +use fmt; +use alloc::{rc, arc}; + +use self::Cow::*; + +/// A trait for borrowing data. +/// +/// In general, there may be several ways to "borrow" a piece of data. The +/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T` +/// (a mutable borrow). But types like `Vec` provide additional kinds of +/// borrows: the borrowed slices `&[T]` and `&mut [T]`. +/// +/// When writing generic code, it is often desirable to abstract over all ways +/// of borrowing data from a given type. That is the role of the `Borrow` +/// trait: if `T: Borrow`, then `&U` can be borrowed from `&T`. A given +/// type can be borrowed as multiple different types. In particular, `Vec: +/// Borrow>` and `Vec: Borrow<[T]>`. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Borrow { + /// Immutably borrow from an owned value. + #[stable(feature = "rust1", since = "1.0.0")] + fn borrow(&self) -> &Borrowed; +} + +/// A trait for mutably borrowing data. +/// +/// Similar to `Borrow`, but for mutable borrows. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait BorrowMut : Borrow { + /// Mutably borrow from an owned value. + #[stable(feature = "rust1", since = "1.0.0")] + fn borrow_mut(&mut self) -> &mut Borrowed; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow for T { + fn borrow(&self) -> &T { self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BorrowMut for T { + fn borrow_mut(&mut self) -> &mut T { self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> Borrow for &'a T { + fn borrow(&self) -> &T { &**self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> Borrow for &'a mut T { + fn borrow(&self) -> &T { &**self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> BorrowMut for &'a mut T { + fn borrow_mut(&mut self) -> &mut T { &mut **self } +} + +impl Borrow for rc::Rc { + fn borrow(&self) -> &T { &**self } +} + +impl Borrow for arc::Arc { + fn borrow(&self) -> &T { &**self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Borrow for Cow<'a, B> where B: ToOwned, ::Owned: 'a { + fn borrow(&self) -> &B { + &**self + } +} + +/// A generalization of Clone to borrowed data. +/// +/// Some types make it possible to go from borrowed to owned, usually by +/// implementing the `Clone` trait. But `Clone` works only for going from `&T` +/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data +/// from any borrow of a given type. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait ToOwned { + #[stable(feature = "rust1", since = "1.0.0")] + type Owned: Borrow; + + /// Create owned data from borrowed data, usually by copying. + #[stable(feature = "rust1", since = "1.0.0")] + fn to_owned(&self) -> Self::Owned; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for T where T: Clone { + type Owned = T; + fn to_owned(&self) -> T { self.clone() } +} + +/// A clone-on-write smart pointer. +/// +/// The type `Cow` is a smart pointer providing clone-on-write functionality: it +/// can enclose and provide immutable access to borrowed data, and clone the +/// data lazily when mutation or ownership is required. The type is designed to +/// work with general borrowed data via the `Borrow` trait. +/// +/// `Cow` implements both `Deref`, which means that you can call +/// non-mutating methods directly on the data it encloses. If mutation +/// is desired, `to_mut` will obtain a mutable references to an owned +/// value, cloning if necessary. +/// +/// # Example +/// +/// ```rust +/// use std::borrow::Cow; +/// +/// fn abs_all(input: &mut Cow<[int]>) { +/// for i in 0..input.len() { +/// let v = input[i]; +/// if v < 0 { +/// // clones into a vector the first time (if not already owned) +/// input.to_mut()[i] = -v; +/// } +/// } +/// } +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned { + /// Borrowed data. + #[stable(feature = "rust1", since = "1.0.0")] + Borrowed(&'a B), + + /// Owned data. + #[stable(feature = "rust1", since = "1.0.0")] + Owned(::Owned) +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned { + fn clone(&self) -> Cow<'a, B> { + match *self { + Borrowed(b) => Borrowed(b), + Owned(ref o) => { + let b: &B = o.borrow(); + Owned(b.to_owned()) + }, + } + } +} + +impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned { + /// Acquire a mutable reference to the owned form of the data. + /// + /// Copies the data if it is not already owned. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_mut(&mut self) -> &mut ::Owned { + match *self { + Borrowed(borrowed) => { + *self = Owned(borrowed.to_owned()); + self.to_mut() + } + Owned(ref mut owned) => owned + } + } + + /// Extract the owned data. + /// + /// Copies the data if it is not already owned. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_owned(self) -> ::Owned { + match self { + Borrowed(borrowed) => borrowed.to_owned(), + Owned(owned) => owned + } + } + + /// Returns true if this `Cow` wraps a borrowed value + #[deprecated(since = "1.0.0", reason = "match on the enum instead")] + #[unstable(feature = "std_misc")] + pub fn is_borrowed(&self) -> bool { + match *self { + Borrowed(_) => true, + _ => false, + } + } + + /// Returns true if this `Cow` wraps an owned value + #[deprecated(since = "1.0.0", reason = "match on the enum instead")] + #[unstable(feature = "std_misc")] + pub fn is_owned(&self) -> bool { + match *self { + Owned(_) => true, + _ => false, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned { + type Target = B; + + fn deref(&self) -> &B { + match *self { + Borrowed(borrowed) => borrowed, + Owned(ref owned) => owned.borrow() + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned { + #[inline] + fn cmp(&self, other: &Cow<'a, B>) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq> for Cow<'a, B> where + B: PartialEq + ToOwned, C: ToOwned, +{ + #[inline] + fn eq(&self, other: &Cow<'b, C>) -> bool { + PartialEq::eq(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned, +{ + #[inline] + fn partial_cmp(&self, other: &Cow<'a, B>) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where + B: fmt::Debug + ToOwned, + ::Owned: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Debug::fmt(b, f), + Owned(ref o) => fmt::Debug::fmt(o, f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where + B: fmt::Display + ToOwned, + ::Owned: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Display::fmt(b, f), + Owned(ref o) => fmt::Display::fmt(o, f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] +impl<'a, B: ?Sized, S: Hasher> Hash for Cow<'a, B> where B: Hash + ToOwned +{ + #[inline] + fn hash(&self, state: &mut S) { + Hash::hash(&**self, state) + } +} +#[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(&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 + } +} diff --git a/src/libcollections/borrow_stage0.rs b/src/libcollections/borrow_stage0.rs new file mode 100644 index 00000000000..c1d74b16ce6 --- /dev/null +++ b/src/libcollections/borrow_stage0.rs @@ -0,0 +1,313 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! A module for working with borrowed data. + +#![stable(feature = "rust1", since = "1.0.0")] + +use core::clone::Clone; +use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; +use core::hash::{Hash, Hasher}; +use core::marker::Sized; +use core::ops::Deref; +use core::option::Option; + +use fmt; +use alloc::{rc, arc}; + +use self::Cow::*; + +/// A trait for borrowing data. +/// +/// In general, there may be several ways to "borrow" a piece of data. The +/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T` +/// (a mutable borrow). But types like `Vec` provide additional kinds of +/// borrows: the borrowed slices `&[T]` and `&mut [T]`. +/// +/// When writing generic code, it is often desirable to abstract over all ways +/// of borrowing data from a given type. That is the role of the `Borrow` +/// trait: if `T: Borrow`, then `&U` can be borrowed from `&T`. A given +/// type can be borrowed as multiple different types. In particular, `Vec: +/// Borrow>` and `Vec: Borrow<[T]>`. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait Borrow { + /// Immutably borrow from an owned value. + #[stable(feature = "rust1", since = "1.0.0")] + fn borrow(&self) -> &Borrowed; +} + +/// A trait for mutably borrowing data. +/// +/// Similar to `Borrow`, but for mutable borrows. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait BorrowMut : Borrow { + /// Mutably borrow from an owned value. + #[stable(feature = "rust1", since = "1.0.0")] + fn borrow_mut(&mut self) -> &mut Borrowed; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow for T { + fn borrow(&self) -> &T { self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl BorrowMut for T { + fn borrow_mut(&mut self) -> &mut T { self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> Borrow for &'a T { + fn borrow(&self) -> &T { &**self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> Borrow for &'a mut T { + fn borrow(&self) -> &T { &**self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T: ?Sized> BorrowMut for &'a mut T { + fn borrow_mut(&mut self) -> &mut T { &mut **self } +} + +impl Borrow for rc::Rc { + fn borrow(&self) -> &T { &**self } +} + +impl Borrow for arc::Arc { + fn borrow(&self) -> &T { &**self } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Borrow for Cow<'a, B> where B: ToOwned, ::Owned: 'a { + fn borrow(&self) -> &B { + &**self + } +} + +/// A generalization of Clone to borrowed data. +/// +/// Some types make it possible to go from borrowed to owned, usually by +/// implementing the `Clone` trait. But `Clone` works only for going from `&T` +/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data +/// from any borrow of a given type. +#[stable(feature = "rust1", since = "1.0.0")] +pub trait ToOwned { + #[stable(feature = "rust1", since = "1.0.0")] + type Owned: Borrow; + + /// Create owned data from borrowed data, usually by copying. + #[stable(feature = "rust1", since = "1.0.0")] + fn to_owned(&self) -> Self::Owned; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for T where T: Clone { + type Owned = T; + fn to_owned(&self) -> T { self.clone() } +} + +/// A clone-on-write smart pointer. +/// +/// The type `Cow` is a smart pointer providing clone-on-write functionality: it +/// can enclose and provide immutable access to borrowed data, and clone the +/// data lazily when mutation or ownership is required. The type is designed to +/// work with general borrowed data via the `Borrow` trait. +/// +/// `Cow` implements both `Deref`, which means that you can call +/// non-mutating methods directly on the data it encloses. If mutation +/// is desired, `to_mut` will obtain a mutable references to an owned +/// value, cloning if necessary. +/// +/// # Example +/// +/// ```rust +/// use std::borrow::Cow; +/// +/// fn abs_all(input: &mut Cow<[int]>) { +/// for i in 0..input.len() { +/// let v = input[i]; +/// if v < 0 { +/// // clones into a vector the first time (if not already owned) +/// input.to_mut()[i] = -v; +/// } +/// } +/// } +/// ``` +#[stable(feature = "rust1", since = "1.0.0")] +pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned { + /// Borrowed data. + #[stable(feature = "rust1", since = "1.0.0")] + Borrowed(&'a B), + + /// Owned data. + #[stable(feature = "rust1", since = "1.0.0")] + Owned(::Owned) +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned { + fn clone(&self) -> Cow<'a, B> { + match *self { + Borrowed(b) => Borrowed(b), + Owned(ref o) => { + let b: &B = o.borrow(); + Owned(b.to_owned()) + }, + } + } +} + +impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned, ::Owned: 'a { + /// Acquire a mutable reference to the owned form of the data. + /// + /// Copies the data if it is not already owned. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn to_mut(&mut self) -> &mut ::Owned where ::Owned: 'a { + match *self { + Borrowed(borrowed) => { + *self = Owned(borrowed.to_owned()); + self.to_mut() + } + Owned(ref mut owned) => owned + } + } + + /// Extract the owned data. + /// + /// Copies the data if it is not already owned. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn into_owned(self) -> ::Owned { + match self { + Borrowed(borrowed) => borrowed.to_owned(), + Owned(owned) => owned + } + } + + /// Returns true if this `Cow` wraps a borrowed value + #[deprecated(since = "1.0.0", reason = "match on the enum instead")] + #[unstable(feature = "std_misc")] + pub fn is_borrowed(&self) -> bool { + match *self { + Borrowed(_) => true, + _ => false, + } + } + + /// Returns true if this `Cow` wraps an owned value + #[deprecated(since = "1.0.0", reason = "match on the enum instead")] + #[unstable(feature = "std_misc")] + pub fn is_owned(&self) -> bool { + match *self { + Owned(_) => true, + _ => false, + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Deref for Cow<'a, B> where + B: ToOwned, ::Owned: 'a +{ + type Target = B; + + fn deref(&self) -> &B { + match *self { + Borrowed(borrowed) => borrowed, + Owned(ref owned) => owned.borrow() + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned, ::Owned: 'a {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> Ord for Cow<'a, B> where + B: Ord + ToOwned, ::Owned: 'a +{ + #[inline] + fn cmp(&self, other: &Cow<'a, B>) -> Ordering { + Ord::cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq> for Cow<'a, B> where + B: PartialEq + ToOwned, C: ToOwned, + ::Owned: 'a, ::Owned: 'b, +{ + #[inline] + fn eq(&self, other: &Cow<'b, C>) -> bool { + PartialEq::eq(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where + B: PartialOrd + ToOwned, ::Owned: 'a +{ + #[inline] + fn partial_cmp(&self, other: &Cow<'a, B>) -> Option { + PartialOrd::partial_cmp(&**self, &**other) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where + B: fmt::Debug + ToOwned, + ::Owned: fmt::Debug, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Debug::fmt(b, f), + Owned(ref o) => fmt::Debug::fmt(o, f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where + B: fmt::Display + ToOwned, + ::Owned: fmt::Display, +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Borrowed(ref b) => fmt::Display::fmt(b, f), + Owned(ref o) => fmt::Display::fmt(o, f), + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized, S: Hasher> Hash for Cow<'a, B> where + B: Hash + ToOwned, ::Owned: 'a +{ + #[inline] + fn hash(&self, state: &mut S) { + Hash::hash(&**self, state) + } +} + +/// Trait for moving into a `Cow` +#[stable(feature = "rust1", since = "1.0.0")] +pub trait IntoCow<'a, B: ?Sized> where B: ToOwned { + /// Moves `self` into `Cow` + #[stable(feature = "rust1", since = "1.0.0")] + fn into_cow(self) -> Cow<'a, B>; +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned { + fn into_cow(self) -> Cow<'a, B> { + self + } +} diff --git a/src/libcollections/btree/map.rs b/src/libcollections/btree/map.rs index 747211e9238..7823f536c7a 100644 --- a/src/libcollections/btree/map.rs +++ b/src/libcollections/btree/map.rs @@ -19,7 +19,6 @@ use core::prelude::*; -use core::borrow::BorrowFrom; use core::cmp::Ordering; use core::default::Default; use core::fmt::Debug; @@ -29,7 +28,8 @@ 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::*; @@ -75,7 +75,7 @@ pub struct BTreeMap { /// An abstract base over-which all other BTree iterators are built. struct AbsIter { - traversals: RingBuf, + traversals: VecDeque, size: usize, } @@ -208,7 +208,7 @@ pub fn clear(&mut self) { /// assert_eq!(map.get(&2), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn get(&self, key: &Q) -> Option<&V> where Q: BorrowFrom + Ord { + pub fn get(&self, key: &Q) -> Option<&V> where K: Borrow, Q: Ord { let mut cur_node = &self.root; loop { match Node::search(cur_node, key) { @@ -240,7 +240,7 @@ pub fn get(&self, key: &Q) -> Option<&V> where Q: BorrowFrom + Ord /// assert_eq!(map.contains_key(&2), false); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn contains_key(&self, key: &Q) -> bool where Q: BorrowFrom + Ord { + pub fn contains_key(&self, key: &Q) -> bool where K: Borrow, Q: Ord { self.get(key).is_some() } @@ -264,7 +264,7 @@ pub fn contains_key(&self, key: &Q) -> bool where Q: BorrowFrom + /// ``` // See `get` for implementation notes, this is basically a copy-paste with mut's added #[stable(feature = "rust1", since = "1.0.0")] - pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom + Ord { + pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where K: Borrow, Q: Ord { // temp_node is a Borrowck hack for having a mutable value outlive a loop iteration let mut temp_node = &mut self.root; loop { @@ -434,7 +434,7 @@ pub fn insert(&mut self, mut key: K, mut value: V) -> Option { /// assert_eq!(map.remove(&1), None); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn remove(&mut self, key: &Q) -> Option where Q: BorrowFrom + Ord { + pub fn remove(&mut self, key: &Q) -> Option where K: Borrow, Q: Ord { // See `swap` for a more thorough description of the stuff going on in here let mut stack = stack::PartialSearchStack::new(self); loop { @@ -512,13 +512,22 @@ mod stack { 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> { @@ -560,7 +569,7 @@ pub struct SearchStack<'a, K:'a, V:'a, Type, NodeType> { pub struct Pusher<'id, 'a, K:'a, V:'a> { map: &'a mut BTreeMap, stack: Stack, - marker: marker::InvariantLifetime<'id> + _marker: InvariantLifetime<'id>, } impl<'a, K, V> PartialSearchStack<'a, K, V> { @@ -595,11 +604,11 @@ pub fn with FnOnce(Pusher<'id, '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) @@ -826,7 +835,7 @@ pub fn insert(mut self, key: K, val: V) -> &'a mut V { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator<(K, V)> for BTreeMap { - fn from_iter>(iter: T) -> BTreeMap { + fn from_iter>(iter: T) -> BTreeMap { let mut map = BTreeMap::new(); map.extend(iter); map @@ -836,13 +845,14 @@ fn from_iter>(iter: T) -> BTreeMap { #[stable(feature = "rust1", since = "1.0.0")] impl Extend<(K, V)> for BTreeMap { #[inline] - fn extend>(&mut self, iter: T) { + fn extend>(&mut self, iter: T) { for (k, v) in iter { self.insert(k, v); } } } +#[cfg(stage0)] #[stable(feature = "rust1", since = "1.0.0")] impl, V: Hash> Hash for BTreeMap { fn hash(&self, state: &mut S) { @@ -851,6 +861,15 @@ fn hash(&self, state: &mut S) { } } } +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +impl Hash for BTreeMap { + fn hash(&self, state: &mut H) { + for elt in self { + elt.hash(state); + } + } +} #[stable(feature = "rust1", since = "1.0.0")] impl Default for BTreeMap { @@ -903,7 +922,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { #[stable(feature = "rust1", since = "1.0.0")] impl Index for BTreeMap - where Q: BorrowFrom + Ord + where K: Borrow, Q: Ord { type Output = V; @@ -914,7 +933,7 @@ fn index(&self, key: &Q) -> &V { #[stable(feature = "rust1", since = "1.0.0")] impl IndexMut for BTreeMap - where Q: BorrowFrom + Ord + where K: Borrow, Q: Ord { fn index_mut(&mut self, key: &Q) -> &mut V { self.get_mut(key).expect("no entry found for key") @@ -1189,7 +1208,7 @@ impl BTreeMap { pub fn iter(&self) -> Iter { 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 { @@ -1221,7 +1240,7 @@ pub fn iter(&self) -> Iter { #[stable(feature = "rust1", since = "1.0.0")] pub fn iter_mut(&mut self) -> IterMut { 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 { @@ -1250,7 +1269,7 @@ pub fn iter_mut(&mut self) -> IterMut { #[stable(feature = "rust1", since = "1.0.0")] pub fn into_iter(self) -> IntoIter { let len = self.len(); - let mut lca = RingBuf::new(); + let mut lca = VecDeque::new(); lca.push_back(Traverse::traverse(self.root)); IntoIter { inner: AbsIter { @@ -1342,7 +1361,7 @@ macro_rules! range_impl { // 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; diff --git a/src/libcollections/btree/node.rs b/src/libcollections/btree/node.rs index 24523d4dcc9..f0fc12da727 100644 --- a/src/libcollections/btree/node.rs +++ b/src/libcollections/btree/node.rs @@ -18,13 +18,15 @@ 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 { @@ -57,8 +59,8 @@ pub struct Node { keys: Unique, vals: Unique, - // In leaf nodes, this will be null, and no space will be allocated for edges. - edges: Unique>, + // In leaf nodes, this will be None, and no space will be allocated for edges. + edges: Option>>, // 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. @@ -278,8 +280,11 @@ fn drop(&mut self) { #[unsafe_destructor] impl Drop for Node { 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; } @@ -292,7 +297,7 @@ fn drop(&mut self) { self.destroy(); } - self.keys.ptr = ptr::null_mut(); + self.keys = unsafe { Unique::new(0 as *mut K) }; } } @@ -308,9 +313,9 @@ unsafe fn new_internal(capacity: usize) -> Node { let (vals_offset, edges_offset) = calculate_offsets_generic::(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), + 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)), _len: 0, _capacity: capacity, } @@ -326,9 +331,9 @@ fn new_leaf(capacity: usize) -> Node { let (vals_offset, _) = calculate_offsets_generic::(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, } @@ -337,18 +342,18 @@ fn new_leaf(capacity: usize) -> Node { unsafe fn destroy(&mut self) { let (alignment, size) = calculate_allocation_generic::(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() }) )} @@ -367,8 +372,12 @@ pub fn as_slices_internal<'b>(&'b self) -> NodeSlice<'b, K, V> { &[] } else { unsafe { + let data = match self.edges { + None => heap::EMPTY as *const Node, + Some(ref p) => **p as *const Node, + }; mem::transmute(raw::Slice { - data: self.edges.ptr, + data: data, len: self.len() + 1 }) } @@ -524,7 +533,8 @@ fn clone(&self) -> Node { #[derive(Copy)] pub struct Handle { node: NodeRef, - index: usize + index: usize, + marker: PhantomData<(Type, NodeType)>, } pub mod handle { @@ -543,13 +553,13 @@ impl Node { /// `Found` will be yielded with the matching index. If it doesn't find an exact match, /// `GoDown` will be yielded with the index of the subtree the key must lie in. pub fn search>>(node: NodeRef, key: &Q) - -> SearchResult where Q: BorrowFrom + Ord { + -> SearchResult where K: Borrow, Q: Ord { // FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V). // For the B configured as of this writing (B = 6), binary search was *significantly* // worse for usizes. 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 }), } } } @@ -586,7 +596,7 @@ pub fn capacity(&self) -> usize { /// 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 @@ -618,7 +628,8 @@ impl Handle where pub fn as_raw(&mut self) -> Handle<*mut Node, Type, NodeType> { Handle { node: &mut *self.node as *mut _, - index: self.index + index: self.index, + marker: PhantomData, } } } @@ -630,7 +641,8 @@ impl Handle<*mut Node, Type, NodeType> { pub unsafe fn from_raw<'a>(&'a self) -> Handle<&'a Node, Type, NodeType> { Handle { node: &*self.node, - index: self.index + index: self.index, + marker: PhantomData, } } @@ -640,7 +652,8 @@ pub unsafe fn from_raw<'a>(&'a self) -> Handle<&'a Node, Type, NodeType> { pub unsafe fn from_raw_mut<'a>(&'a mut self) -> Handle<&'a mut Node, Type, NodeType> { Handle { node: &mut *self.node, - index: self.index + index: self.index, + marker: PhantomData, } } } @@ -688,12 +701,14 @@ pub fn force(self) -> ForceResult { 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, }) } } @@ -826,7 +841,8 @@ impl Handle where unsafe fn left_kv<'a>(&'a mut self) -> Handle<&'a mut Node, handle::KV, NodeType> { Handle { node: &mut *self.node, - index: self.index - 1 + index: self.index - 1, + marker: PhantomData, } } @@ -836,7 +852,8 @@ unsafe fn left_kv<'a>(&'a mut self) -> Handle<&'a mut Node, handle::KV, No unsafe fn right_kv<'a>(&'a mut self) -> Handle<&'a mut Node, handle::KV, NodeType> { Handle { node: &mut *self.node, - index: self.index + index: self.index, + marker: PhantomData, } } } @@ -876,7 +893,8 @@ pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) { pub fn into_left_edge(self) -> Handle<&'a mut Node, handle::Edge, NodeType> { Handle { node: &mut *self.node, - index: self.index + index: self.index, + marker: PhantomData, } } } @@ -926,7 +944,8 @@ impl Handle where pub fn left_edge<'a>(&'a mut self) -> Handle<&'a mut Node, handle::Edge, NodeType> { Handle { node: &mut *self.node, - index: self.index + index: self.index, + marker: PhantomData, } } @@ -935,7 +954,8 @@ pub fn left_edge<'a>(&'a mut self) -> Handle<&'a mut Node, handle::Edge, N pub fn right_edge<'a>(&'a mut self) -> Handle<&'a mut Node, handle::Edge, NodeType> { Handle { node: &mut *self.node, - index: self.index + 1 + index: self.index + 1, + marker: PhantomData, } } } @@ -1044,7 +1064,8 @@ pub fn kv_handle(&mut self, index: usize) -> Handle<&mut Node, handle::KV, debug_assert!(index < self.len(), "kv_handle index out of bounds"); Handle { node: self, - index: index + index: index, + marker: PhantomData, } } @@ -1064,7 +1085,7 @@ pub fn into_iter(self) -> MoveTraversal { 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() }, @@ -1491,9 +1512,9 @@ macro_rules! node_slice_impl { impl<'a, K: Ord + 'a, V: 'a> $NodeSlice<'a, K, V> { /// Performs linear search in a slice. Returns a tuple of (index, is_exact_match). fn search_linear(&self, key: &Q) -> (usize, bool) - where Q: BorrowFrom + Ord { + where K: Borrow, Q: Ord { for (i, k) in self.keys.iter().enumerate() { - match key.cmp(BorrowFrom::borrow_from(k)) { + match key.cmp(k.borrow()) { Greater => {}, Equal => return (i, true), Less => return (i, false), diff --git a/src/libcollections/btree/set.rs b/src/libcollections/btree/set.rs index 7ef887b70cc..929b2f58043 100644 --- a/src/libcollections/btree/set.rs +++ b/src/libcollections/btree/set.rs @@ -13,7 +13,6 @@ use core::prelude::*; -use core::borrow::BorrowFrom; use core::cmp::Ordering::{self, Less, Greater, Equal}; use core::default::Default; use core::fmt::Debug; @@ -21,6 +20,7 @@ use core::iter::{Peekable, Map, FromIterator, IntoIterator}; use core::ops::{BitOr, BitAnd, BitXor, Sub}; +use borrow::Borrow; use btree_map::{BTreeMap, Keys}; use Bound; @@ -336,7 +336,7 @@ pub fn clear(&mut self) { /// assert_eq!(set.contains(&4), false); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn contains(&self, value: &Q) -> bool where Q: BorrowFrom + Ord { + pub fn contains(&self, value: &Q) -> bool where T: Borrow, Q: Ord { self.map.contains_key(value) } @@ -466,14 +466,14 @@ pub fn insert(&mut self, value: T) -> bool { /// assert_eq!(set.remove(&2), false); /// ``` #[stable(feature = "rust1", since = "1.0.0")] - pub fn remove(&mut self, value: &Q) -> bool where Q: BorrowFrom + Ord { + pub fn remove(&mut self, value: &Q) -> bool where T: Borrow, Q: Ord { self.map.remove(value).is_some() } } #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for BTreeSet { - fn from_iter>(iter: Iter) -> BTreeSet { + fn from_iter>(iter: I) -> BTreeSet { let mut set = BTreeSet::new(); set.extend(iter); set @@ -503,7 +503,7 @@ fn into_iter(self) -> Iter<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl Extend for BTreeSet { #[inline] - fn extend>(&mut self, iter: Iter) { + fn extend>(&mut self, iter: Iter) { for elem in iter { self.insert(elem); } diff --git a/src/libcollections/dlist.rs b/src/libcollections/dlist.rs deleted file mode 100644 index eb1bf93c0aa..00000000000 --- a/src/libcollections/dlist.rs +++ /dev/null @@ -1,1505 +0,0 @@ -// 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 or the MIT license -// , 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 { - length: usize, - list_head: Link, - list_tail: Rawlink>, -} - -type Link = Option>>; - -struct Rawlink { - p: *mut T, -} - -impl Copy for Rawlink {} -unsafe impl Send for Rawlink {} -unsafe impl Sync for Rawlink {} - -struct Node { - next: Link, - prev: Rawlink>, - 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, - tail: Rawlink>, - 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, - head: Rawlink>, - tail: Rawlink>, - 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 { - list: DList -} - -/// Rawlink is a type like Option but for holding a raw pointer -impl Rawlink { - /// Like Option::None for Rawlink - fn none() -> Rawlink { - Rawlink{p: ptr::null_mut()} - } - - /// Like Option::Some for Rawlink - fn some(n: &mut T) -> Rawlink { - 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 { - mem::replace(self, Rawlink::none()) - } -} - -impl Clone for Rawlink { - #[inline] - fn clone(&self) -> Rawlink { - Rawlink{p: self.p} - } -} - -impl Node { - fn new(v: T) -> Node { - Node{value: v, next: None, prev: Rawlink::none()} - } -} - -/// Set the .prev field on `next`, then return `Some(next)` -fn link_with_prev(mut next: Box>, prev: Rawlink>) - -> Link { - next.prev = prev; - Some(next) -} - -// private methods -impl DList { - /// Add a Node first in the list - #[inline] - fn push_front_node(&mut self, mut new_head: Box>) { - 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>> { - 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>) { - 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>> { - 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 Default for DList { - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - fn default() -> DList { DList::new() } -} - -impl DList { - /// Creates an empty `DList`. - #[inline] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> DList { - 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) { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 Drop for DList { - 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> - 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) { - (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) { - (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>) { - // 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 Iterator for IntoIter { - type Item = A; - - #[inline] - fn next(&mut self) -> Option { self.list.pop_front() } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - (self.list.length, Some(self.list.length)) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for IntoIter { - #[inline] - fn next_back(&mut self) -> Option { self.list.pop_back() } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl FromIterator for DList { - fn from_iter>(iterator: T) -> DList { - let mut ret = DList::new(); - ret.extend(iterator); - ret - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for DList { - type Item = T; - type IntoIter = IntoIter; - - fn into_iter(self) -> IntoIter { - self.into_iter() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a DList { - 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 { - 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 Extend for DList { - fn extend>(&mut self, iterator: T) { - for elt in iterator { self.push_back(elt); } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for DList { - fn eq(&self, other: &DList) -> bool { - self.len() == other.len() && - iter::order::eq(self.iter(), other.iter()) - } - - fn ne(&self, other: &DList) -> bool { - self.len() != other.len() || - iter::order::ne(self.iter(), other.iter()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for DList {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for DList { - fn partial_cmp(&self, other: &DList) -> Option { - iter::order::partial_cmp(self.iter(), other.iter()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Ord for DList { - #[inline] - fn cmp(&self, other: &DList) -> Ordering { - iter::order::cmp(self.iter(), other.iter()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for DList { - fn clone(&self) -> DList { - self.iter().map(|x| x.clone()).collect() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for DList { - 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> Hash for DList { - 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(list: &DList) { - let mut len = 0; - let mut last_ptr: Option<&Node> = None; - let mut node_ptr: &Node; - 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, pptr as *const Node); - } - _ => 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 { - list_from(&[0,1,2,3,4,5,6]) - } - - #[cfg(test)] - fn list_from(v: &[T]) -> DList { - v.iter().map(|x| (*x).clone()).collect() - } - - #[test] - fn test_append() { - // Empty to empty - { - let mut m = DList::::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![-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::>()); - }).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); - }) - } -} diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index d5403ca5d9b..0c957426060 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -14,6 +14,7 @@ //! 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}; @@ -26,7 +27,8 @@ pub struct EnumSet { // We must maintain the invariant that no bits are set // for which no variant exists - bits: usize + bits: usize, + marker: marker::PhantomData, } impl Copy for EnumSet {} @@ -86,7 +88,7 @@ impl EnumSet { #[unstable(feature = "collections", reason = "matches collection reform specification, waiting for dust to settle")] pub fn new() -> EnumSet { - EnumSet {bits: 0} + EnumSet {bits: 0, marker: marker::PhantomData} } /// Returns the number of elements in the given `EnumSet`. @@ -130,12 +132,14 @@ pub fn is_subset(&self, other: &EnumSet) -> bool { /// Returns the union of both `EnumSets`. pub fn union(&self, e: EnumSet) -> EnumSet { - 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) -> EnumSet { - 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 @@ -175,7 +179,7 @@ impl Sub for EnumSet { type Output = EnumSet; fn sub(self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits & !e.bits} + EnumSet {bits: self.bits & !e.bits, marker: marker::PhantomData} } } @@ -183,7 +187,7 @@ impl BitOr for EnumSet { type Output = EnumSet; fn bitor(self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits | e.bits} + EnumSet {bits: self.bits | e.bits, marker: marker::PhantomData} } } @@ -191,7 +195,7 @@ impl BitAnd for EnumSet { type Output = EnumSet; fn bitand(self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits & e.bits} + EnumSet {bits: self.bits & e.bits, marker: marker::PhantomData} } } @@ -199,7 +203,7 @@ impl BitXor for EnumSet { type Output = EnumSet; fn bitxor(self, e: EnumSet) -> EnumSet { - EnumSet {bits: self.bits ^ e.bits} + EnumSet {bits: self.bits ^ e.bits, marker: marker::PhantomData} } } @@ -207,6 +211,7 @@ fn bitxor(self, e: EnumSet) -> EnumSet { pub struct Iter { index: usize, bits: usize, + marker: marker::PhantomData, } // FIXME(#19839) Remove in favor of `#[derive(Clone)]` @@ -215,13 +220,14 @@ fn clone(&self) -> Iter { Iter { index: self.index, bits: self.bits, + marker: marker::PhantomData, } } } impl Iter { fn new(bits: usize) -> Iter { - Iter { index: 0, bits: bits } + Iter { index: 0, bits: bits, marker: marker::PhantomData } } } @@ -250,9 +256,9 @@ fn size_hint(&self) -> (usize, Option) { } impl FromIterator for EnumSet { - fn from_iter>(iterator: I) -> EnumSet { + fn from_iter>(iter: I) -> EnumSet { let mut ret = EnumSet::new(); - ret.extend(iterator); + ret.extend(iter); ret } } @@ -268,8 +274,8 @@ fn into_iter(self) -> Iter { } impl Extend for EnumSet { - fn extend>(&mut self, iterator: I) { - for element in iterator { + fn extend>(&mut self, iter: I) { + for element in iter { self.insert(element); } } diff --git a/src/libcollections/lib.rs b/src/libcollections/lib.rs index cacbf3bce80..6569ab9c05a 100644 --- a/src/libcollections/lib.rs +++ b/src/libcollections/lib.rs @@ -26,7 +26,6 @@ #![feature(box_syntax)] #![feature(box_patterns)] #![feature(core)] -#![feature(hash)] #![feature(staged_api)] #![feature(unboxed_closures)] #![feature(unicode)] @@ -49,17 +48,33 @@ #[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; @@ -71,27 +86,42 @@ 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")] @@ -117,7 +147,6 @@ mod std { #[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}; @@ -143,6 +172,7 @@ mod prelude { pub use unicode::char::CharExt; // from collections. + pub use borrow::IntoCow; pub use slice::SliceConcatExt; pub use string::{String, ToString}; pub use vec::Vec; diff --git a/src/libcollections/linked_list.rs b/src/libcollections/linked_list.rs new file mode 100644 index 00000000000..c142819a518 --- /dev/null +++ b/src/libcollections/linked_list.rs @@ -0,0 +1,1522 @@ +// 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 or the MIT license +// , 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 { + length: usize, + list_head: Link, + list_tail: Rawlink>, +} + +type Link = Option>>; + +struct Rawlink { + p: *mut T, +} + +impl Copy for Rawlink {} +unsafe impl Send for Rawlink {} +unsafe impl Sync for Rawlink {} + +struct Node { + next: Link, + prev: Rawlink>, + 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, + tail: Rawlink>, + 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, + head: Rawlink>, + tail: Rawlink>, + 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 { + list: LinkedList +} + +/// Rawlink is a type like Option but for holding a raw pointer +impl Rawlink { + /// Like Option::None for Rawlink + fn none() -> Rawlink { + Rawlink{p: ptr::null_mut()} + } + + /// Like Option::Some for Rawlink + fn some(n: &mut T) -> Rawlink { + 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 { + mem::replace(self, Rawlink::none()) + } +} + +impl Clone for Rawlink { + #[inline] + fn clone(&self) -> Rawlink { + Rawlink{p: self.p} + } +} + +impl Node { + fn new(v: T) -> Node { + Node{value: v, next: None, prev: Rawlink::none()} + } +} + +/// Set the .prev field on `next`, then return `Some(next)` +fn link_with_prev(mut next: Box>, prev: Rawlink>) + -> Link { + next.prev = prev; + Some(next) +} + +// private methods +impl LinkedList { + /// Add a Node first in the list + #[inline] + fn push_front_node(&mut self, mut new_head: Box>) { + 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>> { + 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>) { + 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>> { + 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 Default for LinkedList { + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + fn default() -> LinkedList { LinkedList::new() } +} + +impl LinkedList { + /// Creates an empty `LinkedList`. + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new() -> LinkedList { + 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) { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 Drop for LinkedList { + 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> + 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) { + (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) { + (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>) { + // 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 Iterator for IntoIter { + type Item = A; + + #[inline] + fn next(&mut self) -> Option { self.list.pop_front() } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + (self.list.length, Some(self.list.length)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { self.list.pop_back() } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for LinkedList { + fn from_iter>(iter: T) -> LinkedList { + let mut ret = DList::new(); + ret.extend(iter); + ret + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for LinkedList { + type Item = T; + type IntoIter = IntoIter; + + fn into_iter(self) -> IntoIter { + self.into_iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> IntoIterator for &'a LinkedList { + 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 { + 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 Extend for LinkedList { + fn extend>(&mut self, iter: T) { + for elt in iter { self.push_back(elt); } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for LinkedList { + fn eq(&self, other: &LinkedList) -> bool { + self.len() == other.len() && + iter::order::eq(self.iter(), other.iter()) + } + + fn ne(&self, other: &LinkedList) -> bool { + self.len() != other.len() || + iter::order::ne(self.iter(), other.iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for LinkedList {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for LinkedList { + fn partial_cmp(&self, other: &LinkedList) -> Option { + iter::order::partial_cmp(self.iter(), other.iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for LinkedList { + #[inline] + fn cmp(&self, other: &LinkedList) -> Ordering { + iter::order::cmp(self.iter(), other.iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for LinkedList { + fn clone(&self) -> LinkedList { + self.iter().cloned().collect() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for LinkedList { + 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> Hash for LinkedList { + 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 Hash for LinkedList { + fn hash(&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(list: &LinkedList) { + let mut len = 0; + let mut last_ptr: Option<&Node> = None; + let mut node_ptr: &Node; + 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, pptr as *const Node); + } + _ => 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 { + list_from(&[0,1,2,3,4,5,6]) + } + + #[cfg(test)] + fn list_from(v: &[T]) -> LinkedList { + v.iter().cloned().collect() + } + + #[test] + fn test_append() { + // Empty to empty + { + let mut m = LinkedList::::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![-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::>()); + }).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); + }) + } +} diff --git a/src/libcollections/ring_buf.rs b/src/libcollections/ring_buf.rs deleted file mode 100644 index 6dcdb21f800..00000000000 --- a/src/libcollections/ring_buf.rs +++ /dev/null @@ -1,2876 +0,0 @@ -// 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 or the MIT license -// , 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 { - // 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 Send for RingBuf {} - -#[stable(feature = "rust1", since = "1.0.0")] -unsafe impl Sync for RingBuf {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for RingBuf { - fn clone(&self) -> RingBuf { - self.iter().cloned().collect() - } -} - -#[unsafe_destructor] -#[stable(feature = "rust1", since = "1.0.0")] -impl Drop for RingBuf { - fn drop(&mut self) { - self.clear(); - unsafe { - if mem::size_of::() != 0 { - heap::deallocate(self.ptr as *mut u8, - self.cap * mem::size_of::(), - mem::min_align_of::()) - } - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Default for RingBuf { - #[inline] - fn default() -> RingBuf { RingBuf::new() } -} - -impl RingBuf { - /// 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 RingBuf { - /// Creates an empty `RingBuf`. - #[stable(feature = "rust1", since = "1.0.0")] - pub fn new() -> RingBuf { - 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 { - // +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::()) - .expect("capacity overflow"); - - let ptr = if mem::size_of::() != 0 { - unsafe { - let ptr = heap::allocate(size, mem::min_align_of::()) 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 = 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 = 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 = 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::() != 0 { - let old = self.cap * mem::size_of::(); - let new = count.checked_mul(mem::size_of::()) - .expect("capacity overflow"); - unsafe { - self.ptr = heap::reallocate(self.ptr as *mut u8, - old, - new, - mem::min_align_of::()) 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::() != 0 { - let old = self.cap * mem::size_of::(); - let new_size = target_cap * mem::size_of::(); - unsafe { - self.ptr = heap::reallocate(self.ptr as *mut u8, - old, - new_size, - mem::min_align_of::()) 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::>().as_slice(), b); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter(&self) -> Iter { - 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::>()[], b); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn iter_mut(&mut self) -> IterMut { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 RingBuf { - /// 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) { - 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) { - 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 { - inner: RingBuf, -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for IntoIter { - type Item = T; - - #[inline] - fn next(&mut self) -> Option { - self.inner.pop_front() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - let len = self.inner.len(); - (len, Some(len)) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl DoubleEndedIterator for IntoIter { - #[inline] - fn next_back(&mut self) -> Option { - self.inner.pop_back() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl ExactSizeIterator for IntoIter {} - -/// 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, -} - -#[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 { - self.inner.pop_front() - } - - #[inline] - fn size_hint(&self) -> (usize, Option) { - 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 { - 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 PartialEq for RingBuf { - fn eq(&self, other: &RingBuf) -> bool { - self.len() == other.len() && - self.iter().zip(other.iter()).all(|(a, b)| a.eq(b)) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for RingBuf {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for RingBuf { - fn partial_cmp(&self, other: &RingBuf) -> Option { - iter::order::partial_cmp(self.iter(), other.iter()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl Ord for RingBuf { - #[inline] - fn cmp(&self, other: &RingBuf) -> Ordering { - iter::order::cmp(self.iter(), other.iter()) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl> Hash for RingBuf { - 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 Index for RingBuf { - 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 IndexMut for RingBuf { - #[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 FromIterator for RingBuf { - fn from_iter>(iterator: T) -> RingBuf { - let (lower, _) = iterator.size_hint(); - let mut deq = RingBuf::with_capacity(lower); - deq.extend(iterator); - deq - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for RingBuf { - type Item = T; - type IntoIter = IntoIter; - - fn into_iter(self) -> IntoIter { - self.into_iter() - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> IntoIterator for &'a RingBuf { - 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 { - 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 Extend for RingBuf { - fn extend>(&mut self, iterator: T) { - for elt in iterator { - self.push_back(elt); - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for RingBuf { - 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(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 = 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::::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::::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 { - 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::(5, 72, 64, 175); - } - - #[test] - fn test_param_taggy() { - test_parameterized::(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42)); - } - - #[test] - fn test_param_taggypar() { - test_parameterized::>(Onepar::(1), - Twopar::(1, 2), - Threepar::(1, 2, 3), - Twopar::(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::(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!(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::>(), 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::>(), 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::>(), 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::>(), 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![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 = 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::>(), 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::>(), 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 = 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::>(), [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::>(), [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 = 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 = 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![]); - } -} diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 06ae8127c00..776b8b3af14 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -88,7 +88,6 @@ #![stable(feature = "rust1", since = "1.0.0")] use alloc::boxed::Box; -use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned}; use core::clone::Clone; use core::cmp::Ordering::{self, Greater, Less}; use core::cmp::{self, Ord, PartialEq}; @@ -105,6 +104,7 @@ use core::slice as core_slice; use self::Direction::*; +use borrow::{Borrow, BorrowMut, ToOwned}; use vec::Vec; pub use core::slice::{Chunks, AsSlice, Windows}; @@ -1175,18 +1175,19 @@ pub fn new(length: usize) -> ElementSwaps { // Standard trait implementations for slices //////////////////////////////////////////////////////////////////////////////// -#[unstable(feature = "collections", reason = "trait is unstable")] -impl BorrowFrom> for [T] { - fn borrow_from(owned: &Vec) -> &[T] { &owned[] } +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow<[T]> for Vec { + fn borrow(&self) -> &[T] { &self[..] } } -#[unstable(feature = "collections", reason = "trait is unstable")] -impl BorrowFromMut> for [T] { - fn borrow_from_mut(owned: &mut Vec) -> &mut [T] { &mut owned[] } +#[stable(feature = "rust1", since = "1.0.0")] +impl BorrowMut<[T]> for Vec { + fn borrow_mut(&mut self) -> &mut [T] { &mut self[..] } } -#[unstable(feature = "collections", reason = "trait is unstable")] -impl ToOwned> for [T] { +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for [T] { + type Owned = Vec; fn to_owned(&self) -> Vec { self.to_vec() } } @@ -1743,7 +1744,7 @@ fn test_slice() { #[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: &[_] = &[]; @@ -2264,15 +2265,15 @@ fn test_permute_fail() { #[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] diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 2d4dc2bcf30..ec0a487acdc 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -55,7 +55,6 @@ use self::RecompositionState::*; use self::DecompositionType::*; -use core::borrow::{BorrowFrom, ToOwned}; use core::char::CharExt; use core::clone::Clone; use core::iter::AdditiveIterator; @@ -68,7 +67,8 @@ 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; @@ -261,7 +261,7 @@ enum RecompositionState { pub struct Recompositions<'a> { iter: Decompositions<'a>, state: RecompositionState, - buffer: RingBuf, + buffer: VecDeque, composee: Option, last_ccc: Option } @@ -386,13 +386,14 @@ macro_rules! utf8_acc_cont_byte { ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63u8) as u32) } -#[unstable(feature = "collections", reason = "trait is unstable")] -impl BorrowFrom for str { - fn borrow_from(owned: &String) -> &str { &owned[] } +#[stable(feature = "rust1", since = "1.0.0")] +impl Borrow for String { + fn borrow(&self) -> &str { &self[..] } } -#[unstable(feature = "collections", reason = "trait is unstable")] -impl ToOwned for str { +#[stable(feature = "rust1", since = "1.0.0")] +impl ToOwned for str { + type Owned = String; fn to_owned(&self) -> String { unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) @@ -466,7 +467,7 @@ fn replace(&self, from: &str, to: &str) -> String { 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 @@ -480,7 +481,7 @@ fn nfd_chars(&self) -> Decompositions { 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 @@ -496,7 +497,7 @@ fn nfc_chars(&self) -> Recompositions { Recompositions { iter: self.nfd_chars(), state: Composing, - buffer: RingBuf::new(), + buffer: VecDeque::new(), composee: None, last_ccc: None } @@ -511,7 +512,7 @@ fn nfkc_chars(&self) -> Recompositions { Recompositions { iter: self.nfkd_chars(), state: Composing, - buffer: RingBuf::new(), + buffer: VecDeque::new(), composee: None, last_ccc: None } @@ -530,7 +531,7 @@ fn nfkc_chars(&self) -> Recompositions { /// ``` #[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. @@ -547,7 +548,7 @@ fn contains(&self, pat: &str) -> bool { #[unstable(feature = "collections", reason = "might get removed in favour of a more generic contains()")] fn contains_char(&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 @@ -561,7 +562,7 @@ fn contains_char(&self, pat: P) -> bool { /// ``` #[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` @@ -574,13 +575,13 @@ fn chars(&self) -> Chars { /// ``` #[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 @@ -603,7 +604,7 @@ fn char_indices(&self) -> CharIndices { /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn split(&self, pat: P) -> Split

{ - core_str::StrExt::split(&self[], pat) + core_str::StrExt::split(&self[..], pat) } /// An iterator over substrings of `self`, separated by characters @@ -630,7 +631,7 @@ fn split(&self, pat: P) -> Split

{ /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn splitn(&self, count: usize, pat: P) -> SplitN

{ - core_str::StrExt::splitn(&self[], count, pat) + core_str::StrExt::splitn(&self[..], count, pat) } /// An iterator over substrings of `self`, separated by characters @@ -659,7 +660,7 @@ fn splitn(&self, count: usize, pat: P) -> SplitN

{ /// ``` #[unstable(feature = "collections", reason = "might get removed")] fn split_terminator(&self, pat: P) -> SplitTerminator

{ - core_str::StrExt::split_terminator(&self[], pat) + core_str::StrExt::split_terminator(&self[..], pat) } /// An iterator over substrings of `self`, separated by characters @@ -680,7 +681,7 @@ fn split_terminator(&self, pat: P) -> SplitTerminator

{ /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn rsplitn(&self, count: usize, pat: P) -> RSplitN

{ - 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 @@ -706,7 +707,7 @@ fn rsplitn(&self, count: usize, pat: P) -> RSplitN

{ #[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`. @@ -723,7 +724,7 @@ fn match_indices<'a>(&'a self, pat: &'a str) -> MatchIndices<'a> { #[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 @@ -739,7 +740,7 @@ fn split_str<'a>(&'a self, pat: &'a str) -> SplitStr<'a> { /// ``` #[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 @@ -755,7 +756,7 @@ fn lines(&self) -> Lines { /// ``` #[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. @@ -802,7 +803,7 @@ fn lines_any(&self) -> LinesAny { #[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. @@ -813,7 +814,7 @@ fn slice_chars(&self, begin: usize, end: usize) -> &str { /// 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. @@ -825,7 +826,7 @@ unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str { /// ``` #[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. @@ -837,7 +838,7 @@ fn starts_with(&self, pat: &str) -> bool { /// ``` #[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 @@ -857,7 +858,7 @@ fn ends_with(&self, pat: &str) -> bool { /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn trim_matches(&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 @@ -877,7 +878,7 @@ fn trim_matches(&self, pat: P) -> &str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn trim_left_matches(&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 @@ -897,7 +898,7 @@ fn trim_left_matches(&self, pat: P) -> &str { /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn trim_right_matches(&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 @@ -926,7 +927,7 @@ fn trim_right_matches(&self, pat: P) -> &str { #[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 @@ -985,7 +986,7 @@ fn is_char_boundary(&self, index: usize) -> bool { #[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. @@ -1001,7 +1002,7 @@ fn char_range_at(&self, start: usize) -> CharRange { #[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. @@ -1022,7 +1023,7 @@ fn char_range_at_reverse(&self, start: usize) -> CharRange { #[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. @@ -1034,7 +1035,7 @@ fn char_at(&self, i: usize) -> char { #[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. @@ -1046,7 +1047,7 @@ fn char_at_reverse(&self, i: usize) -> char { /// ``` #[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 @@ -1074,7 +1075,7 @@ fn as_bytes(&self) -> &[u8] { /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn find(&self, pat: P) -> Option { - core_str::StrExt::find(&self[], pat) + core_str::StrExt::find(&self[..], pat) } /// Returns the byte index of the last character of `self` that @@ -1102,7 +1103,7 @@ fn find(&self, pat: P) -> Option { /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn rfind(&self, pat: P) -> Option { - core_str::StrExt::rfind(&self[], pat) + core_str::StrExt::rfind(&self[..], pat) } /// Returns the byte index of the first matching substring @@ -1127,7 +1128,7 @@ fn rfind(&self, pat: P) -> Option { #[unstable(feature = "collections", reason = "might get removed in favor of a more generic find in the future")] fn find_str(&self, needle: &str) -> Option { - core_str::StrExt::find_str(&self[], needle) + core_str::StrExt::find_str(&self[..], needle) } /// Retrieves the first character from a string slice and returns @@ -1151,7 +1152,7 @@ fn find_str(&self, needle: &str) -> Option { #[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. @@ -1171,7 +1172,7 @@ fn slice_shift_char(&self) -> Option<(char, &str)> { #[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. @@ -1182,14 +1183,14 @@ fn subslice_offset(&self, inner: &str) -> usize { #[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 @@ -1203,7 +1204,7 @@ fn utf16_units(&self) -> Utf16Units { #[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 @@ -1216,7 +1217,7 @@ fn len(&self) -> usize { #[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. @@ -1230,7 +1231,7 @@ fn is_empty(&self) -> bool { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn parse(&self) -> Result { - core_str::StrExt::parse(&self[]) + core_str::StrExt::parse(&self[..]) } /// Returns an iterator over the @@ -1255,7 +1256,7 @@ fn parse(&self) -> Result { #[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. @@ -1271,7 +1272,7 @@ fn graphemes(&self, is_extended: bool) -> Graphemes { #[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 @@ -1288,7 +1289,7 @@ fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices { #[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 @@ -1303,25 +1304,25 @@ fn words(&self) -> Words { #[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[..]) } } @@ -2704,7 +2705,7 @@ fn test_graphemes() { &["\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())); diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 69fd28d1723..3b179d0b94c 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -16,12 +16,11 @@ 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; @@ -29,6 +28,7 @@ use unicode::str as unicode_str; use unicode::str::Utf16Item; +use borrow::{Cow, IntoCow}; use str::{self, CharRange, FromStr, Utf8Error}; use vec::{DerefVec, Vec, as_vec}; @@ -142,7 +142,7 @@ pub fn from_utf8(vec: Vec) -> Result { /// 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), @@ -709,18 +709,18 @@ fn description(&self) -> &str { "invalid utf-16" } #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for String { - fn from_iter>(iterator: I) -> String { + fn from_iter>(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>(iterator: I) -> String { + fn from_iter>(iter: I) -> String { let mut buf = String::new(); - buf.extend(iterator); + buf.extend(iter); buf } } @@ -728,7 +728,8 @@ fn from_iter>(iterator: I) -> String { #[unstable(feature = "collections", reason = "waiting on Extend stabilization")] impl Extend for String { - fn extend>(&mut self, iterator: I) { + fn extend>(&mut self, iterable: I) { + let iterator = iterable.into_iter(); let (lower_bound, _) = iterator.size_hint(); self.reserve(lower_bound); for ch in iterator { @@ -740,7 +741,8 @@ fn extend>(&mut self, iterator: I) { #[unstable(feature = "collections", reason = "waiting on Extend stabilization")] impl<'a> Extend<&'a str> for String { - fn extend>(&mut self, iterator: I) { + fn extend>(&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); @@ -780,10 +782,10 @@ fn ne(&self, other: &$lhs) -> bool { PartialEq::ne(&**self, &**other) } } impl_eq! { String, &'a str } -impl_eq! { CowString<'a>, String } +impl_eq! { Cow<'a, str>, String } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> PartialEq<&'b str> for CowString<'a> { +impl<'a, 'b> PartialEq<&'b str> for Cow<'a, str> { #[inline] fn eq(&self, other: &&'b str) -> bool { PartialEq::eq(&**self, &**other) } #[inline] @@ -791,11 +793,11 @@ fn ne(&self, other: &&'b str) -> bool { PartialEq::ne(&**self, &**other) } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b> PartialEq> for &'b str { +impl<'a, 'b> PartialEq> for &'b str { #[inline] - fn eq(&self, other: &CowString<'a>) -> bool { PartialEq::eq(&**self, &**other) } + fn eq(&self, other: &Cow<'a, str>) -> bool { PartialEq::eq(&**self, &**other) } #[inline] - fn ne(&self, other: &CowString<'a>) -> bool { PartialEq::ne(&**self, &**other) } + fn ne(&self, other: &Cow<'a, str>) -> bool { PartialEq::ne(&**self, &**other) } } #[unstable(feature = "collections", reason = "waiting on Str stabilization")] @@ -833,12 +835,21 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } #[unstable(feature = "collections", reason = "waiting on Hash stabilization")] +#[cfg(stage0)] impl hash::Hash 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(&self, hasher: &mut H) { + (**self).hash(hasher) + } +} #[unstable(feature = "collections", reason = "recent addition, needs more experience")] @@ -857,7 +868,7 @@ impl ops::Index> for String { type Output = str; #[inline] fn index(&self, index: &ops::Range) -> &str { - &self[][*index] + &self[..][*index] } } #[stable(feature = "rust1", since = "1.0.0")] @@ -865,7 +876,7 @@ impl ops::Index> for String { type Output = str; #[inline] fn index(&self, index: &ops::RangeTo) -> &str { - &self[][*index] + &self[..][*index] } } #[stable(feature = "rust1", since = "1.0.0")] @@ -873,7 +884,7 @@ impl ops::Index> for String { type Output = str; #[inline] fn index(&self, index: &ops::RangeFrom) -> &str { - &self[][*index] + &self[..][*index] } } #[stable(feature = "rust1", since = "1.0.0")] @@ -891,7 +902,7 @@ impl ops::Deref for String { #[inline] fn deref(&self) -> &str { - unsafe { mem::transmute(&self.vec[]) } + unsafe { mem::transmute(&self.vec[..]) } } } @@ -958,31 +969,34 @@ fn to_string(&self) -> String { } } -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] @@ -1287,7 +1301,7 @@ fn insert() { #[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]); diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index bde733644b5..1cc2a5235ab 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -50,24 +50,26 @@ 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` but pronounced 'vector.' /// /// # Examples @@ -137,10 +139,9 @@ #[unsafe_no_drop_flag] #[stable(feature = "rust1", since = "1.0.0")] pub struct Vec { - ptr: NonZero<*mut T>, + ptr: Unique, len: usize, cap: usize, - _own: marker::PhantomData, } unsafe impl Send for Vec { } @@ -249,10 +250,9 @@ pub fn with_capacity(capacity: usize) -> Vec { pub unsafe fn from_raw_parts(ptr: *mut T, length: usize, capacity: usize) -> Vec { Vec { - ptr: NonZero::new(ptr), + ptr: Unique::new(ptr), len: length, cap: capacity, - _own: marker::PhantomData, } } @@ -373,7 +373,7 @@ pub fn shrink_to_fit(&mut self) { self.len * mem::size_of::(), mem::min_align_of::()) as *mut T; if ptr.is_null() { ::alloc::oom() } - self.ptr = NonZero::new(ptr); + self.ptr = Unique::new(ptr); } self.cap = self.len; } @@ -655,7 +655,7 @@ pub fn push(&mut self, value: T) { 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; } @@ -756,7 +756,7 @@ pub fn drain(&mut self) -> Drain { Drain { ptr: begin, end: end, - marker: ContravariantLifetime, + marker: PhantomData, } } } @@ -871,6 +871,8 @@ pub fn map_in_place(self, mut f: F) -> Vec where F: FnMut(T) -> U { end_t: unsafe { start.offset(offset) }, start_u: start as *mut U, end_u: start as *mut U, + + _marker: PhantomData, }; // start_t // start_u @@ -967,8 +969,7 @@ pub fn map_in_place(self, mut f: F) -> Vec where F: FnMut(T) -> U { let mut pv = PartialVecZeroSized:: { num_t: vec.len(), num_u: 0, - marker_t: InvariantType, - marker_u: InvariantType, + marker: PhantomData, }; unsafe { mem::forget(vec); } @@ -1226,7 +1227,7 @@ fn grow_capacity(&mut self, capacity: usize) { unsafe { let ptr = alloc_or_realloc(*self.ptr, self.cap * mem::size_of::(), size); if ptr.is_null() { ::alloc::oom() } - self.ptr = NonZero::new(ptr); + self.ptr = Unique::new(ptr); } self.cap = capacity; } @@ -1302,12 +1303,21 @@ fn clone_from(&mut self, other: &Vec) { } } +#[cfg(stage0)] impl> Hash for Vec { #[inline] fn hash(&self, state: &mut S) { Hash::hash(&**self, state) } } +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(stage0))] +impl Hash for Vec { + #[inline] + fn hash(&self, state: &mut H) { + Hash::hash(&**self, state) + } +} #[stable(feature = "rust1", since = "1.0.0")] impl Index for Vec { @@ -1407,7 +1417,8 @@ fn deref_mut(&mut self) -> &mut [T] { self.as_mut_slice() } #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator for Vec { #[inline] - fn from_iter>(mut iterator: I) -> Vec { + fn from_iter>(iterable: I) -> Vec { + let mut iterator = iterable.into_iter(); let (lower, _) = iterator.size_hint(); let mut vector = Vec::with_capacity(lower); @@ -1480,7 +1491,8 @@ fn into_iter(mut self) -> slice::IterMut<'a, T> { #[unstable(feature = "collections", reason = "waiting on Extend stability")] impl Extend for Vec { #[inline] - fn extend>(&mut self, iterator: I) { + fn extend>(&mut self, iterable: I) { + let iterator = iterable.into_iter(); let (lower, _) = iterator.size_hint(); self.reserve(lower); for element in iterator { @@ -1517,34 +1529,34 @@ fn ne(&self, other: &$lhs) -> bool { PartialEq::ne(&**self, &**other) } impl_eq! { Vec, &'b [B] } impl_eq! { Vec, &'b mut [B] } -impl<'a, A, B> PartialEq> for CowVec<'a, A> where A: PartialEq + Clone { +impl<'a, A, B> PartialEq> for Cow<'a, [A]> where A: PartialEq + Clone { #[inline] fn eq(&self, other: &Vec) -> bool { PartialEq::eq(&**self, &**other) } #[inline] fn ne(&self, other: &Vec) -> bool { PartialEq::ne(&**self, &**other) } } -impl<'a, A, B> PartialEq> for Vec where A: Clone, B: PartialEq { +impl<'a, A, B> PartialEq> for Vec where A: Clone, B: PartialEq { #[inline] - fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) } + fn eq(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::eq(&**self, &**other) } #[inline] - fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) } + fn ne(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::ne(&**self, &**other) } } macro_rules! impl_eq_for_cowvec { ($rhs:ty) => { - impl<'a, 'b, A, B> PartialEq<$rhs> for CowVec<'a, A> where A: PartialEq + Clone { + impl<'a, 'b, A, B> PartialEq<$rhs> for Cow<'a, [A]> where A: PartialEq + Clone { #[inline] fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) } #[inline] fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) } } - impl<'a, 'b, A, B> PartialEq> for $rhs where A: Clone, B: PartialEq { + impl<'a, 'b, A, B> PartialEq> for $rhs where A: Clone, B: PartialEq { #[inline] - fn eq(&self, other: &CowVec<'a, A>) -> bool { PartialEq::eq(&**self, &**other) } + fn eq(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::eq(&**self, &**other) } #[inline] - fn ne(&self, other: &CowVec<'a, A>) -> bool { PartialEq::ne(&**self, &**other) } + fn ne(&self, other: &Cow<'a, [A]>) -> bool { PartialEq::ne(&**self, &**other) } } } } @@ -1552,8 +1564,7 @@ fn ne(&self, other: &CowVec<'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 PartialOrd for Vec { #[inline] fn partial_cmp(&self, other: &Vec) -> Option { @@ -1561,10 +1572,10 @@ fn partial_cmp(&self, other: &Vec) -> Option { } } -#[unstable(feature = "collections", reason = "waiting on Eq stability")] +#[stable(feature = "rust1", since = "1.0.0")] impl Eq for Vec {} -#[unstable(feature = "collections", reason = "waiting on Ord stability")] +#[stable(feature = "rust1", since = "1.0.0")] impl Ord for Vec { #[inline] fn cmp(&self, other: &Vec) -> Ordering { @@ -1587,8 +1598,12 @@ impl AsSlice for Vec { #[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 }) } @@ -1643,26 +1658,26 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Clone-on-write //////////////////////////////////////////////////////////////////////////////// -#[unstable(feature = "collections", - reason = "unclear how valuable this alias is")] /// A clone-on-write vector -pub type CowVec<'a, T> = Cow<'a, Vec, [T]>; +#[deprecated(since = "1.0.0", reason = "use Cow<'a, [T]> instead")] +#[unstable(feature = "collections")] +pub type CowVec<'a, T> = Cow<'a, [T]>; #[unstable(feature = "collections")] -impl<'a, T> FromIterator for CowVec<'a, T> where T: Clone { - fn from_iter>(it: I) -> CowVec<'a, T> { +impl<'a, T> FromIterator for Cow<'a, [T]> where T: Clone { + fn from_iter>(it: I) -> Cow<'a, [T]> { Cow::Owned(FromIterator::from_iter(it)) } } -impl<'a, T: 'a> IntoCow<'a, Vec, [T]> for Vec where T: Clone { - fn into_cow(self) -> CowVec<'a, T> { +impl<'a, T: 'a> IntoCow<'a, [T]> for Vec where T: Clone { + fn into_cow(self) -> Cow<'a, [T]> { Cow::Owned(self) } } -impl<'a, T> IntoCow<'a, Vec, [T]> for &'a [T] where T: Clone { - fn into_cow(self) -> CowVec<'a, T> { +impl<'a, T> IntoCow<'a, [T]> for &'a [T] where T: Clone { + fn into_cow(self) -> Cow<'a, [T]> { Cow::Borrowed(self) } } @@ -1779,10 +1794,10 @@ fn drop(&mut 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")] @@ -1867,9 +1882,9 @@ fn drop(&mut self) { /// Wrapper type providing a `&Vec` reference via `Deref`. #[unstable(feature = "collections")] -pub struct DerefVec<'a, T> { +pub struct DerefVec<'a, T:'a> { x: Vec, - l: ContravariantLifetime<'a> + l: PhantomData<&'a T>, } #[unstable(feature = "collections")] @@ -1897,7 +1912,7 @@ pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> { unsafe { DerefVec { x: Vec::from_raw_parts(x.as_ptr() as *mut T, x.len(), x.len()), - l: ContravariantLifetime::<'a> + l: PhantomData, } } } @@ -1921,6 +1936,8 @@ struct PartialVecNonZeroSized { end_u: *mut U, start_t: *mut T, end_t: *mut T, + + _marker: PhantomData, } /// An owned, partially type-converted vector of zero-sized elements. @@ -1930,8 +1947,7 @@ struct PartialVecNonZeroSized { struct PartialVecZeroSized { num_t: usize, num_u: usize, - marker_t: InvariantType, - marker_u: InvariantType, + marker: PhantomData<::core::cell::Cell<(T,U)>>, } #[unsafe_destructor] @@ -2589,7 +2605,7 @@ fn do_bench_from_slice(b: &mut Bencher, src_len: usize) { 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)); }); diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs new file mode 100644 index 00000000000..3ba22a41ff7 --- /dev/null +++ b/src/libcollections/vec_deque.rs @@ -0,0 +1,2896 @@ +// 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 or the MIT license +// , 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 { + // 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, +} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Send for VecDeque {} + +#[stable(feature = "rust1", since = "1.0.0")] +unsafe impl Sync for VecDeque {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Clone for VecDeque { + fn clone(&self) -> VecDeque { + self.iter().cloned().collect() + } +} + +#[unsafe_destructor] +#[stable(feature = "rust1", since = "1.0.0")] +impl Drop for VecDeque { + fn drop(&mut self) { + self.clear(); + unsafe { + if mem::size_of::() != 0 { + heap::deallocate(*self.ptr as *mut u8, + self.cap * mem::size_of::(), + mem::min_align_of::()) + } + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for VecDeque { + #[inline] + fn default() -> VecDeque { VecDeque::new() } +} + +impl VecDeque { + /// 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 VecDeque { + /// Creates an empty `VecDeque`. + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new() -> VecDeque { + 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 { + // +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::()) + .expect("capacity overflow"); + + let ptr = unsafe { + if mem::size_of::() != 0 { + let ptr = heap::allocate(size, mem::min_align_of::()) 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 = 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 = 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 = 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::() != 0 { + let old = self.cap * mem::size_of::(); + let new = count.checked_mul(mem::size_of::()) + .expect("capacity overflow"); + unsafe { + let ptr = heap::reallocate(*self.ptr as *mut u8, + old, + new, + mem::min_align_of::()) 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::() != 0 { + let old = self.cap * mem::size_of::(); + let new_size = target_cap * mem::size_of::(); + unsafe { + let ptr = heap::reallocate(*self.ptr as *mut u8, + old, + new_size, + mem::min_align_of::()) 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::>().as_slice(), b); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter(&self) -> Iter { + 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::>()[], b); + /// ``` + #[stable(feature = "rust1", since = "1.0.0")] + pub fn iter_mut(&mut self) -> IterMut { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 VecDeque { + /// 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) { + 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) { + 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 { + inner: VecDeque, +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Iterator for IntoIter { + type Item = T; + + #[inline] + fn next(&mut self) -> Option { + self.inner.pop_front() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + let len = self.inner.len(); + (len, Some(len)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl DoubleEndedIterator for IntoIter { + #[inline] + fn next_back(&mut self) -> Option { + self.inner.pop_back() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter {} + +/// 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, +} + +#[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 { + self.inner.pop_front() + } + + #[inline] + fn size_hint(&self) -> (usize, Option) { + 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 { + 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 PartialEq for VecDeque { + fn eq(&self, other: &VecDeque) -> bool { + self.len() == other.len() && + self.iter().zip(other.iter()).all(|(a, b)| a.eq(b)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for VecDeque {} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for VecDeque { + fn partial_cmp(&self, other: &VecDeque) -> Option { + iter::order::partial_cmp(self.iter(), other.iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Ord for VecDeque { + #[inline] + fn cmp(&self, other: &VecDeque) -> Ordering { + iter::order::cmp(self.iter(), other.iter()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(stage0)] +impl> Hash for VecDeque { + 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 Hash for VecDeque { + fn hash(&self, state: &mut H) { + self.len().hash(state); + for elt in self { + elt.hash(state); + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Index for VecDeque { + 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 IndexMut for VecDeque { + #[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 FromIterator for VecDeque { + fn from_iter>(iterable: T) -> VecDeque { + 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 IntoIterator for VecDeque { + type Item = T; + type IntoIter = IntoIter; + + fn into_iter(self) -> IntoIter { + self.into_iter() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T> IntoIterator for &'a VecDeque { + 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 { + 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 Extend for VecDeque { + fn extend>(&mut self, iter: T) { + for elt in iter { + self.push_back(elt); + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for VecDeque { + 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(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 = 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::::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::::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 { + 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::(5, 72, 64, 175); + } + + #[test] + fn test_param_taggy() { + test_parameterized::(One(1), Two(1, 2), Three(1, 2, 3), Two(17, 42)); + } + + #[test] + fn test_param_taggypar() { + test_parameterized::>(Onepar::(1), + Twopar::(1, 2), + Threepar::(1, 2, 3), + Twopar::(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::(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!(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::>(), 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::>(), 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::>(), 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::>(), 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![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 = 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::>(), 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::>(), 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 = 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::>(), [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::>(), [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 = 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 = 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![]); + } +} diff --git a/src/libcollections/vec_map.rs b/src/libcollections/vec_map.rs index 82ccfd0614f..54589a31423 100644 --- a/src/libcollections/vec_map.rs +++ b/src/libcollections/vec_map.rs @@ -20,7 +20,8 @@ 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; @@ -99,6 +100,7 @@ impl Default for VecMap { fn default() -> VecMap { VecMap::new() } } +#[stable(feature = "rust1", since = "1.0.0")] impl Clone for VecMap { #[inline] fn clone(&self) -> VecMap { @@ -111,6 +113,7 @@ fn clone_from(&mut self, source: &VecMap) { } } +#[cfg(stage0)] impl> Hash for VecMap { fn hash(&self, state: &mut S) { // In order to not traverse the `VecMap` twice, count the elements @@ -123,6 +126,20 @@ fn hash(&self, state: &mut S) { count.hash(state); } } +#[stable(feature = "rust1", since = "1.0.0")] +#[cfg(not(stage0))] +impl Hash for VecMap { + fn hash(&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 VecMap { /// Creates an empty `VecMap`. @@ -661,7 +678,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { #[stable(feature = "rust1", since = "1.0.0")] impl FromIterator<(usize, V)> for VecMap { - fn from_iter>(iter: Iter) -> VecMap { + fn from_iter>(iter: I) -> VecMap { let mut map = VecMap::new(); map.extend(iter); map @@ -700,7 +717,7 @@ fn into_iter(mut self) -> IterMut<'a, T> { #[stable(feature = "rust1", since = "1.0.0")] impl Extend<(usize, V)> for VecMap { - fn extend>(&mut self, iter: Iter) { + fn extend>(&mut self, iter: I) { for (k, v) in iter { self.insert(k, v); } @@ -859,7 +876,7 @@ pub struct IntoIter { } #[unstable(feature = "collections")] -pub struct Drain<'a, V> { +pub struct Drain<'a, V:'a> { iter: FilterMap< Enumerate>>, fn((usize, Option)) -> Option<(usize, V)>> diff --git a/src/libcore/array.rs b/src/libcore/array.rs index 838ca4e478b..afb5d95c9f8 100644 --- a/src/libcore/array.rs +++ b/src/libcore/array.rs @@ -17,7 +17,7 @@ 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; @@ -35,16 +35,24 @@ macro_rules! array_impls { } } - impl> Hash for [T; $N] { + #[cfg(stage0)] + impl> Hash 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 Hash for [T; $N] { + fn hash(&self, state: &mut H) { + Hash::hash(&self[..], state) } } #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for [T; $N] { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Debug::fmt(&&self[], f) + fmt::Debug::fmt(&&self[..], f) } } @@ -72,11 +80,11 @@ fn into_iter(self) -> IterMut<'a, T> { impl PartialEq<[B; $N]> for [A; $N] where A: PartialEq { #[inline] fn eq(&self, other: &[B; $N]) -> bool { - &self[] == &other[] + &self[..] == &other[..] } #[inline] fn ne(&self, other: &[B; $N]) -> bool { - &self[] != &other[] + &self[..] != &other[..] } } @@ -87,11 +95,11 @@ fn into_iter(self) -> IterMut<'a, T> { { #[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) } } @@ -102,11 +110,11 @@ fn ne(&self, other: &Rhs) -> bool { { #[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[..]) } } @@ -117,23 +125,23 @@ fn ne(&self, other: &Rhs) -> bool { impl PartialOrd for [T; $N] { #[inline] fn partial_cmp(&self, other: &[T; $N]) -> Option { - 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[..]) } } @@ -141,7 +149,7 @@ fn ne(&self, other: &Rhs) -> bool { impl Ord for [T; $N] { #[inline] fn cmp(&self, other: &[T; $N]) -> Ordering { - Ord::cmp(&&self[], &&other[]) + Ord::cmp(&&self[..], &&other[..]) } } )+ diff --git a/src/libcore/atomic.rs b/src/libcore/atomic.rs index 05d864accc1..6afe5b2257d 100644 --- a/src/libcore/atomic.rs +++ b/src/libcore/atomic.rs @@ -76,6 +76,7 @@ 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")] @@ -105,6 +106,7 @@ unsafe impl Sync for AtomicUsize {} #[stable(feature = "rust1", since = "1.0.0")] pub struct AtomicPtr { p: UnsafeCell, + _marker: PhantomData<*mut T>, } unsafe impl Sync for AtomicPtr {} @@ -791,7 +793,8 @@ impl AtomicPtr { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn new(p: *mut T) -> AtomicPtr { - AtomicPtr { p: UnsafeCell::new(p as usize) } + AtomicPtr { p: UnsafeCell::new(p as usize), + _marker: PhantomData } } /// Loads a value from the pointer. diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs deleted file mode 100644 index 035443e9c3f..00000000000 --- a/src/libcore/borrow.rs +++ /dev/null @@ -1,265 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A module for working with borrowed data. -//! -//! # The `BorrowFrom` traits -//! -//! In general, there may be several ways to "borrow" a piece of data. The -//! typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T` -//! (a mutable borrow). But types like `Vec` provide additional kinds of -//! borrows: the borrowed slices `&[T]` and `&mut [T]`. -//! -//! When writing generic code, it is often desirable to abstract over all ways -//! of borrowing data from a given type. That is the role of the `BorrowFrom` -//! trait: if `T: BorrowFrom`, then `&T` can be borrowed from `&U`. A given -//! type can be borrowed as multiple different types. In particular, `Vec: -//! BorrowFrom>` and `[T]: BorrowFrom>`. -//! -//! # The `ToOwned` trait -//! -//! Some types make it possible to go from borrowed to owned, usually by -//! implementing the `Clone` trait. But `Clone` works only for going from `&T` -//! to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data -//! from any borrow of a given type. -//! -//! # The `Cow` (clone-on-write) type -//! -//! The type `Cow` is a smart pointer providing clone-on-write functionality: it -//! can enclose and provide immutable access to borrowed data, and clone the -//! data lazily when mutation or ownership is required. The type is designed to -//! work with general borrowed data via the `BorrowFrom` trait. -//! -//! `Cow` implements both `Deref`, which means that you can call -//! non-mutating methods directly on the data it encloses. If mutation -//! is desired, `to_mut` will obtain a mutable references to an owned -//! value, cloning if necessary. - -#![unstable(feature = "core", - reason = "recently added as part of collections reform")] - -use clone::Clone; -use cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd}; -use fmt; -use marker::Sized; -use ops::Deref; -use option::Option; -use self::Cow::*; - -/// A trait for borrowing data. -#[old_orphan_check] -pub trait BorrowFrom { - /// Immutably borrow from an owned value. - fn borrow_from(owned: &Owned) -> &Self; -} - -/// A trait for mutably borrowing data. -#[old_orphan_check] -pub trait BorrowFromMut : BorrowFrom { - /// Mutably borrow from an owned value. - fn borrow_from_mut(owned: &mut Owned) -> &mut Self; -} - -impl BorrowFrom for T { - fn borrow_from(owned: &T) -> &T { owned } -} - -impl BorrowFromMut for T { - fn borrow_from_mut(owned: &mut T) -> &mut T { owned } -} - -impl<'a, T: ?Sized> BorrowFrom<&'a T> for T { - fn borrow_from<'b>(owned: &'b &'a T) -> &'b T { &**owned } -} - -impl<'a, T: ?Sized> BorrowFrom<&'a mut T> for T { - fn borrow_from<'b>(owned: &'b &'a mut T) -> &'b T { &**owned } -} - -impl<'a, T: ?Sized> BorrowFromMut<&'a mut T> for T { - fn borrow_from_mut<'b>(owned: &'b mut &'a mut T) -> &'b mut T { &mut **owned } -} - -impl<'a, T, B: ?Sized> BorrowFrom> for B where B: ToOwned { - fn borrow_from<'b>(owned: &'b Cow<'a, T, B>) -> &'b B { - &**owned - } -} - -/// Trait for moving into a `Cow` -#[old_orphan_check] -pub trait IntoCow<'a, T, B: ?Sized> { - /// Moves `self` into `Cow` - fn into_cow(self) -> Cow<'a, T, B>; -} - -impl<'a, T, B: ?Sized> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned { - fn into_cow(self) -> Cow<'a, T, B> { - self - } -} - -/// A generalization of Clone to borrowed data. -#[old_orphan_check] -pub trait ToOwned: BorrowFrom { - /// Create owned data from borrowed data, usually by copying. - fn to_owned(&self) -> Owned; -} - -impl ToOwned for T where T: Clone { - fn to_owned(&self) -> T { self.clone() } -} - -/// A clone-on-write smart pointer. -/// -/// # Example -/// -/// ```rust -/// use std::borrow::Cow; -/// -/// fn abs_all(input: &mut Cow, [int]>) { -/// for i in 0..input.len() { -/// let v = input[i]; -/// if v < 0 { -/// // clones into a vector the first time (if not already owned) -/// input.to_mut()[i] = -v; -/// } -/// } -/// } -/// ``` -pub enum Cow<'a, T, B: ?Sized + 'a> where B: ToOwned { - /// Borrowed data. - Borrowed(&'a B), - - /// Owned data. - Owned(T) -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> Clone for Cow<'a, T, B> where B: ToOwned { - fn clone(&self) -> Cow<'a, T, B> { - match *self { - Borrowed(b) => Borrowed(b), - Owned(ref o) => { - let b: &B = BorrowFrom::borrow_from(o); - Owned(b.to_owned()) - }, - } - } -} - -impl<'a, T, B: ?Sized> Cow<'a, T, B> where B: ToOwned { - /// Acquire a mutable reference to the owned form of the data. - /// - /// Copies the data if it is not already owned. - pub fn to_mut(&mut self) -> &mut T { - match *self { - Borrowed(borrowed) => { - *self = Owned(borrowed.to_owned()); - self.to_mut() - } - Owned(ref mut owned) => owned - } - } - - /// Extract the owned data. - /// - /// Copies the data if it is not already owned. - pub fn into_owned(self) -> T { - match self { - Borrowed(borrowed) => borrowed.to_owned(), - Owned(owned) => owned - } - } - - /// Returns true if this `Cow` wraps a borrowed value - pub fn is_borrowed(&self) -> bool { - match *self { - Borrowed(_) => true, - _ => false, - } - } - - /// Returns true if this `Cow` wraps an owned value - pub fn is_owned(&self) -> bool { - match *self { - Owned(_) => true, - _ => false, - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> Deref for Cow<'a, T, B> where B: ToOwned { - type Target = B; - - fn deref(&self) -> &B { - match *self { - Borrowed(borrowed) => borrowed, - Owned(ref owned) => BorrowFrom::borrow_from(owned) - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> Eq for Cow<'a, T, B> where B: Eq + ToOwned {} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> Ord for Cow<'a, T, B> where B: Ord + ToOwned { - #[inline] - fn cmp(&self, other: &Cow<'a, T, B>) -> Ordering { - Ord::cmp(&**self, &**other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, U, B: ?Sized, C: ?Sized> PartialEq> for Cow<'a, T, B> where - B: PartialEq + ToOwned, - C: ToOwned, -{ - #[inline] - fn eq(&self, other: &Cow<'b, U, C>) -> bool { - PartialEq::eq(&**self, &**other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned { - #[inline] - fn partial_cmp(&self, other: &Cow<'a, T, B>) -> Option { - PartialOrd::partial_cmp(&**self, &**other) - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> fmt::Debug for Cow<'a, T, B> where - B: fmt::Debug + ToOwned, - T: fmt::Debug, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Borrowed(ref b) => fmt::Debug::fmt(b, f), - Owned(ref o) => fmt::Debug::fmt(o, f), - } - } -} - -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, B: ?Sized> fmt::Display for Cow<'a, T, B> where - B: fmt::Display + ToOwned, - T: fmt::Display, -{ - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match *self { - Borrowed(ref b) => fmt::Display::fmt(b, f), - Owned(ref o) => fmt::Display::fmt(o, f), - } - } -} diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index 19ec245300d..b37bad5f754 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -215,7 +215,7 @@ impl Ord for Ordering { #[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)) } } @@ -224,7 +224,7 @@ impl PartialOrd for Ordering { #[inline] #[stable(feature = "rust1", since = "1.0.0")] fn partial_cmp(&self, other: &Ordering) -> Option { - (*self as int).partial_cmp(&(*other as int)) + (*self as i32).partial_cmp(&(*other as i32)) } } @@ -482,7 +482,7 @@ fn ne(&self, _other: &()) -> bool { false } } 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 { @@ -492,7 +492,7 @@ impl Eq for $t {} )*) } - 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)*) => ($( @@ -535,7 +535,7 @@ fn partial_cmp(&self, other: &bool) -> Option { } } - 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)*) => ($( @@ -565,7 +565,7 @@ fn cmp(&self, other: &bool) -> Ordering { } } - 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 diff --git a/src/libcore/default.rs b/src/libcore/default.rs index d79b613f589..7f46d9cbe50 100644 --- a/src/libcore/default.rs +++ b/src/libcore/default.rs @@ -16,7 +16,7 @@ //! //! ``` //! struct SomeOptions { -//! foo: int, +//! foo: i32, //! bar: f32, //! } //! ``` @@ -28,7 +28,7 @@ //! //! #[derive(Default)] //! struct SomeOptions { -//! foo: int, +//! foo: i32, //! bar: f32, //! } //! @@ -56,7 +56,7 @@ //! //! #[derive(Default)] //! struct SomeOptions { -//! foo: int, +//! foo: i32, //! bar: f32, //! baz: Kind, //! } @@ -73,7 +73,7 @@ //! # use std::default::Default; //! # #[derive(Default)] //! # struct SomeOptions { -//! # foo: int, +//! # foo: i32, //! # bar: f32, //! # } //! fn main() { @@ -93,7 +93,7 @@ /// ``` /// #[derive(Default)] /// struct SomeOptions { -/// foo: int, +/// foo: i32, /// bar: f32, /// } /// ``` @@ -113,7 +113,7 @@ pub trait Default { /// /// let i: i8 = Default::default(); /// let (x, y): (Option, 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: @@ -150,13 +150,13 @@ fn default() -> $t { $v } 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 } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 67c8c9fec09..a2c1bbc0331 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -16,7 +16,7 @@ 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}; @@ -914,6 +914,11 @@ fn fmt(&self, f: &mut Formatter) -> Result { f.pad("()") } } +impl Debug for PhantomData { + fn fmt(&self, f: &mut Formatter) -> Result { + f.pad("PhantomData") + } +} #[stable(feature = "rust1", since = "1.0.0")] impl Debug for Cell { diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index a5d2618eff9..2e83334b937 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -35,7 +35,7 @@ //! the trait `Hash`: //! //! ```rust -//! use std::hash::{hash, Hash, Hasher, Writer, SipHasher}; +//! use std::hash::{hash, Hash, Hasher, SipHasher}; //! //! struct Person { //! id: uint, @@ -43,8 +43,8 @@ //! phone: u64, //! } //! -//! impl Hash for Person { -//! fn hash(&self, state: &mut H) { +//! impl Hash for Person { +//! fn hash(&self, state: &mut H) { //! self.id.hash(state); //! self.phone.hash(state); //! } @@ -56,15 +56,12 @@ //! 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; @@ -76,22 +73,123 @@ /// 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(&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(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 { /// 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 @@ -99,6 +197,7 @@ pub trait Hasher { #[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]); } @@ -107,148 +206,292 @@ pub trait Writer { /// /// The specified value will be hashed with this hasher and then the resulting /// hash will be returned. +#[cfg(stage0)] pub fn hash, 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(value: &T) -> u64 { + let mut h: H = Default::default(); + value.hash(&mut h); + h.finish() +} + ////////////////////////////////////////////////////////////////////////////// -macro_rules! impl_hash { - ($ty:ident, $uty:ident) => { - impl Hash 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 Hash 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 Hash 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 Hash for bool { + #[inline] + fn hash(&self, state: &mut S) { + (*self as u8).hash(state); + } } -} -impl Hash for char { - #[inline] - fn hash(&self, state: &mut S) { - (*self as u32).hash(state); + impl Hash for char { + #[inline] + fn hash(&self, state: &mut S) { + (*self as u32).hash(state); + } } -} -impl Hash for str { - #[inline] - fn hash(&self, state: &mut S) { - state.write(self.as_bytes()); - 0xffu8.hash(state) + impl Hash for str { + #[inline] + fn hash(&self, state: &mut S) { + state.write(self.as_bytes()); + 0xffu8.hash(state) + } } -} -macro_rules! impl_hash_tuple { - () => ( - impl Hash for () { - #[inline] - fn hash(&self, _state: &mut S) {} - } - ); - - ( $($name:ident)+) => ( - impl),*> Hash 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 Hash for () { + #[inline] + fn hash(&self, _state: &mut S) {} + } + ); + + ( $($name:ident)+) => ( + impl),*> Hash 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> Hash 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> Hash 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> Hash for &'a T { + #[inline] + fn hash(&self, state: &mut S) { + (**self).hash(state); } } -} + impl<'a, S: Hasher, T: ?Sized + Hash> Hash for &'a mut T { + #[inline] + fn hash(&self, state: &mut S) { + (**self).hash(state); + } + } -impl<'a, S: Hasher, T: ?Sized + Hash> Hash for &'a T { - #[inline] - fn hash(&self, state: &mut S) { - (**self).hash(state); + impl Hash 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> Hash for &'a mut T { - #[inline] - fn hash(&self, state: &mut S) { - (**self).hash(state); + impl Hash 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 Hash 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(&self, state: &mut H) { + state.$meth(*self) + } + + fn hash_slice(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 Hash 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 for Cow<'a, T, B> - where B: Hash + ToOwned -{ - #[inline] - fn hash(&self, state: &mut S) { - Hash::hash(&**self, state) + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for bool { + fn hash(&self, state: &mut H) { + state.write_u8(*self as u8) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for char { + fn hash(&self, state: &mut H) { + state.write_u32(*self as u32) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for str { + fn hash(&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(&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(&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 Hash for [T] { + fn hash(&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(&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(&self, state: &mut H) { + (**self).hash(state); + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for *const T { + fn hash(&self, state: &mut H) { + state.write_usize(*self as usize) + } + } + + #[stable(feature = "rust1", since = "1.0.0")] + impl Hash for *mut T { + fn hash(&self, state: &mut H) { + state.write_usize(*self as usize) + } } } diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index d405d0d28be..ce8917cc205 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -15,7 +15,9 @@ use prelude::*; use default::Default; -use super::{Hasher, Writer}; +use super::Hasher; +#[cfg(stage0)] +use super::Writer; /// An implementation of SipHash 2-4. /// @@ -30,6 +32,7 @@ /// 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, @@ -88,12 +91,14 @@ macro_rules! compress { 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, @@ -114,10 +119,16 @@ pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher { #[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; @@ -164,16 +175,28 @@ fn write(&mut self, msg: &[u8]) { } } +#[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 { @@ -199,6 +222,7 @@ fn finish(&self) -> u64 { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Clone for SipHasher { #[inline] fn clone(&self) -> SipHasher { @@ -216,6 +240,7 @@ fn clone(&self) -> SipHasher { } } +#[stable(feature = "rust1", since = "1.0.0")] impl Default for SipHasher { fn default() -> SipHasher { SipHasher::new() diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 050c144b742..b2ee9596387 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -50,10 +50,10 @@ #[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, @@ -186,15 +186,15 @@ pub struct TyDesc { /// would *exactly* overwrite a value. When laid out in vectors /// and structures there may be additional padding between /// elements. - pub fn size_of() -> uint; + pub fn size_of() -> usize; /// Move a value to an uninitialized memory location. /// /// Drop glue is not run on the destination. pub fn move_val_init(dst: &mut T, src: T); - pub fn min_align_of() -> uint; - pub fn pref_align_of() -> uint; + pub fn min_align_of() -> usize; + pub fn pref_align_of() -> usize; /// Get a static pointer to a type descriptor. pub fn get_tydesc() -> *const TyDesc; @@ -253,7 +253,7 @@ pub struct 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(dst: *const T, offset: int) -> *const T; + pub fn offset(dst: *const T, offset: isize) -> *const T; /// Copies `count * size_of` bytes from `src` to `dst`. The source /// and destination may *not* overlap. @@ -294,7 +294,7 @@ pub struct TyDesc { /// } /// ``` #[unstable(feature = "core")] - pub fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: uint); + pub fn copy_nonoverlapping_memory(dst: *mut T, src: *const T, count: usize); /// Copies `count * size_of` bytes from `src` to `dst`. The source /// and destination may overlap. @@ -324,13 +324,13 @@ pub struct TyDesc { /// ``` /// #[unstable(feature = "core")] - pub fn copy_memory(dst: *mut T, src: *const T, count: uint); + pub fn copy_memory(dst: *mut T, src: *const T, count: usize); /// Invokes memset on the specified pointer, setting `count * size_of::()` /// bytes of memory starting at `dst` to `c`. #[unstable(feature = "core", reason = "uncertain about naming and semantics")] - pub fn set_memory(dst: *mut T, val: u8, count: uint); + pub fn set_memory(dst: *mut T, val: u8, count: usize); /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with /// a size of `count` * `size_of::()` and an alignment of @@ -338,19 +338,19 @@ pub struct TyDesc { /// /// The volatile parameter parameter is set to `true`, so it will not be optimized out. pub fn volatile_copy_nonoverlapping_memory(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::()` and an alignment of /// `min_align_of::()` /// /// The volatile parameter parameter is set to `true`, so it will not be optimized out. - pub fn volatile_copy_memory(dst: *mut T, src: *const T, count: uint); + pub fn volatile_copy_memory(dst: *mut T, src: *const T, count: usize); /// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a /// size of `count` * `size_of::()` and an alignment of /// `min_align_of::()`. /// /// The volatile parameter parameter is set to `true`, so it will not be optimized out. - pub fn volatile_set_memory(dst: *mut T, val: u8, count: uint); + pub fn volatile_set_memory(dst: *mut T, val: u8, count: usize); /// Perform a volatile load from the `src` pointer. pub fn volatile_load(src: *const T) -> T; diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index fffba1561a3..8fb10b5b2dc 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -62,6 +62,7 @@ use cmp; use cmp::Ord; use default::Default; +use marker; use mem; use num::{ToPrimitive, Int}; use ops::{Add, Deref, FnMut}; @@ -113,9 +114,9 @@ fn size_hint(&self) -> (usize, Option) { (**self).size_hint() } #[rustc_on_unimplemented="a collection of type `{Self}` cannot be \ built from an iterator over elements of type `{A}`"] pub trait FromIterator { - /// 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>(iterator: T) -> Self; + fn from_iter>(iterator: T) -> Self; } /// Conversion into an `Iterator` @@ -147,7 +148,7 @@ fn into_iter(self) -> I { pub trait Extend { /// Extend a container with the elements yielded by an arbitrary iterator #[stable(feature = "rust1", since = "1.0.0")] - fn extend>(&mut self, iterator: T); + fn extend>(&mut self, iterable: T); } /// An extension trait providing numerous methods applicable to all iterators. @@ -332,7 +333,7 @@ fn enumerate(self) -> Enumerate { /// /// ``` /// 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); @@ -522,11 +523,11 @@ fn fuse(self) -> Fuse { /// /// 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] @@ -561,7 +562,7 @@ fn by_ref(&mut self) -> &mut Self { self } /// /// ``` /// 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] @@ -937,7 +938,7 @@ fn rev(self) -> Rev { /// /// ``` /// 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); /// ``` @@ -947,7 +948,7 @@ fn unzip(self) -> (FromA, FromB) where FromB: Default + Extend, Self: Iterator, { - struct SizeHint(usize, Option); + struct SizeHint(usize, Option, marker::PhantomData); impl Iterator for SizeHint { type Item = A; @@ -961,8 +962,8 @@ fn size_hint(&self) -> (usize, Option) { 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()); @@ -1142,7 +1143,7 @@ pub trait AdditiveIterator { /// 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; @@ -1305,6 +1306,23 @@ impl ExactSizeIterator for Cloned where I: ExactSizeIterator, {} +#[unstable(feature = "core", reason = "trait is experimental")] +impl RandomAccessIterator for Cloned where + T: Clone, + D: Deref, + I: RandomAccessIterator +{ + #[inline] + fn indexable(&self) -> usize { + self.it.indexable() + } + + #[inline] + fn idx(&mut self, index: usize) -> Option { + self.it.idx(index).cloned() + } +} + /// An iterator that repeats endlessly #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] @@ -2047,8 +2065,8 @@ pub struct Scan { } #[stable(feature = "rust1", since = "1.0.0")] -impl Iterator for Scan where - F: FnMut(&mut St, I::Item) -> Option, +impl, St, F> Iterator for Scan where + F: FnMut(&mut St, A) -> Option, { type Item = B; diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index f0c60ffe4bf..3c58480ff0c 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -126,7 +126,6 @@ pub mod any; pub mod atomic; -pub mod borrow; pub mod cell; pub mod char; pub mod panicking; diff --git a/src/libcore/marker.rs b/src/libcore/marker.rs index 56e1c5dedc1..d284eb34179 100644 --- a/src/libcore/marker.rs +++ b/src/libcore/marker.rs @@ -26,6 +26,10 @@ #![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", @@ -37,12 +41,11 @@ pub unsafe trait Send: 'static { // 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. } @@ -50,7 +53,7 @@ pub unsafe trait Send { #[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. } @@ -155,7 +158,7 @@ pub trait Sized { /// 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. } @@ -204,236 +207,179 @@ pub trait Copy { /// 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; + reason = "likely to change with new variance strategy")] +#[lang="no_copy_bound"] +#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct NoCopy; -impl Copy for PhantomData {} -impl Clone for PhantomData { - fn clone(&self) -> PhantomData { *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 Hash for $t { + #[inline] + fn hash(&self, _: &mut S) { + } + } + #[cfg(not(stage0))] + impl Hash for $t { + #[inline] + fn hash(&self, _: &mut H) { + } + } + + impl cmp::PartialEq for $t { + fn eq(&self, _other: &$t) -> bool { + true + } + } + + impl cmp::Eq for $t { + } + + impl cmp::PartialOrd for $t { + fn partial_cmp(&self, _other: &$t) -> Option { + Option::Some(cmp::Ordering::Equal) + } + } + + impl cmp::Ord for $t { + fn cmp(&self, _other: &$t) -> cmp::Ordering { + cmp::Ordering::Equal + } + } + + impl Copy for $t { } + + impl Clone for $t { + fn clone(&self) -> $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 . -/// -/// *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 { } +impl 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`. /// /// # 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 { x: *() } -/// fn get(s: &S) -> 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` is -/// a subtype of `S>` (or, for that matter, `S` 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` to inform the type checker that -/// `S` is a subtype of `S` 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; - -impl Copy for CovariantType {} -impl Clone for CovariantType { - fn clone(&self) -> CovariantType { *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 . +/// ```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 { } +/// ``` /// -/// 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 { x: *const () } -/// fn get(s: &S, 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` is -/// a subtype of `S>` (or, for that matter, `S` 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` is only a -/// subtype of `S` 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; - -impl Copy for ContravariantType {} -impl Clone for ContravariantType { - fn clone(&self) -> ContravariantType { *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 . +/// # 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 { 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; - -#[unstable(feature = "core", - reason = "likely to change with new variance strategy")] -impl Copy for InvariantType {} -#[unstable(feature = "core", - reason = "likely to change with new variance strategy")] -impl Clone for InvariantType { - fn clone(&self) -> InvariantType { *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 . -#[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 { } -/// 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 . -#[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 PhantomFn 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; -/// 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` +/// 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` 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; -/// 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 { @@ -442,3 +388,40 @@ 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`")] +#[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>`")] +#[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`")] +#[lang="contravariant_type"] +pub struct ContravariantType; + +/// Old-style marker trait. Deprecated. +#[unstable(feature = "core", reason = "deprecated")] +#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData`")] +#[lang="covariant_type"] +#[cfg(not(stage0))] +pub struct CovariantType; + +/// Old-style marker trait. Deprecated. +#[unstable(feature = "core", reason = "deprecated")] +#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData>`")] +#[lang="invariant_type"] +pub struct InvariantType; diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs index 5644f763069..230587b726f 100644 --- a/src/libcore/nonzero.rs +++ b/src/libcore/nonzero.rs @@ -10,15 +10,14 @@ //! 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 Zeroable for *const T {} -unsafe impl Zeroable for *mut T {} -unsafe impl Zeroable for Unique { } +unsafe impl Zeroable for *const T {} +unsafe impl Zeroable for *mut T {} unsafe impl Zeroable for isize {} unsafe impl Zeroable for usize {} unsafe impl Zeroable for i8 {} diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 9a89682127f..abfef72a5db 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -149,7 +149,7 @@ 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}; @@ -909,7 +909,7 @@ impl> FromIterator> for Option { /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - fn from_iter>>(iter: I) -> Option { + fn from_iter>>(iter: I) -> Option { // FIXME(#11084): This could be replaced with Iterator::scan when this // performance bug is closed. @@ -934,7 +934,7 @@ fn next(&mut self) -> Option { } } - 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 { diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 072c60c7036..16b84dcf18e 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -91,8 +91,10 @@ 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}; @@ -303,7 +305,7 @@ impl PtrExt for *const T { #[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")] @@ -330,7 +332,7 @@ impl PtrExt for *mut T { #[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")] @@ -517,15 +519,16 @@ fn ge(&self, other: &*mut T) -> bool { *self >= *other } /// 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` 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` or `Box`, which +/// `Unique` 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` or `Box`, which /// internally use raw pointers to manage the memory that they own. #[unstable(feature = "core", reason = "recently added to this module")] -pub struct Unique { - /// The wrapped `*mut T`. - pub ptr: *mut T, - _own: marker::PhantomData, +pub struct Unique { + pointer: NonZero<*const T>, + _marker: PhantomData, } /// `Unique` pointers are `Send` if `T` is `Send` because the data they @@ -542,25 +545,34 @@ unsafe impl Send for Unique { } #[unstable(feature = "core", reason = "recently added to this module")] unsafe impl Sync for Unique { } -impl Unique { - /// Returns a null Unique. +impl Unique { + /// Create a new `Unique`. #[unstable(feature = "core", reason = "recently added to this module")] - pub fn null() -> Unique { - Unique(null_mut()) + pub unsafe fn new(ptr: *mut T) -> Unique { + 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(ptr: *mut T) -> Unique { - Unique { ptr: ptr, _own: marker::PhantomData } +impl Deref for Unique { + type Target = *mut T; + + #[inline] + fn deref<'a>(&'a self) -> &'a *mut T { + unsafe { mem::transmute(&*self.pointer) } + } } diff --git a/src/libcore/result.rs b/src/libcore/result.rs index 1a874ee178b..23e936a75d7 100644 --- a/src/libcore/result.rs +++ b/src/libcore/result.rs @@ -230,7 +230,8 @@ 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; @@ -906,7 +907,7 @@ impl> FromIterator> for Result { /// assert!(res == Ok(vec!(2, 3))); /// ``` #[inline] - fn from_iter>>(iter: I) -> Result { + fn from_iter>>(iter: I) -> Result { // FIXME(#11084): This could be replaced with Iterator::scan when this // performance bug is closed. @@ -931,7 +932,7 @@ fn next(&mut self) -> Option { } } - 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 { diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index bbfe7e58ef4..a86da53b372 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -140,11 +140,11 @@ fn iter<'a>(&'a self) -> Iter<'a, T> { if mem::size_of::() == 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} } } } @@ -279,11 +279,11 @@ fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> { if mem::size_of::() == 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} } } } @@ -733,7 +733,7 @@ macro_rules! make_slice { pub struct Iter<'a, T: 'a> { ptr: *const T, end: *const T, - marker: marker::ContravariantLifetime<'a> + _marker: marker::PhantomData<&'a T>, } #[unstable(feature = "core")] @@ -790,7 +790,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {} #[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")] @@ -823,7 +823,7 @@ fn idx(&mut self, index: usize) -> Option<&'a T> { pub struct IterMut<'a, T: 'a> { ptr: *mut T, end: *mut T, - marker: marker::ContravariantLifetime<'a>, + _marker: marker::PhantomData<&'a mut T>, } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index ce26abe606d..eec997b9f10 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1280,7 +1280,7 @@ fn index(&self, _index: &ops::RangeFull) -> &str { /// 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. diff --git a/src/libcoretest/hash/mod.rs b/src/libcoretest/hash/mod.rs index fd0d3c676a4..9b6af182f72 100644 --- a/src/libcoretest/hash/mod.rs +++ b/src/libcoretest/hash/mod.rs @@ -9,7 +9,7 @@ // 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 { @@ -22,25 +22,19 @@ fn default() -> 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: &T) -> u64 { + fn hash(t: &T) -> u64 { ::std::hash::hash::<_, MyHasher>(t) } @@ -90,9 +84,9 @@ struct Custom { hash: u64 } 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 { @@ -101,15 +95,15 @@ fn default() -> CustomHasher { } } -impl Hash for Custom { - fn hash(&self, state: &mut CustomHasher) { - state.output = self.hash; +impl Hash for Custom { + fn hash(&self, state: &mut H) { + state.write_u64(self.hash); } } #[test] fn test_custom_state() { - fn hash>(t: &T) -> u64 { + fn hash(t: &T) -> u64 { ::std::hash::hash::<_, CustomHasher>(t) } diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index 7eb0fb97bed..39a590c7307 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -91,7 +91,7 @@ fn test_iterator_chain() { 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]); @@ -119,7 +119,7 @@ fn test_iterator_enumerate() { #[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); @@ -259,12 +259,12 @@ fn test_inspect() { let mut n = 0; let ys = xs.iter() - .map(|&x| x) + .cloned() .inspect(|_| n += 1) .collect::>(); assert_eq!(n, xs.len()); - assert_eq!(&xs[], &ys[]); + assert_eq!(&xs[..], &ys[..]); } #[test] @@ -329,33 +329,33 @@ fn test_iterator_len() { #[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] @@ -373,7 +373,7 @@ fn test_iterator_size_hint() { 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)); @@ -398,7 +398,7 @@ fn test_iterator_size_hint() { #[test] fn test_collect() { let a = vec![1, 2, 3, 4, 5]; - let b: Vec = a.iter().map(|&x| x).collect(); + let b: Vec = a.iter().cloned().collect(); assert!(a == b); } @@ -471,7 +471,7 @@ fn test_rev() { let mut it = xs.iter(); it.next(); it.next(); - assert!(it.rev().map(|&x| x).collect::>() == + assert!(it.rev().cloned().collect::>() == vec![16, 14, 12, 10, 8, 6]); } @@ -508,7 +508,7 @@ fn test_double_ended_map() { #[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))); @@ -522,8 +522,8 @@ fn test_double_ended_enumerate() { 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))); @@ -713,7 +713,7 @@ fn test_random_access_inspect() { 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)); diff --git a/src/libcoretest/mem.rs b/src/libcoretest/mem.rs index 421ce76caaf..5aeb330b78b 100644 --- a/src/libcoretest/mem.rs +++ b/src/libcoretest/mem.rs @@ -92,7 +92,7 @@ fn test_transmute_copy() { #[test] fn test_transmute() { - trait Foo {} + trait Foo { fn dummy(&self) { } } impl Foo for int {} let a = box 100 as Box; diff --git a/src/libcoretest/ptr.rs b/src/libcoretest/ptr.rs index 9c2e242c105..57456bfb1a7 100644 --- a/src/libcoretest/ptr.rs +++ b/src/libcoretest/ptr.rs @@ -171,8 +171,8 @@ fn test_set_memory() { #[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); } diff --git a/src/libcoretest/slice.rs b/src/libcoretest/slice.rs index 6d5cc38ef0a..46c7730cc64 100644 --- a/src/libcoretest/slice.rs +++ b/src/libcoretest/slice.rs @@ -43,13 +43,13 @@ macro_rules! test { { 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(); @@ -57,17 +57,17 @@ macro_rules! test { } { 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(); diff --git a/src/libflate/lib.rs b/src/libflate/lib.rs index ff6400a11df..24660b3f396 100644 --- a/src/libflate/lib.rs +++ b/src/libflate/lib.rs @@ -45,13 +45,13 @@ pub struct Bytes { 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 _); } } } @@ -84,7 +84,7 @@ fn deflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option { &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 @@ -110,7 +110,7 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option { &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 diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index 1c7e97d784c..be77622ac1d 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -215,11 +215,11 @@ fn must_consume(&mut self, c: char) { } Some((_, other)) => { self.err(&format!("expected `{:?}`, found `{:?}`", c, - other)[]); + other)); } None => { self.err(&format!("expected `{:?}` but string was terminated", - c)[]); + c)); } } } diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs index c743119f409..fdd7f7395c2 100644 --- a/src/libgetopts/lib.rs +++ b/src/libgetopts/lib.rs @@ -287,7 +287,7 @@ pub fn long_to_short(&self) -> Opt { impl Matches { fn opt_vals(&self, nm: &str) -> Vec { - 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) } @@ -326,7 +326,7 @@ pub fn opts_present(&self, names: &[String]) -> bool { /// Returns the string argument supplied to one of several matching options or `None`. pub fn opts_str(&self, names: &[String]) -> Option { for nm in names { - match self.opt_val(&nm[]) { + match self.opt_val(&nm[..]) { Some(Val(ref s)) => return Some(s.clone()), _ => () } @@ -593,7 +593,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { 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; @@ -667,7 +667,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result { 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 { @@ -730,7 +730,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String { 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"), @@ -741,7 +741,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String { 0 => {} _ => { row.push_str("--"); - row.push_str(&long_name[]); + row.push_str(&long_name[..]); row.push(' '); } } @@ -749,10 +749,10 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String { // 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(']'); } } @@ -765,7 +765,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String { row.push(' '); } } else { - row.push_str(&desc_sep[]); + row.push_str(&desc_sep[..]); } // Normalize desc to contain words separated by one space character @@ -777,14 +777,14 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String { // 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 }); @@ -803,10 +803,10 @@ fn format_option(opt: &OptGroup) -> String { // 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 { @@ -814,7 +814,7 @@ fn format_option(opt: &OptGroup) -> String { if opt.hasarg == Maybe { line.push('['); } - line.push_str(&opt.hint[]); + line.push_str(&opt.hint[..]); if opt.hasarg == Maybe { line.push(']'); } @@ -836,7 +836,7 @@ pub fn short_usage(program_name: &str, opts: &[OptGroup]) -> String { line.push_str(&opts.iter() .map(format_option) .collect::>() - .connect(" ")[]); + .connect(" ")[..]); line } diff --git a/src/libgraphviz/lib.rs b/src/libgraphviz/lib.rs index 230deabee00..acd52c752e8 100644 --- a/src/libgraphviz/lib.rs +++ b/src/libgraphviz/lib.rs @@ -275,15 +275,12 @@ 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> { @@ -291,7 +288,7 @@ 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 @@ -303,7 +300,7 @@ pub enum LabelText<'a> { /// 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. @@ -340,7 +337,7 @@ pub enum LabelText<'a> { /// `Id` is a Graphviz `ID`. pub struct Id<'a> { - name: CowString<'a>, + name: Cow<'a, str>, } impl<'a> Id<'a> { @@ -358,7 +355,7 @@ impl<'a> Id<'a> { /// /// Passing an invalid string (containing spaces, brackets, /// quotes, ...) will return an empty `Err` value. - pub fn new>(name: Name) -> Result, ()> { + pub fn new>(name: Name) -> Result, ()> { let name = name.into_cow(); { let mut chars = name.chars(); @@ -387,7 +384,7 @@ pub fn as_slice(&'a self) -> &'a str { &*self.name } - pub fn name(self) -> CowString<'a> { + pub fn name(self) -> Cow<'a, str> { self.name } } @@ -427,11 +424,11 @@ fn edge_label(&'a self, e: &E) -> LabelText<'a> { } impl<'a> LabelText<'a> { - pub fn label>(s: S) -> LabelText<'a> { + pub fn label>(s: S) -> LabelText<'a> { LabelStr(s.into_cow()) } - pub fn escaped>(s: S) -> LabelText<'a> { + pub fn escaped>(s: S) -> LabelText<'a> { EscStr(s.into_cow()) } @@ -455,7 +452,7 @@ fn escape_str(s: &str) -> String { 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[..]), } } @@ -463,7 +460,7 @@ pub fn escape(&self) -> String { /// 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('\\') { @@ -484,13 +481,13 @@ pub fn suffix_line(self, suffix: LabelText) -> LabelText<'static> { 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.) @@ -678,7 +675,7 @@ fn id_name<'a>(n: &Node) -> Id<'a> { 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) diff --git a/src/liblog/lib.rs b/src/liblog/lib.rs index 4dab07acfd2..c2c7f20ce9c 100644 --- a/src/liblog/lib.rs +++ b/src/liblog/lib.rs @@ -287,7 +287,7 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) { // 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, _ => {} } @@ -382,7 +382,7 @@ fn enabled(level: u32, // 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 } @@ -397,7 +397,7 @@ fn enabled(level: u32, /// `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), }; diff --git a/src/librand/distributions/mod.rs b/src/librand/distributions/mod.rs index d1d24cea871..5a85552dc38 100644 --- a/src/librand/distributions/mod.rs +++ b/src/librand/distributions/mod.rs @@ -21,6 +21,7 @@ use core::prelude::*; use core::num::{Float, Int}; +use core::marker::PhantomData; use {Rng, Rand}; @@ -56,7 +57,13 @@ pub trait IndependentSample: Sample { /// A wrapper for generating types that implement `Rand` via the /// `Sample` & `IndependentSample` traits. -pub struct RandSample; +pub struct RandSample { _marker: PhantomData } + +impl RandSample { + pub fn new() -> RandSample { + RandSample { _marker: PhantomData } + } +} impl Sample for RandSample { fn sample(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) } @@ -285,7 +292,7 @@ fn next_u64(&mut self) -> u64 { #[test] fn test_rand_sample() { - let mut rand_sample = RandSample::; + let mut rand_sample = RandSample::::new(); assert_eq!(rand_sample.sample(&mut ::test::rng()), ConstRand(0)); assert_eq!(rand_sample.ind_sample(&mut ::test::rng()), ConstRand(0)); diff --git a/src/librand/isaac.rs b/src/librand/isaac.rs index f15523fc010..701749ff344 100644 --- a/src/librand/isaac.rs +++ b/src/librand/isaac.rs @@ -215,7 +215,7 @@ impl<'a> SeedableRng<&'a [u32]> for IsaacRng { 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; @@ -458,7 +458,7 @@ impl<'a> SeedableRng<&'a [u64]> for Isaac64Rng { 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; diff --git a/src/librand/lib.rs b/src/librand/lib.rs index 915c70bbf8c..7588bf7c515 100644 --- a/src/librand/lib.rs +++ b/src/librand/lib.rs @@ -41,6 +41,7 @@ #[cfg(test)] #[macro_use] extern crate log; use core::prelude::*; +use core::marker::PhantomData; pub use isaac::{IsaacRng, Isaac64Rng}; pub use chacha::ChaChaRng; @@ -206,7 +207,7 @@ fn gen(&mut self) -> T { /// .collect::>()); /// ``` 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`). @@ -317,6 +318,7 @@ fn shuffle(&mut self, values: &mut [T]) { /// This iterator is created via the `gen_iter` method on `Rng`. pub struct Generator<'a, T, R:'a> { rng: &'a mut R, + _marker: PhantomData } impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> { diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index eb51046d7c9..dc81e89902b 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -37,7 +37,7 @@ 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}; @@ -508,7 +508,7 @@ fn check_heap_type<'a, 'tcx>(&self, cx: &Context<'a, 'tcx>, 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[..]); } } } @@ -736,7 +736,7 @@ fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) { } } 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); } } _ => {} @@ -803,7 +803,7 @@ fn to_camel_case(s: &str) -> String { } 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[..]); } } } @@ -950,7 +950,7 @@ fn is_snake_case(ident: ast::Ident) -> bool { 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)); @@ -1033,7 +1033,7 @@ fn check_upper_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) { 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)); @@ -1196,7 +1196,7 @@ fn check_item(&mut self, cx: &Context, item: &ast::Item) { let m = format!("braces around {} is unnecessary", &token::get_ident(*name)); cx.span_lint(UNUSED_IMPORT_BRACES, item.span, - &m[]); + &m[..]); }, _ => () } @@ -1474,7 +1474,7 @@ fn enter_lint_attrs(&mut self, _: &Context, attrs: &[ast::Attribute]) { 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); @@ -1702,7 +1702,7 @@ fn output(cx: &Context, span: Span, stability: &Option, _ => format!("use of {} item", label) }; - cx.span_lint(lint, span, &msg[]); + cx.span_lint(lint, span, &msg[..]); } } } @@ -1791,7 +1791,7 @@ fn check_fn(&mut self, cx: &Context, fn_kind: visit::FnKind, _: &ast::FnDecl, 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(); diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 42a6861f452..068c179d343 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -125,11 +125,11 @@ pub fn register_pass(&mut self, sess: Option<&Session>, 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[..]), } } @@ -150,11 +150,11 @@ pub fn register_group(&mut self, sess: Option<&Session>, 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[..]), } } } @@ -251,8 +251,8 @@ fn find_lint(&self, lint_name: &str, sess: &Session, span: Option) 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) } @@ -262,13 +262,13 @@ fn find_lint(&self, lint_name: &str, sess: &Session, span: Option) 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::>>() - .get(&lint_name[]) { + .get(&lint_name[..]) { Some(v) => { v.iter() .map(|lint_id: &LintId| @@ -411,15 +411,15 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint, 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 { @@ -503,7 +503,7 @@ fn with_lint_attrs(&mut self, 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)) @@ -729,7 +729,7 @@ fn visit_id(&mut self, id: ast::NodeId) { 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[..]) } } } diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 5dc23d27ee1..bdcc10ebcec 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -185,12 +185,20 @@ fn eq(&self, other: &LintId) -> bool { impl Eq for LintId { } +#[cfg(stage0)] impl hash::Hash 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(&self, state: &mut H) { + let ptr = self.lint as *const Lint; + ptr.hash(state); + } +} impl LintId { /// Get the `LintId` for a `Lint`. diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs index 0871c36d892..d48a404176a 100644 --- a/src/librustc/metadata/creader.rs +++ b/src/librustc/metadata/creader.rs @@ -183,7 +183,7 @@ fn extract_crate_info(&self, i: &ast::Item) -> Option { 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 } @@ -321,7 +321,7 @@ fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind) 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() }); @@ -459,8 +459,8 @@ fn read_extension_crate(&mut self, span: Span, info: &CrateInfo) -> ExtensionCra 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, @@ -562,7 +562,7 @@ pub fn find_plugin_registrar(&mut self, span: Span, name: &str) -> Option<(Path, 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(); } @@ -575,7 +575,7 @@ pub fn find_plugin_registrar(&mut self, span: Span, name: &str) -> Option<(Path, 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 diff --git a/src/librustc/metadata/cstore.rs b/src/librustc/metadata/cstore.rs index 0a3e173b35e..a3f7d57da67 100644 --- a/src/librustc/metadata/cstore.rs +++ b/src/librustc/metadata/cstore.rs @@ -139,8 +139,7 @@ pub fn add_used_crate_source(&self, src: CrateSource) { pub fn get_used_crate_source(&self, cnum: ast::CrateNum) -> Option { 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) { @@ -218,7 +217,7 @@ pub fn add_extern_mod_stmt_cnum(&self, pub fn find_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option { - self.extern_mod_crate_map.borrow().get(&emod_id).map(|x| *x) + self.extern_mod_crate_map.borrow().get(&emod_id).cloned() } } diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 3123fa31abd..42a70cec5df 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -163,7 +163,7 @@ fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) { 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(); } @@ -353,9 +353,9 @@ fn encode_enum_variant_info(ecx: &EncodeContext, 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); } } @@ -1158,7 +1158,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder, class itself */ let idx = encode_info_for_struct(ecx, rbml_w, - &fields[], + &fields[..], index); /* Index the class*/ @@ -1181,7 +1181,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder, /* 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)); @@ -1588,6 +1588,7 @@ fn encode_info_for_items(ecx: &EncodeContext, // Path and definition ID indexing +#[cfg(stage0)] fn encode_index(rbml_w: &mut Encoder, index: Vec>, mut write_fn: F) where F: FnMut(&mut SeekableMemWriter, &T), T: Hash, @@ -1628,6 +1629,47 @@ fn encode_index(rbml_w: &mut Encoder, index: Vec>, mut write_fn: rbml_w.end_tag(); rbml_w.end_tag(); } +#[cfg(not(stage0))] +fn encode_index(rbml_w: &mut Encoder, index: Vec>, mut write_fn: F) where + F: FnMut(&mut SeekableMemWriter, &T), + T: Hash, +{ + let mut buckets: Vec>> = (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; diff --git a/src/librustc/metadata/loader.rs b/src/librustc/metadata/loader.rs index 3158ccd0765..01d1f4e7011 100644 --- a/src/librustc/metadata/loader.rs +++ b/src/librustc/metadata/loader.rs @@ -322,7 +322,7 @@ pub fn report_load_errs(&mut self) { &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(); @@ -404,7 +404,7 @@ fn find_library_crate(&mut self) -> Option { 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) @@ -413,7 +413,7 @@ fn find_library_crate(&mut self) -> Option { (&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(), @@ -627,7 +627,7 @@ fn find_commandline_library(&mut self, locs: &[String]) -> Option { 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())[]); @@ -645,8 +645,8 @@ fn find_commandline_library(&mut self, locs: &[String]) -> Option { 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 } } @@ -744,7 +744,7 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result abi::Abi { 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) }) } diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index c3302debdfa..ae10eb686b0 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -134,7 +134,7 @@ pub fn decode_inlined_item<'tcx>(cdata: &cstore::crate_metadata, // 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(); diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs index 1f0fe4f1aca..46b4a51c9d6 100644 --- a/src/librustc/middle/cfg/graphviz.rs +++ b/src/librustc/middle/cfg/graphviz.rs @@ -92,7 +92,7 @@ fn edge_label(&self, e: &Edge<'a>) -> dot::LabelText<'a> { let s = replace_newline_with_backslash_l(s); label.push_str(&format!("exiting scope_{} {}", i, - &s[])[]); + &s[..])[]); } dot::LabelText::EscStr(label.into_cow()) } diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs index 03456f85290..86c59b24e3e 100644 --- a/src/librustc/middle/check_match.rs +++ b/src/librustc/middle/check_match.rs @@ -25,7 +25,7 @@ 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}; @@ -76,7 +76,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 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::(); try!(write!(f, "{}\n", br)); for row in pretty_printed_matrix { @@ -94,8 +94,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } impl<'a> FromIterator> for Matrix<'a> { - fn from_iter>>(iterator: T) -> Matrix<'a> { - Matrix(iterator.collect()) + fn from_iter>>(iter: T) -> Matrix<'a> { + Matrix(iter.into_iter().collect()) } } @@ -200,7 +200,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) { } // 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. @@ -291,7 +291,7 @@ fn check_arms(cx: &MatchCheckCtxt, 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 { .. } => { @@ -351,7 +351,7 @@ fn raw_pat<'a>(p: &'a Pat) -> &'a Pat { 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!() @@ -360,7 +360,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: ast: ast::MatchSource::ForLoopDesugar => { // `witness` has the form `Some()`, 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!(), }, @@ -664,7 +664,7 @@ fn is_useful(cx: &MatchCheckCtxt, 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(); @@ -711,10 +711,10 @@ fn is_useful_specialized(cx: &MatchCheckCtxt, &Matrix(ref m): &Matrix, 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 } } diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs index 3d03cd946c4..5bf7422dbc0 100644 --- a/src/librustc/middle/const_eval.rs +++ b/src/librustc/middle/const_eval.rs @@ -62,7 +62,7 @@ fn variant_expr<'a>(variants: &'a [P], id: ast::NodeId) 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 }, @@ -83,7 +83,7 @@ fn variant_expr<'a>(variants: &'a [P], id: ast::NodeId) // 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 }, @@ -209,7 +209,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P 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[..]) } } @@ -501,7 +501,7 @@ fn lit_to_const(lit: &ast::Lit, ty_hint: Option) -> const_val { 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), @@ -552,14 +552,14 @@ pub fn compare_lit_exprs<'tcx>(tcx: &ty::ctxt<'tcx>, 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; } }; diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index b792a44d4d8..085d5cbc347 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -89,7 +89,7 @@ struct PropagationContext<'a, 'b: 'a, 'tcx: 'b, O: 'a> { } fn to_cfgidx_or_die(id: ast::NodeId, index: &NodeMap) -> 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); }) @@ -312,7 +312,7 @@ pub fn each_bit_for_node(&self, e: EntryOrExit, cfgidx: CFGIndex, f: F) -> bo 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={}", @@ -400,7 +400,7 @@ pub fn add_kills_from_flow_exits(&mut self, cfg: &cfg::CFG) { 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); @@ -421,7 +421,7 @@ pub fn add_kills_from_flow_exits(&mut self, cfg: &cfg::CFG) { 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)); } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index b2335f91ad9..ff78deb8d12 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -321,7 +321,7 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool { 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, _ => (), } } diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 6d35a82d153..ad9f4eade5c 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -158,7 +158,7 @@ fn calculate_type(sess: &session::Session, // 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, } diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index 8dbac7f515e..e99d214742a 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -29,7 +29,6 @@ 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; @@ -128,16 +127,14 @@ pub enum MatchMode { MovingMatch, } -#[derive(PartialEq,Debug)] -enum TrackMatchMode { +#[derive(Copy, PartialEq, Debug)] +enum TrackMatchMode { Unknown, Definite(MatchMode), Conflicting, } -impl marker::Copy for TrackMatchMode {} - -impl TrackMatchMode { +impl TrackMatchMode { // Builds up the whole match mode for a pattern from its constituent // parts. The lattice looks like this: // @@ -931,7 +928,7 @@ fn walk_overloaded_operator(&mut self, return true; } - fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &ast::Arm) -> TrackMatchMode { + 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); @@ -966,7 +963,7 @@ fn walk_irrefutable_pat(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &ast::Pat) { fn determine_pat_move_mode(&mut self, cmt_discr: mc::cmt<'tcx>, pat: &ast::Pat, - mode: &mut TrackMatchMode) { + 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| { @@ -1166,7 +1163,7 @@ fn walk_pat(&mut self, 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[..]) } } } diff --git a/src/librustc/middle/graph.rs b/src/librustc/middle/graph.rs index 4dd7a4a2266..436f04fc9e9 100644 --- a/src/librustc/middle/graph.rs +++ b/src/librustc/middle/graph.rs @@ -34,7 +34,7 @@ use std::fmt::{Formatter, Error, Debug}; use std::usize; -use std::collections::BitvSet; +use std::collections::BitSet; pub struct Graph { nodes: Vec> , @@ -292,7 +292,7 @@ pub fn depth_traverse<'a>(&'a self, start: NodeIndex) -> DepthFirstTraversal<'a, DepthFirstTraversal { graph: self, stack: vec![start], - visited: BitvSet::new() + visited: BitSet::new() } } } @@ -300,7 +300,7 @@ pub fn depth_traverse<'a>(&'a self, start: NodeIndex) -> DepthFirstTraversal<'a, pub struct DepthFirstTraversal<'g, N:'g, E:'g> { graph: &'g Graph, stack: Vec, - visited: BitvSet + visited: BitSet } impl<'g, N, E> Iterator for DepthFirstTraversal<'g, N, E> { diff --git a/src/librustc/middle/infer/bivariate.rs b/src/librustc/middle/infer/bivariate.rs new file mode 100644 index 00000000000..93c80fb754f --- /dev/null +++ b/src/librustc/middle/infer/bivariate.rs @@ -0,0 +1,145 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! 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(&self, a: &ty::Binder, b: &ty::Binder) -> cres<'tcx, ty::Binder> + 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)) + } +} diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index daa820f43b5..0eeafb767d8 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -32,6 +32,7 @@ // 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; @@ -39,7 +40,7 @@ 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}; @@ -48,7 +49,7 @@ 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; @@ -58,41 +59,32 @@ 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>> { - // 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::>>()); - 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, @@ -100,6 +92,11 @@ fn substs(&self, 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 { @@ -119,7 +116,8 @@ fn substs_variances(&self, 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); } @@ -132,20 +130,7 @@ fn substs_variances(&self, 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, @@ -157,13 +142,34 @@ fn substs_variances(&self, 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>> + { + 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> { + -> cres<'tcx, Vec> + { let tcx = this.infcx().tcx; - let num_region_params = variances.len(); + let num_region_params = a_rs.len(); debug!("relate_region_params(\ a_rs={}, \ @@ -173,22 +179,18 @@ fn relate_region_params<'tcx, C: Combine<'tcx>>(this: &C, 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() } } @@ -241,7 +243,7 @@ fn argvecs<'tcx, C: Combine<'tcx>>(combiner: &C, } 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>; @@ -309,7 +311,7 @@ fn existential_bounds(&self, 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, @@ -322,11 +324,6 @@ fn builtin_bounds(&self, 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>) @@ -540,7 +537,8 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C, } (&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 @@ -644,6 +642,10 @@ fn equate(&self) -> Equate<'f, 'tcx> { Equate((*self).clone()) } + fn bivariate(&self) -> Bivariate<'f, 'tcx> { + Bivariate((*self).clone()) + } + fn sub(&self) -> Sub<'f, 'tcx> { Sub((*self).clone()) } @@ -697,7 +699,7 @@ pub fn instantiate(&self, EqTo => { self.generalize(a_ty, b_vid, false) } - SupertypeOf | SubtypeOf => { + BiTo | SupertypeOf | SubtypeOf => { self.generalize(a_ty, b_vid, true) } }); @@ -721,6 +723,10 @@ pub fn instantiate(&self, // 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)); } @@ -730,7 +736,7 @@ pub fn instantiate(&self, } SupertypeOf => { - try!(self.sub().contratys(a_ty, b_ty)); + try!(self.sub().tys_with_variance(ty::Contravariant, a_ty, b_ty)); } } } diff --git a/src/librustc/middle/infer/equate.rs b/src/librustc/middle/infer/equate.rs index f0bde222864..7194e20b0cf 100644 --- a/src/librustc/middle/infer/equate.rs +++ b/src/librustc/middle/infer/equate.rs @@ -13,11 +13,7 @@ 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}; @@ -33,21 +29,20 @@ pub fn Equate<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Equate<'f, 'tcx> { } 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) } diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 72b33613c66..53032f9b9ac 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -200,9 +200,9 @@ fn report_region_errors(&self, 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[..]); } } } @@ -675,6 +675,17 @@ fn report_concrete_failure(&self, 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, @@ -824,7 +835,7 @@ fn give_suggestion(&self, same_regions: &[SameRegions]) { 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) => { @@ -924,7 +935,7 @@ fn new(tcx: &'a ty::ctxt<'tcx>, fn rebuild(&self) -> (ast::FnDecl, Option, 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(); @@ -942,7 +953,7 @@ fn rebuild(&self) } 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, @@ -1426,7 +1437,7 @@ fn give_expl_lifetime_param(&self, 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, @@ -1593,6 +1604,11 @@ fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) { 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, @@ -1771,7 +1787,7 @@ fn give_lifetime(&self) -> ast::Lifetime { 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; } diff --git a/src/librustc/middle/infer/glb.rs b/src/librustc/middle/infer/glb.rs index ff0c2d92f45..33303808e84 100644 --- a/src/librustc/middle/infer/glb.rs +++ b/src/librustc/middle/infer/glb.rs @@ -10,12 +10,9 @@ 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}; @@ -34,15 +31,30 @@ pub fn Glb<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Glb<'f, 'tcx> { } 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; @@ -75,10 +87,6 @@ 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>> { - 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), @@ -104,11 +112,6 @@ fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> { 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) } diff --git a/src/librustc/middle/infer/higher_ranked/mod.rs b/src/librustc/middle/infer/higher_ranked/mod.rs index 4469e27a5b0..a729156c88b 100644 --- a/src/librustc/middle/infer/higher_ranked/mod.rs +++ b/src/librustc/middle/infer/higher_ranked/mod.rs @@ -31,7 +31,7 @@ fn higher_ranked_glb(&self, a: &Binder, b: &Binder) -> cres<'tcx, Binde where T : Combineable<'tcx>; } -trait InferCtxtExt<'tcx> { +trait InferCtxtExt { fn tainted_regions(&self, snapshot: &CombinedSnapshot, r: ty::Region) -> Vec; fn region_vars_confined_to_snapshot(&self, @@ -371,7 +371,7 @@ fn fold_regions_in<'tcx, T, F>(tcx: &ty::ctxt<'tcx>, })) } -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 { self.region_vars.tainted(&snapshot.region_vars_snapshot, r) } diff --git a/src/librustc/middle/infer/lub.rs b/src/librustc/middle/infer/lub.rs index 204560e87ee..3570effa9fa 100644 --- a/src/librustc/middle/infer/lub.rs +++ b/src/librustc/middle/infer/lub.rs @@ -9,13 +9,10 @@ // 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}; @@ -34,15 +31,30 @@ pub fn Lub<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Lub<'f, 'tcx> { } 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(); @@ -70,10 +82,6 @@ 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>> { - 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), @@ -90,11 +98,6 @@ fn builtin_bounds(&self, 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(), diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 00e377d65fe..b0576ff55ff 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -45,6 +45,7 @@ use self::unify::{UnificationTable, InferCtxtMethodsForSimplyUnifiableTypes}; use self::error_reporting::ErrorReporting; +pub mod bivariate; pub mod combine; pub mod equate; pub mod error_reporting; @@ -209,6 +210,9 @@ pub enum SubregionOrigin<'tcx> { // 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), @@ -1194,6 +1198,7 @@ pub fn span(&self) -> Span { CallRcvr(a) => a, CallArg(a) => a, CallReturn(a) => a, + Operand(a) => a, AddrOf(a) => a, AutoBorrow(a) => a, SafeDestructor(a) => a, @@ -1257,6 +1262,7 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { 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)), diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs index 5cdfdcc7c9b..b4fd34f206f 100644 --- a/src/librustc/middle/infer/region_inference/mod.rs +++ b/src/librustc/middle/infer/region_inference/mod.rs @@ -977,7 +977,7 @@ fn infer_variable_values(&self, 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 diff --git a/src/librustc/middle/infer/sub.rs b/src/librustc/middle/infer/sub.rs index 1e0d14544ff..33da3092b2a 100644 --- a/src/librustc/middle/infer/sub.rs +++ b/src/librustc/middle/infer/sub.rs @@ -10,12 +10,8 @@ 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}; @@ -37,28 +33,30 @@ pub fn Sub<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Sub<'f, 'tcx> { } 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({}, {})", diff --git a/src/librustc/middle/infer/type_variable.rs b/src/librustc/middle/infer/type_variable.rs index 9b8a4a84412..a856137af09 100644 --- a/src/librustc/middle/infer/type_variable.rs +++ b/src/librustc/middle/infer/type_variable.rs @@ -14,6 +14,7 @@ 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; @@ -42,13 +43,13 @@ enum UndoEntry { 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 { @@ -56,14 +57,15 @@ fn opposite(self) -> 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 { diff --git a/src/librustc/middle/infer/unify.rs b/src/librustc/middle/infer/unify.rs index 235f3f994c6..0675cec6f69 100644 --- a/src/librustc/middle/infer/unify.rs +++ b/src/librustc/middle/infer/unify.rs @@ -18,6 +18,7 @@ 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; @@ -79,7 +80,7 @@ pub struct UnificationTable { /// made during the snapshot may either be *committed* or *rolled back*. pub struct Snapshot { // Link snapshot to the key type `K` of the table. - marker: marker::CovariantType, + marker: marker::PhantomData, snapshot: sv::Snapshot, } @@ -92,7 +93,7 @@ pub struct Node { } #[derive(Copy)] -pub struct Delegate; +pub struct Delegate(PhantomData); // We can't use V:LatticeValue, much as I would like to, // because frequently the pattern is that V=Option for some @@ -102,14 +103,14 @@ pub struct Node { impl UnificationTable { pub fn new() -> UnificationTable { 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 { - Snapshot { marker: marker::CovariantType::, + Snapshot { marker: marker::PhantomData::, snapshot: self.values.start_snapshot() } } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index e13a5672778..56c5928a132 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -147,18 +147,12 @@ struct LanguageItemCollector<'a> { 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); @@ -312,12 +306,13 @@ pub fn collect_language_items(krate: &ast::Crate, 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; diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index d4fe0979313..e58136fb3f4 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -1119,7 +1119,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode) // 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) => { @@ -1143,7 +1143,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode) } else { succ }; - let succ = self.propagate_through_exprs(&args[], succ); + let succ = self.propagate_through_exprs(&args[..], succ); self.propagate_through_expr(&**f, succ) } @@ -1156,11 +1156,11 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode) } 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) => { diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 2f0462ab8c3..e539f6ae6cb 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -407,7 +407,7 @@ pub fn mark_as_terminating_scope(&self, scope_id: CodeExtent) { pub fn opt_encl_scope(&self, id: CodeExtent) -> Option { //! 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 diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index e91d7d8c52c..3ba08c10320 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -562,7 +562,7 @@ pub fn early_bound_lifetimes<'a>(generics: &'a ast::Generics) -> Vec bool { } pub fn self_ty(&self) -> Option> { - self.types.get_self().map(|&t| t) + self.types.get_self().cloned() } pub fn with_self_ty(&self, self_ty: Ty<'tcx>) -> Substs<'tcx> { diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index 3a7522cafee..e199a60c370 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -10,24 +10,27 @@ //! 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={}, \ @@ -35,28 +38,68 @@ pub fn impl_can_satisfy(infcx: &InferCtxt, 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 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>, + Vec>) +{ + 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> { diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 57c9fa7a4d9..a63dcfc24a1 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -28,6 +28,7 @@ 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; @@ -270,16 +271,6 @@ pub struct VtableObjectData<'tcx> { 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>, diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs index b2701ae875c..f10f7eb3951 100644 --- a/src/librustc/middle/traits/object_safety.rs +++ b/src/librustc/middle/traits/object_safety.rs @@ -20,7 +20,7 @@ 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; @@ -31,6 +31,10 @@ pub enum ObjectSafetyViolation<'tcx> { /// Self : Sized declared on the trait SizedSelf, + /// Supertrait reference references `Self` an in illegal location + /// (e.g. `trait Foo : Bar`) + SupertraitSelf, + /// Method has something illegal Method(Rc>, MethodViolationCode), } @@ -57,7 +61,7 @@ pub fn is_object_safe<'tcx>(tcx: &ty::ctxt<'tcx>, { // 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(|| { @@ -110,6 +114,9 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>, 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), @@ -118,6 +125,35 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'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 @@ -138,11 +174,7 @@ fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>, .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(..) | @@ -295,8 +327,17 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String { 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, + } +} diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index 027415de998..0e298920841 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -132,6 +132,7 @@ pub enum MethodMatchedData { /// 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), @@ -736,7 +737,7 @@ fn check_candidate_cache(&mut self, { 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, @@ -793,8 +794,6 @@ fn assemble_candidates<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result, SelectionError<'tcx>> { - // Check for overflow. - let TraitObligationStack { obligation, .. } = *stack; let mut candidates = SelectionCandidateSet { @@ -802,6 +801,14 @@ fn assemble_candidates<'o>(&mut self, 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. @@ -996,7 +1003,7 @@ fn assemble_candidates_from_caller_bounds<'o>(&mut self, let all_bounds = util::transitive_bounds( - self.tcx(), &caller_trait_refs[]); + self.tcx(), &caller_trait_refs[..]); let matching_bounds = all_bounds.filter( @@ -1521,7 +1528,7 @@ fn builtin_bound(&mut self, 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) } @@ -1629,6 +1636,7 @@ fn confirm_candidate(&mut self, try!(self.confirm_builtin_candidate(obligation, builtin_bound)))) } + PhantomFnCandidate | ErrorCandidate => { Ok(VtableBuiltin(VtableBuiltinData { nested: VecPerParamSpace::empty() })) } @@ -2295,6 +2303,7 @@ fn derived_cause(&self, 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)), diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index e3eda02b0a8..e9908397f97 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -68,15 +68,16 @@ 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; @@ -958,11 +959,18 @@ fn eq(&self, other: &TyS<'tcx>) -> bool { } impl<'tcx> Eq for TyS<'tcx> {} +#[cfg(stage0)] impl<'tcx, S: Writer + Hasher> Hash 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(&self, s: &mut H) { + (self as *const _).hash(s) + } +} pub type Ty<'tcx> = &'tcx TyS<'tcx>; @@ -980,15 +988,22 @@ fn eq(&self, other: &InternedTy<'tcx>) -> bool { impl<'tcx> Eq for InternedTy<'tcx> {} +#[cfg(stage0)] impl<'tcx, S: Writer + Hasher> Hash 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(&self, s: &mut H) { + self.ty.sty.hash(s) + } +} -impl<'tcx> BorrowFrom> for sty<'tcx> { - fn borrow_from<'a>(ty: &'a InternedTy<'tcx>) -> &'a sty<'tcx> { - &ty.ty.sty +impl<'tcx> Borrow> for InternedTy<'tcx> { + fn borrow<'a>(&'a self) -> &'a sty<'tcx> { + &self.ty.sty } } @@ -2004,6 +2019,40 @@ fn as_predicate(&self) -> Predicate<'tcx> { } 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> { + 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(), @@ -2331,7 +2380,7 @@ pub fn trait_did(&self, cx: &ctxt) -> ast::DefId { }; match result { Ok(trait_did) => trait_did, - Err(err) => cx.sess.fatal(&err[]), + Err(err) => cx.sess.fatal(&err[..]), } } } @@ -2665,7 +2714,7 @@ fn add_sty(&mut self, st: &sty) { } &ty_tup(ref ts) => { - self.add_tys(&ts[]); + self.add_tys(&ts[..]); } &ty_bare_fn(_, ref f) => { @@ -2836,7 +2885,7 @@ pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>, 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 { @@ -2959,6 +3008,13 @@ pub fn walk_children(&'tcx self) -> TypeWalker<'tcx> { assert_eq!(r, Some(self)); walker } + + pub fn as_opt_param_ty(&self) -> Option { + 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) @@ -3451,7 +3507,7 @@ fn tc_ty<'tcx>(cx: &ctxt<'tcx>, 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) { @@ -3474,14 +3530,14 @@ fn tc_ty<'tcx>(cx: &ctxt<'tcx>, } 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) @@ -3805,7 +3861,7 @@ fn are_inner_types_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span, -> 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. @@ -4112,7 +4168,7 @@ pub fn positional_element_ty<'tcx>(cx: &ctxt<'tcx>, variant: Option) -> Option> { 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) @@ -4933,7 +4989,7 @@ pub fn note_and_explain_type_err(cx: &ctxt, err: &type_err) { } pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option { - 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) @@ -4944,7 +5000,7 @@ 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( @@ -6600,7 +6656,7 @@ fn accum_substs(accumulator: &mut Vec, substs: &Substs) { } /// 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, @@ -6625,7 +6681,7 @@ pub fn with_freevars(tcx: &ty::ctxt, fid: ast::NodeId, f: F) -> T where { match tcx.freevars.borrow().get(&fid) { None => f(&[]), - Some(d) => f(&d[]) + Some(d) => f(&d[..]) } } diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index ee3fd681a00..60a9ffc7d2e 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -55,7 +55,7 @@ pub fn check_crate(krate: &ast::Crate, pub fn link_name(attrs: &[ast::Attribute]) -> Option { lang_items::extract(attrs).and_then(|name| { - $(if &name[] == stringify!($name) { + $(if &name[..] == stringify!($name) { Some(InternedString::new(stringify!($sym))) } else)* { None diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index 1895cbcb542..b3bc898748f 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -111,19 +111,19 @@ fn dylink_registrar(&mut self, // 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[..]) } }; diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index 5768539b2cd..93a25de0491 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -629,7 +629,7 @@ pub fn build_configuration(sess: &Session) -> ast::CrateConfig { append_configuration(&mut user_cfg, InternedString::new("test")) } let mut v = user_cfg.into_iter().collect::>(); - v.push_all(&default_cfg[]); + v.push_all(&default_cfg[..]); v } @@ -824,7 +824,7 @@ pub fn parse_cfgspecs(cfgspecs: Vec ) -> ast::CrateConfig { 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; @@ -923,7 +923,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { 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| { @@ -981,7 +981,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options { --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, @@ -1119,7 +1119,7 @@ fn test_switch_implies_cfg_test() { 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 diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index bd44dbe78f5..c1c55188875 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -75,13 +75,13 @@ pub fn fatal(&self, msg: &str) -> ! { } 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) } } diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs index d3d0f56c3ce..c9d50b9cecf 100644 --- a/src/librustc/util/common.rs +++ b/src/librustc/util/common.rs @@ -13,7 +13,8 @@ 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; @@ -144,11 +145,54 @@ pub fn block_query

(b: &ast::Block, p: P) -> bool where P: FnMut(&ast::Expr) - /// 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(edges_map: &HashMap, S>, source: T, destination: T) -> bool where S: HashState, ::Hasher: Hasher, - T: Hash< ::Hasher> + Eq + Clone, + T: Hash<::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, V, S, H: Hasher +/// +/// 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(edges_map: &HashMap, S>, source: T, + destination: T) -> bool + where S: HashState, T: Hash + Eq + Clone, { if source == destination { return true; @@ -206,12 +250,57 @@ pub fn can_reach(edges_map: &HashMap, S>, source: T, /// } /// ``` #[inline(always)] +#[cfg(stage0)] pub fn memoized(cache: &RefCell>, arg: T, f: F) -> U where T: Clone + Hash<::Hasher> + Eq, U: Clone, S: HashState, ::Hasher: Hasher, 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>( +/// cache: &RefCell, +/// f: &|T| -> U +/// ) -> impl |T| -> U { +/// ``` +/// but currently it is not possible. +/// +/// # Example +/// ``` +/// struct Context { +/// cache: RefCell> +/// } +/// +/// 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(cache: &RefCell>, 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()); diff --git a/src/librustc/util/lev_distance.rs b/src/librustc/util/lev_distance.rs index ca1bb7d7a94..10a7b2abea8 100644 --- a/src/librustc/util/lev_distance.rs +++ b/src/librustc/util/lev_distance.rs @@ -48,7 +48,7 @@ fn test_lev_distance() { 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"; diff --git a/src/librustc/util/nodemap.rs b/src/librustc/util/nodemap.rs index f8e3defe19d..1b07ce789e7 100644 --- a/src/librustc/util/nodemap.rs +++ b/src/librustc/util/nodemap.rs @@ -15,7 +15,8 @@ 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 = HashMap>; @@ -27,12 +28,22 @@ pub type NodeSet = FnvHashSet; pub type DefIdSet = FnvHashSet; +#[cfg(stage0)] pub fn FnvHashMap + Eq, V>() -> FnvHashMap { Default::default() } +#[cfg(stage0)] pub fn FnvHashSet + Eq>() -> FnvHashSet { Default::default() } +#[cfg(not(stage0))] +pub fn FnvHashMap() -> FnvHashMap { + Default::default() +} +#[cfg(not(stage0))] +pub fn FnvHashSet() -> FnvHashSet { + Default::default() +} pub fn NodeMap() -> NodeMap { FnvHashMap() } pub fn DefIdMap() -> DefIdMap { FnvHashMap() } @@ -52,12 +63,14 @@ impl Default for FnvHasher { 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; @@ -68,3 +81,16 @@ fn write(&mut self, bytes: &[u8]) { *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 } +} diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index d54199a679a..1d46c011bb3 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -28,7 +28,8 @@ 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; @@ -292,7 +293,7 @@ fn bare_fn_to_string<'tcx>(cx: &ctxt<'tcx>, 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 => { } @@ -376,7 +377,7 @@ fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String { .iter() .map(|elem| ty_to_string(cx, *elem)) .collect::>(); - match &strs[] { + match &strs[..] { [ref string] => format!("({},)", string), strs => format!("({})", strs.connect(", ")) } @@ -508,13 +509,26 @@ pub fn parameterized<'tcx,GG>(cx: &ctxt<'tcx>, // 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() @@ -625,7 +639,7 @@ fn repr(&self, tcx: &ctxt<'tcx>) -> String { impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for OwnedSlice { fn repr(&self, tcx: &ctxt<'tcx>) -> String { - repr_vec(tcx, &self[]) + repr_vec(tcx, &self[..]) } } @@ -633,7 +647,7 @@ fn repr(&self, tcx: &ctxt<'tcx>) -> String { // autoderef cannot convert the &[T] handler impl<'tcx, T:Repr<'tcx>> Repr<'tcx> for Vec { fn repr(&self, tcx: &ctxt<'tcx>) -> String { - repr_vec(tcx, &self[]) + repr_vec(tcx, &self[..]) } } @@ -673,7 +687,7 @@ fn user_string(&self, tcx: &ctxt<'tcx>) -> String { &base, trait_ref.substs, trait_ref.def_id, - &projection_bounds[], + &projection_bounds[..], || ty::lookup_trait_def(tcx, trait_ref.def_id).generics.clone()) } } @@ -1259,7 +1273,7 @@ fn user_string(&self, tcx: &ctxt<'tcx>) -> String { } }) }); - 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 { @@ -1420,6 +1434,7 @@ fn repr(&self, tcx: &ctxt<'tcx>) -> String { } } +#[cfg(stage0)] impl<'tcx, S, K, V> Repr<'tcx> for HashMap where K: Hash<::Hasher> + Eq + Repr<'tcx>, V: Repr<'tcx>, @@ -1435,6 +1450,21 @@ fn repr(&self, tcx: &ctxt<'tcx>) -> String { } } +#[cfg(not(stage0))] +impl<'tcx, S, K, V> Repr<'tcx> for HashMap + 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::>() + .connect(", ")) + } +} + impl<'tcx, T, U> Repr<'tcx> for ty::OutlivesPredicate where T : Repr<'tcx> + TypeFoldable<'tcx>, U : Repr<'tcx> + TypeFoldable<'tcx>, diff --git a/src/librustc_back/archive.rs b/src/librustc_back/archive.rs index b779963a219..c45ee258342 100644 --- a/src/librustc_back/archive.rs +++ b/src/librustc_back/archive.rs @@ -53,7 +53,7 @@ fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option, 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); @@ -84,7 +84,7 @@ fn run_ar(handler: &ErrorHandler, maybe_ar_prog: &Option, 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"); @@ -101,10 +101,10 @@ pub fn find_library(name: &str, osprefix: &str, ossuffix: &str, 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 } } } @@ -192,12 +192,12 @@ pub fn add_rlib(&mut self, rlib: &Path, name: &str, // 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 @@ -234,7 +234,7 @@ pub fn build(self) -> Archive<'a> { // 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; } @@ -254,7 +254,7 @@ pub fn build(self) -> Archive<'a> { // 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); @@ -269,7 +269,7 @@ pub fn build(self) -> Archive<'a> { // 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 } @@ -312,7 +312,7 @@ fn add_archive(&mut self, archive: &Path, name: &str, } 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)); } diff --git a/src/librustc_back/rpath.rs b/src/librustc_back/rpath.rs index 36bbd4b9872..e7419d4bec3 100644 --- a/src/librustc_back/rpath.rs +++ b/src/librustc_back/rpath.rs @@ -40,12 +40,9 @@ pub fn get_rpath_flags(config: RPathConfig) -> Vec where debug!("preparing the RPATH!"); let libs = config.used_crates.clone(); - let libs = libs.into_iter().filter_map(|(_, l)| { - l.map(|p| p.clone()) - }).collect::>(); - - let rpaths = get_rpaths(config, &libs[]); - flags.push_all(&rpaths_to_flags(&rpaths[])[]); + let libs = libs.into_iter().filter_map(|(_, l)| l).collect::>(); + let rpaths = get_rpaths(config, &libs[..]); + flags.push_all(&rpaths_to_flags(&rpaths[..])); flags } @@ -82,14 +79,14 @@ fn log_rpaths(desc: &str, rpaths: &[String]) { } } - 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; } @@ -139,7 +136,7 @@ fn minimize_rpaths(rpaths: &[String]) -> Vec { 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()); } } diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index 692e6b474fd..01a5f0d6e20 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -254,18 +254,18 @@ pub fn from_json(obj: Json) -> Target { 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() ) diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index a18e8b16e8b..abe01d193b4 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -656,7 +656,7 @@ fn check_for_move_of_borrowed_path(&self, &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", diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs index bee1ada28e3..c873831cb0f 100644 --- a/src/librustc_borrowck/borrowck/fragments.rs +++ b/src/librustc_borrowck/borrowck/fragments.rs @@ -38,7 +38,7 @@ enum Fragment { // 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), } @@ -198,11 +198,11 @@ pub fn fixup_fragment_sets<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) { // 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 { @@ -222,14 +222,14 @@ pub fn fixup_fragment_sets<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) { 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 { @@ -247,16 +247,16 @@ pub fn fixup_fragment_sets<'tcx>(this: &MoveData<'tcx>, tcx: &ty::ctxt<'tcx>) { 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; @@ -437,7 +437,7 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>, 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[..]) } } } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 93d97a054a4..518e4bc472c 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -137,7 +137,7 @@ fn borrowck_fn(this: &mut BorrowckCtxt, check_loans::check_loans(this, &loan_dfcx, flowed_moves, - &all_loans[], + &all_loans[..], id, decl, body); diff --git a/src/librustc_borrowck/graphviz.rs b/src/librustc_borrowck/graphviz.rs index 56bf3ae7fd5..39c9d9ba6ad 100644 --- a/src/librustc_borrowck/graphviz.rs +++ b/src/librustc_borrowck/graphviz.rs @@ -89,7 +89,7 @@ fn build_set(&self, 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 }); diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs index c2677cc3fd0..b7cfda28092 100644 --- a/src/librustc_borrowck/lib.rs +++ b/src/librustc_borrowck/lib.rs @@ -20,7 +20,6 @@ #![allow(non_camel_case_types)] #![feature(core)] -#![feature(hash)] #![feature(int_uint)] #![feature(quote)] #![feature(rustc_diagnostic_macros)] diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 728ff647599..a260997f605 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -85,7 +85,7 @@ macro_rules! controller_entry_point{($point: ident, $make_state: expr) => ({ let expanded_crate = match phase_2_configure_and_expand(&sess, krate, - &id[], + &id[..], addl_plugins) { None => return, Some(k) => k @@ -99,20 +99,20 @@ macro_rules! controller_entry_point{($point: ident, $make_state: expr) => ({ &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, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index ac91a0098ea..2550432c810 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -272,7 +272,7 @@ fn early_callback(&mut self, -> Compilation { match matches.opt_str("explain") { Some(ref code) => { - match descriptions.find_description(&code[]) { + match descriptions.find_description(&code[..]) { Some(ref description) => { println!("{}", description); } @@ -582,7 +582,7 @@ fn sort_lint_groups(lints: Vec<(&'static str, Vec, bool)>) 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"); }; @@ -612,7 +612,7 @@ fn sort_lint_groups(lints: Vec<(&'static str, Vec, bool)>) let desc = to.into_iter().map(|x| x.as_str().replace("_", "-")) .collect::>().connect(", "); println!(" {} {}", - padded(&name[]), desc); + padded(&name[..]), desc); } println!("\n"); }; @@ -678,7 +678,7 @@ pub fn handle_options(mut args: Vec) -> Option { } 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, @@ -803,7 +803,7 @@ pub fn monitor(f: F) { "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() { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 5dfef6c775e..0fbfa5fd89d 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -383,7 +383,7 @@ fn all_matching_node_ids<'a, 'ast>(&'a self, map: &'a ast_map::Map<'ast>) ItemViaNode(node_id) => NodesMatchingDirect(Some(node_id).into_iter()), ItemViaPath(ref parts) => - NodesMatchingSuffix(map.nodes_matching_suffix(&parts[])), + NodesMatchingSuffix(map.nodes_matching_suffix(&parts[..])), } } @@ -395,7 +395,7 @@ fn to_one_node_id(self, user_option: &str, sess: &Session, map: &ast_map::Map) - user_option, self.reconstructed_input(), is_wrong_because); - sess.fatal(&message[]) + sess.fatal(&message[..]) }; let mut saw_node = ast::DUMMY_NODE_ID; @@ -522,7 +522,7 @@ pub fn pretty_print_input(sess: Session, 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 } @@ -541,7 +541,7 @@ pub fn pretty_print_input(sess: Session, }; 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); @@ -632,8 +632,8 @@ pub fn pretty_print_input(sess: Session, // 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[..]) } } } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 7105a6cc488..fbbd72e2c76 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -254,7 +254,7 @@ pub fn t_fn(&self, 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 { @@ -278,7 +278,7 @@ pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> { 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, diff --git a/src/librustc_llvm/archive_ro.rs b/src/librustc_llvm/archive_ro.rs index d3555e4c043..14a99026aac 100644 --- a/src/librustc_llvm/archive_ro.rs +++ b/src/librustc_llvm/archive_ro.rs @@ -30,7 +30,7 @@ impl ArchiveRO { /// raised. pub fn open(dst: &Path) -> Option { 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 @@ -44,7 +44,7 @@ pub fn open(dst: &Path) -> Option { 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() { diff --git a/src/librustc_llvm/lib.rs b/src/librustc_llvm/lib.rs index aa90d7c851b..09a187befb2 100644 --- a/src/librustc_llvm/lib.rs +++ b/src/librustc_llvm/lib.rs @@ -25,7 +25,6 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(core)] -#![feature(hash)] #![feature(int_uint)] #![feature(libc)] #![feature(link_args)] @@ -2149,7 +2148,7 @@ fn drop(&mut self) { } 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()) } } diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs index 96e146fc894..5662a74a53d 100644 --- a/src/librustc_privacy/lib.rs +++ b/src/librustc_privacy/lib.rs @@ -585,10 +585,10 @@ fn report_error(&self, result: CheckResult) -> bool { 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 => {}, } @@ -690,7 +690,7 @@ fn check_field(&mut self, 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. diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 874c8f2a940..333d32d76b6 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -20,7 +20,6 @@ #![feature(alloc)] #![feature(collections)] #![feature(core)] -#![feature(hash)] #![feature(int_uint)] #![feature(rustc_diagnostic_macros)] #![feature(rustc_private)] @@ -1072,7 +1071,7 @@ fn resolve_imports_for_module(&mut self, module: Rc) { &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. @@ -1102,7 +1101,7 @@ fn path_names_to_string(&self, path: &Path) -> String { .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, @@ -1166,7 +1165,7 @@ fn resolve_import_for_module(&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. @@ -1175,7 +1174,7 @@ fn resolve_import_for_module(&mut self, 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) { @@ -1768,7 +1767,7 @@ fn check_for_conflicting_import(&mut self, ValueNS => "value", }, &token::get_name(name)); - span_err!(self.session, import_span, E0252, "{}", &msg[]); + span_err!(self.session, import_span, E0252, "{}", &msg[..]); } Some(_) | None => {} } @@ -1783,7 +1782,7 @@ fn check_that_import_is_importable(&mut self, 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[..]); } } @@ -1804,7 +1803,7 @@ fn check_for_conflicts_between_imports_and_items(&mut self, 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 => {} } @@ -1826,7 +1825,7 @@ fn check_for_conflicts_between_imports_and_items(&mut self, 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"); @@ -1844,7 +1843,7 @@ fn check_for_conflicts_between_imports_and_items(&mut self, 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") @@ -1857,7 +1856,7 @@ fn check_for_conflicts_between_imports_and_items(&mut self, 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") } @@ -1866,7 +1865,7 @@ fn check_for_conflicts_between_imports_and_items(&mut self, 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") @@ -1920,18 +1919,15 @@ fn resolve_module_path_from_root(&mut self, -> ResolveResult<(Rc, LastPrivate)> { fn search_parent_externals(needle: Name, module: &Rc) -> Option> { - 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_; @@ -1953,7 +1949,7 @@ fn search_parent_externals(needle: Name, module: &Rc) 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, @@ -2066,7 +2062,7 @@ fn resolve_module_path(&mut self, 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 `{}`", @@ -2369,11 +2365,11 @@ fn resolve_module_prefix(&mut self, 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. @@ -2384,7 +2380,7 @@ fn resolve_module_prefix(&mut self, // 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 {}", @@ -2515,7 +2511,7 @@ fn report_unresolved_imports(&mut self, module_: Rc) { } else { let err = format!("unresolved import (maybe you meant `{}::*`?)", sn); - self.resolve_error((*imports)[index].span, &err[]); + self.resolve_error((*imports)[index].span, &err[..]); } } @@ -2853,7 +2849,7 @@ fn resolve_item(&mut self, item: &Item) { generics, implemented_traits, &**self_type, - &impl_items[]); + &impl_items[..]); } ItemTrait(_, ref generics, ref bounds, ref trait_items) => { @@ -3196,7 +3192,7 @@ fn resolve_trait_reference(&mut self, }; 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 { @@ -3624,7 +3620,7 @@ fn resolve_type(&mut self, ty: &Ty) { 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[..]); } } } @@ -3825,7 +3821,7 @@ struct or enum variant", 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[..]); } } } @@ -4082,7 +4078,7 @@ fn resolve_module_relative_path(&mut self, let last_private; let module = self.current_module.clone(); match self.resolve_module_path(module, - &module_path[], + &module_path[..], UseLexicalScope, path.span, PathSearch) { @@ -4140,7 +4136,7 @@ fn resolve_crate_relative_path(&mut self, let containing_module; let last_private; match self.resolve_module_path_from_root(root_module, - &module_path[], + &module_path[..], 0, path.span, PathSearch, @@ -4150,7 +4146,7 @@ fn resolve_crate_relative_path(&mut self, 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) } }; @@ -4309,7 +4305,7 @@ fn get_module(this: &mut Resolver, span: Span, name_path: &[ast::Name]) } } else { match this.resolve_module_path(root, - &name_path[], + &name_path[..], UseLexicalScope, span, PathSearch) { @@ -4347,7 +4343,7 @@ fn get_module(this: &mut Resolver, span: Span, name_path: &[ast::Name]) let name_path = path.segments.iter().map(|seg| seg.identifier.name).collect::>(); // 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); @@ -4568,7 +4564,7 @@ fn resolve_expr(&mut self, expr: &Expr) { 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[..]); } } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 9f26e9182ab..ef849bb3dca 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -127,7 +127,7 @@ pub fn find_crate_name(sess: Option<&Session>, attrs: &[ast::Attribute], input: &Input) -> String { let validate = |s: String, span: Option| { - creader::validate_crate_name(sess, &s[], span); + creader::validate_crate_name(sess, &s[..], span); s }; @@ -141,11 +141,11 @@ pub fn find_crate_name(sess: Option<&Session>, 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); @@ -195,7 +195,7 @@ fn symbol_hash<'tcx>(tcx: &ty::ctxt<'tcx>, 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)[]); @@ -262,7 +262,7 @@ pub fn sanitize(s: &str) -> String { 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; @@ -331,17 +331,17 @@ pub fn mangle_exported_name<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, path: PathEl 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 { @@ -541,7 +541,7 @@ fn link_rlib<'a>(sess: &'a Session, 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 => {} } @@ -619,7 +619,7 @@ fn link_rlib<'a>(sess: &'a Session, 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())[]) @@ -678,7 +678,7 @@ fn write_rlib_bytecode_object_v1(writer: &mut T, 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 @@ -733,7 +733,7 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) { 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()); @@ -769,7 +769,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, // 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(), @@ -798,7 +798,7 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool, 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()); @@ -868,7 +868,7 @@ fn link_args(cmd: &mut Command, 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"]); } @@ -993,7 +993,7 @@ fn link_args(cmd: &mut Command, 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"); @@ -1029,7 +1029,7 @@ fn link_args(cmd: &mut Command, // 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 @@ -1086,14 +1086,14 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) { } 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 { @@ -1106,7 +1106,7 @@ fn add_local_native_libraries(cmd: &mut Command, sess: &Session) { cmd.arg(format!("-l{}", l)); } cstore::NativeFramework => { - cmd.arg("-framework").arg(&l[]); + cmd.arg("-framework").arg(&l[..]); } cstore::NativeStatic => unreachable!(), } @@ -1248,7 +1248,7 @@ fn add_dynamic_crate(cmd: &mut Command, sess: &Session, cratepath: Path) { let mut v = "-l".as_bytes().to_vec(); v.push_all(unlib(&sess.target, cratepath.filestem().unwrap())); - cmd.arg(&v[]); + cmd.arg(&v[..]); } } @@ -1290,7 +1290,7 @@ fn add_upstream_native_libraries(cmd: &mut Command, sess: &Session) { } cstore::NativeFramework => { cmd.arg("-framework"); - cmd.arg(&lib[]); + cmd.arg(&lib[..]); } cstore::NativeStatic => { sess.bug("statics shouldn't be propagated"); diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index 0331b6171f3..0a0f2a9c186 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -132,7 +132,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, bc_decoded.len() as libc::size_t) { write::llvm_err(sess.diagnostic().handler(), format!("failed to load bc of `{}`", - &name[])); + &name[..])); } }); } @@ -140,7 +140,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef, // Internalize everything but the reachable symbols of the current module let cstrs: Vec = 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(); diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 9934d9993d6..86b720d3fc1 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -22,7 +22,7 @@ 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; @@ -47,14 +47,14 @@ pub fn llvm_err(handler: &diagnostic::Handler, msg: String) -> ! { 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[..])[]); } } } @@ -67,7 +67,7 @@ pub fn write_output_file( 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 { @@ -105,7 +105,7 @@ fn dump(&mut self, handler: &Handler) { Some(ref code) => { handler.emit_with_code(None, &diag.msg[], - &code[], + &code[..], diag.lvl); }, None => { @@ -165,7 +165,7 @@ fn get_llvm_opt_level(optimize: config::OptLevel) -> llvm::CodeGenOptLevel { 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 { @@ -198,7 +198,7 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef { 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[] }; @@ -221,13 +221,13 @@ fn create_target_machine(sess: &Session) -> TargetMachineRef { 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, @@ -365,7 +365,7 @@ struct HandlerFreeVars<'a> { 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) { @@ -380,7 +380,7 @@ struct HandlerFreeVars<'a> { } 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 { @@ -424,7 +424,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, 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()); } @@ -440,7 +440,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, // 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")); } @@ -453,7 +453,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, } 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)); } @@ -477,7 +477,7 @@ unsafe fn optimize_and_codegen(cgcx: &CodegenContext, 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()); } }, @@ -511,7 +511,7 @@ unsafe fn with_codegen(tm: TargetMachineRef, 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()); } @@ -519,7 +519,7 @@ unsafe fn with_codegen(tm: TargetMachineRef, 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()); }) @@ -711,7 +711,7 @@ pub fn run_passes(sess: &Session, }; 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"); @@ -829,12 +829,12 @@ pub fn run_passes(sess: &Session, 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[..])); } } @@ -960,7 +960,7 @@ fn run_work_multithreaded(sess: &Session, 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)); @@ -975,7 +975,7 @@ pub fn run_assembler(sess: &Session, outputs: &OutputFilenames) { 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(); } }, @@ -1004,7 +1004,7 @@ unsafe fn configure_llvm(sess: &Session) { 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); }; diff --git a/src/librustc_trans/lib.rs b/src/librustc_trans/lib.rs index 4606200d058..3deca436a1f 100644 --- a/src/librustc_trans/lib.rs +++ b/src/librustc_trans/lib.rs @@ -28,7 +28,6 @@ #![feature(box_syntax)] #![feature(collections)] #![feature(core)] -#![feature(hash)] #![feature(int_uint)] #![feature(old_io)] #![feature(env)] diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index cdcd917ee5e..8d2a2d51ee4 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -155,7 +155,7 @@ fn write_sub_paths(&mut self, path: &ast::Path, global: bool) { }; self.fmt.sub_mod_ref_str(path.span, *span, - &qualname[], + &qualname[..], self.cur_scope); } } @@ -178,7 +178,7 @@ fn write_sub_paths_truncated(&mut self, path: &ast::Path, global: bool) { }; self.fmt.sub_mod_ref_str(path.span, *span, - &qualname[], + &qualname[..], self.cur_scope); } } @@ -197,7 +197,7 @@ fn write_sub_path_trait_truncated(&mut self, path: &ast::Path) { 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 { @@ -207,7 +207,7 @@ fn write_sub_path_trait_truncated(&mut self, path: &ast::Path) { for &(ref span, ref qualname) in sub_paths { self.fmt.sub_mod_ref_str(path.span, *span, - &qualname[], + &qualname[..], self.cur_scope); } } @@ -280,7 +280,7 @@ fn process_formals(&mut self, formals: &Vec, qualname: &str) { id, qualname, &path_to_string(p)[], - &typ[]); + &typ[..]); } self.collected_paths.clear(); } @@ -356,7 +356,7 @@ fn process_method(&mut self, method: &ast::Method) { }; 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, @@ -436,9 +436,9 @@ fn process_struct_field_def(&mut self, 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 {}", @@ -470,7 +470,7 @@ fn process_generic_params(&mut self, self.fmt.typedef_str(full_span, Some(*param_ss), param.id, - &name[], + &name[..], ""); } self.visit_generics(generics); @@ -487,10 +487,10 @@ fn process_fn(&mut self, 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 { @@ -504,7 +504,7 @@ fn process_fn(&mut self, // 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, @@ -526,8 +526,8 @@ fn process_static(&mut self, sub_span, item.id, &get_ident(item.ident), - &qualname[], - &value[], + &qualname[..], + &value[..], &ty_to_string(&*typ)[], self.cur_scope); @@ -549,7 +549,7 @@ fn process_const(&mut self, sub_span, item.id, &get_ident(item.ident), - &qualname[], + &qualname[..], "", &ty_to_string(&*typ)[], self.cur_scope); @@ -575,17 +575,17 @@ fn process_struct(&mut self, 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, @@ -598,9 +598,9 @@ 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)[]), @@ -619,9 +619,9 @@ fn process_enum(&mut self, 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); @@ -637,9 +637,9 @@ fn process_enum(&mut self, 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 { @@ -650,7 +650,7 @@ fn process_enum(&mut self, } } - 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, @@ -724,9 +724,9 @@ fn process_trait(&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 { @@ -758,7 +758,7 @@ fn process_trait(&mut self, } // 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) } @@ -776,9 +776,9 @@ fn process_mod(&mut self, 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)); } @@ -990,7 +990,7 @@ fn process_method_call(&mut self, 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) { @@ -1164,7 +1164,7 @@ fn visit_item(&mut self, item: &ast::Item) { item.id, cnum, name, - &location[], + &location[..], self.cur_scope); } ast::ItemFn(ref decl, _, _, ref ty_params, ref body) => @@ -1196,8 +1196,8 @@ fn visit_item(&mut self, item: &ast::Item) { 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); @@ -1260,7 +1260,7 @@ fn visit_trait_item(&mut self, tm: &ast::TraitItem) { }; 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, @@ -1401,7 +1401,7 @@ fn visit_expr(&mut self, ex: &ast::Expr) { 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 { @@ -1464,7 +1464,7 @@ fn visit_arm(&mut self, arm: &ast::Arm) { Some(p.span), id, &path_to_string(p)[], - &value[], + &value[..], "") } def::DefVariant(..) | def::DefTy(..) | def::DefStruct(..) => { @@ -1520,8 +1520,8 @@ fn visit_local(&mut self, l: &ast::Local) { sub_span, id, &path_to_string(p)[], - &value[], - &typ[]); + &value[..], + &typ[..]); } self.collected_paths.clear(); @@ -1603,7 +1603,7 @@ pub fn process_crate(sess: &Session, cur_scope: 0 }; - visitor.dump_crate_info(&cratename[], krate); + visitor.dump_crate_info(&cratename[..], krate); visit::walk_crate(&mut visitor, krate); } diff --git a/src/librustc_trans/save/recorder.rs b/src/librustc_trans/save/recorder.rs index 3bd04ed29d4..08e36bb1d85 100644 --- a/src/librustc_trans/save/recorder.rs +++ b/src/librustc_trans/save/recorder.rs @@ -43,7 +43,7 @@ pub fn dump_span(&mut self, 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[..]); } } @@ -170,14 +170,14 @@ pub fn make_values_str(&self, 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 })) } @@ -205,9 +205,9 @@ pub fn record_without_span(&mut self, }; 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, @@ -238,7 +238,7 @@ 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, diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index b0ed6f9e727..2826afb71a2 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -566,7 +566,7 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>( 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) ) } @@ -987,7 +987,7 @@ fn compile_submatch<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>, if has_nested_bindings(m, col) { let expanded = expand_nested_bindings(bcx, m, col, val); compile_submatch_continue(bcx, - &expanded[], + &expanded[..], vals, chk, col, @@ -1233,10 +1233,10 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } 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); } @@ -1255,8 +1255,8 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, } _ => { compile_submatch(else_cx, - &defaults[], - &vals_left[], + &defaults[..], + &vals_left[..], chk, has_genuine_default); } @@ -1468,7 +1468,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>, && 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 { @@ -1482,7 +1482,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>, 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; } diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index ddd720f1e84..eaf6eaa2f08 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -155,7 +155,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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); @@ -167,13 +167,13 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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::>(); - 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); @@ -187,7 +187,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // (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); } @@ -219,7 +219,7 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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); } @@ -320,10 +320,10 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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) } @@ -453,9 +453,9 @@ fn mk_struct<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, .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), @@ -659,7 +659,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, // 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; @@ -682,10 +682,10 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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 } } @@ -763,7 +763,7 @@ pub fn trans_get_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, 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) @@ -851,7 +851,7 @@ pub fn trans_set_discr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, r: &Repr<'tcx>, } 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) } @@ -933,7 +933,7 @@ pub fn struct_field_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, st: &Struct<'tcx>, v let val = if needs_cast { let ccx = bcx.ccx(); let fields = st.fields.iter().map(|&ty| type_of::type_of(ccx, ty)).collect::>(); - 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 @@ -972,7 +972,7 @@ pub fn fold_variants<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, let fields = case.fields.iter().map(|&ty| type_of::type_of(bcx.ccx(), ty)).collect::>(); - 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); @@ -1045,18 +1045,18 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr } 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 { @@ -1080,7 +1080,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, r: &Repr<'tcx>, discr }).collect::>(); C_struct(ccx, &build_const_struct(ccx, nonnull, - &vals[])[], + &vals[..])[], false) } } diff --git a/src/librustc_trans/trans/asm.rs b/src/librustc_trans/trans/asm.rs index e419be65fc4..a3bd0cf6b1a 100644 --- a/src/librustc_trans/trans/asm.rs +++ b/src/librustc_trans/trans/asm.rs @@ -71,7 +71,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) callee::DontAutorefArg) }) }).collect::>(); - 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); @@ -91,18 +91,18 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) 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(); @@ -112,7 +112,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) } 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 { @@ -120,8 +120,8 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm) 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(), diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 7f7b5cd8006..3091c852f55 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -86,7 +86,7 @@ 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; @@ -186,7 +186,7 @@ fn drop(&mut self) { 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()) }; @@ -247,7 +247,7 @@ fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>, 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 @@ -340,7 +340,7 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId, 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 @@ -523,7 +523,7 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty::mk_nil(ccx.tcx())); get_extern_fn(ccx, &mut *ccx.externs().borrow_mut(), - &name[], + &name[..], llvm::CCallConv, llty, dtor_ty) @@ -898,14 +898,14 @@ pub fn trans_external_path<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, 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[..]) } } } @@ -947,7 +947,7 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llresult = Invoke(bcx, llfn, - &llargs[], + &llargs[..], normal_bcx.llbb, landing_pad, Some(attributes), @@ -961,7 +961,7 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llresult = Call(bcx, llfn, - &llargs[], + &llargs[..], Some(attributes), debug_loc); return (llresult, bcx); @@ -1219,19 +1219,6 @@ pub fn alloca_zeroed<'blk, 'tcx>(cx: Block<'blk, 'tcx>, ty: Ty<'tcx>, 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 { @@ -1646,7 +1633,7 @@ fn copy_closure_args_to_allocas<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, "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 \ @@ -1834,12 +1821,12 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, 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 { @@ -1855,7 +1842,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg_scope, &decl.inputs[], arg_datums, - &monomorphized_arg_types[]) + &monomorphized_arg_types[..]) } }; @@ -2000,7 +1987,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, bcx = expr::trans_adt(bcx, result_ty, disr, - &fields[], + &fields[..], None, expr::SaveIn(llresult), debug_loc); @@ -2070,7 +2057,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx 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"); @@ -2315,7 +2302,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { ast::ItemImpl(_, _, ref generics, _, _, ref impl_items) => { meth::trans_impl(ccx, item.ident, - &impl_items[], + &impl_items[..], generics, item.id); } @@ -2430,7 +2417,7 @@ fn register_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, _ => 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 } @@ -2475,7 +2462,7 @@ pub fn get_fn_llvm_attributes<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty< 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") @@ -2611,7 +2598,7 @@ pub fn register_fn_llvmty(ccx: &CrateContext, 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()))); @@ -2667,7 +2654,7 @@ fn create_entry_fn(ccx: &CrateContext, 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) @@ -2783,12 +2770,12 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { } 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()); @@ -2826,7 +2813,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef { §)[]); } unsafe { - let buf = CString::from_slice(sect.as_bytes()); + let buf = CString::new(sect.as_bytes()).unwrap(); llvm::LLVMSetSection(v, buf.as_ptr()); } }, @@ -2988,12 +2975,12 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec { 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()) @@ -3001,7 +2988,7 @@ pub fn write_metadata(cx: &SharedCrateContext, krate: &ast::Crate) -> Vec { 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; @@ -3039,8 +3026,8 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet) { 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); } } @@ -3056,8 +3043,8 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet) { 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); @@ -3211,7 +3198,7 @@ pub fn trans_crate<'tcx>(analysis: ty::CrateAnalysis<'tcx>) 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 { diff --git a/src/librustc_trans/trans/builder.rs b/src/librustc_trans/trans/builder.rs index e268c2f0d5c..8199e6189c9 100644 --- a/src/librustc_trans/trans/builder.rs +++ b/src/librustc_trans/trans/builder.rs @@ -431,7 +431,7 @@ pub fn alloca(&self, ty: Type, name: &str) -> ValueRef { 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()) } @@ -567,7 +567,7 @@ pub fn gepi(&self, base: ValueRef, ixs: &[uint]) -> ValueRef { } else { let v = ixs.iter().map(|i| C_i32(self.ccx, *i as i32)).collect::>(); self.count_insn("gepi"); - self.inbounds_gep(base, &v[]) + self.inbounds_gep(base, &v[..]) } } @@ -775,8 +775,8 @@ pub fn add_span_comment(&self, sp: Span, text: &str) { let s = format!("{} ({})", text, self.ccx.sess().codemap().span_to_string(sp)); - debug!("{}", &s[]); - self.add_comment(&s[]); + debug!("{}", &s[..]); + self.add_comment(&s[..]); } } @@ -786,7 +786,7 @@ pub fn add_comment(&self, text: &str) { 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, @@ -813,7 +813,7 @@ pub fn inline_asm_call(&self, asm: *const c_char, cons: *const c_char, }).collect::>(); 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); diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index bda8b8938b7..3d3e35cd776 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -323,7 +323,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( let llfn = decl_internal_rust_fn(ccx, tuple_fn_ty, - &function_name[]); + &function_name[..]); // let empty_substs = tcx.mk_substs(Substs::trans_empty()); @@ -359,7 +359,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( 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); @@ -792,7 +792,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, // Invoke the actual rust fn and update bcx/llresult. let (llret, b) = base::invoke(bcx, llfn, - &llargs[], + &llargs[..], callee_ty, debug_loc); bcx = b; @@ -833,7 +833,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, callee_ty, llfn, opt_llretslot.unwrap(), - &llargs[], + &llargs[..], arg_tys, debug_loc); } diff --git a/src/librustc_trans/trans/cleanup.rs b/src/librustc_trans/trans/cleanup.rs index 1c831090e3e..85e53618f6d 100644 --- a/src/librustc_trans/trans/cleanup.rs +++ b/src/librustc_trans/trans/cleanup.rs @@ -764,7 +764,7 @@ fn trans_cleanups_to_exit_scope(&'blk self, 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() { @@ -811,7 +811,7 @@ fn get_or_create_landing_pad(&'blk self) -> BasicBlockRef { 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); } } diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs index f92df999e60..1d4bbd79d71 100644 --- a/src/librustc_trans/trans/closure.rs +++ b/src/librustc_trans/trans/closure.rs @@ -158,7 +158,7 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc 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); @@ -208,7 +208,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, let function_type = typer.closure_type(closure_id, param_substs); let freevars: Vec = - 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); @@ -221,7 +221,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>, &[], 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 diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index ac9a982f298..a9cda94beba 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -488,7 +488,7 @@ pub fn new_block(&'a self, opt_node_id: Option) -> 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()); @@ -757,7 +757,7 @@ pub fn C_integral(t: Type, u: u64, sign_extend: bool) -> ValueRef { 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()) } } @@ -835,7 +835,8 @@ pub fn C_cstr(cx: &CrateContext, s: InternedString, null_terminated: bool) -> Va !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); @@ -1161,8 +1162,8 @@ pub fn langcall(bcx: Block, 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[..]), } } } diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 86f5589556a..7705b53ee38 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -75,7 +75,7 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit) 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); @@ -611,8 +611,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } 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); @@ -642,9 +642,9 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } }).collect::>(); 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[..]) } }) } @@ -655,9 +655,9 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, .collect::>(); // 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) => { @@ -671,9 +671,9 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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(_) => { @@ -715,14 +715,14 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } 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, _)) => { @@ -733,7 +733,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, adt::trans_const(cx, &*repr, vinfo.disr_val, - &arg_vals[]) + &arg_vals[..]) } _ => cx.sess().span_bug(e.span, "expected a struct or variant def") } diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs index 96506291b5a..eb07bdb7ba1 100644 --- a/src/librustc_trans/trans/context.rs +++ b/src/librustc_trans/trans/context.rs @@ -225,15 +225,15 @@ fn next(&mut self) -> Option<(CrateContext<'a, 'tcx>, bool)> { 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) } @@ -288,7 +288,7 @@ pub fn new(crate_name: &str, // 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); } diff --git a/src/librustc_trans/trans/controlflow.rs b/src/librustc_trans/trans/controlflow.rs index e6cd44676ce..26e12a1af40 100644 --- a/src/librustc_trans/trans/controlflow.rs +++ b/src/librustc_trans/trans/controlflow.rs @@ -177,7 +177,7 @@ pub fn trans_if<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, } 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); @@ -378,7 +378,7 @@ pub fn trans_fail<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, 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); @@ -407,7 +407,7 @@ pub fn trans_fail_bounds_check<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, 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); diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 23498089c58..fc0129239aa 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -299,7 +299,7 @@ fn register_unique_id_with_metadata(&mut self, 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[..])[]); } } @@ -380,14 +380,14 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>, 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('*'); @@ -397,7 +397,7 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>, 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('&'); @@ -407,7 +407,7 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>, 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 { @@ -421,7 +421,7 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>, 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 "); @@ -452,7 +452,7 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>, 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(','); } @@ -465,7 +465,7 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>, 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("!"); @@ -538,7 +538,7 @@ fn from_def_id_and_substs<'a, 'tcx>(type_map: &mut TypeMap<'tcx>, 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(','); } @@ -568,7 +568,7 @@ fn get_unique_type_id_of_closure_type<'a>(&mut self, 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(','); } @@ -582,7 +582,7 @@ fn get_unique_type_id_of_closure_type<'a>(&mut self, 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("!"); @@ -806,11 +806,11 @@ pub fn create_global_var_metadata(cx: &CrateContext, 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, @@ -1287,7 +1287,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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. @@ -1366,7 +1366,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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 { @@ -1379,8 +1379,8 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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), @@ -1451,7 +1451,7 @@ fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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>, @@ -1486,7 +1486,7 @@ 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(","); @@ -1501,7 +1501,7 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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), @@ -1525,7 +1525,7 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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(","); @@ -1535,7 +1535,7 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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), @@ -1552,7 +1552,7 @@ fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, name_to_append_suffix_to.push('>'); - return create_DIArray(DIB(cx), &template_params[]); + return create_DIArray(DIB(cx), &template_params[..]); } } @@ -1601,7 +1601,7 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor { path_bytes.insert(1, prefix[1]); } - CString::from_vec(path_bytes) + CString::new(path_bytes).unwrap() } _ => fallback_path(cx) } @@ -1614,8 +1614,8 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor { (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 { @@ -1632,7 +1632,7 @@ fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor { }; 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() } } @@ -1646,7 +1646,7 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, 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); @@ -1658,7 +1658,7 @@ fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, 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}, _) => { @@ -1724,8 +1724,8 @@ fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile { 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()) @@ -1800,7 +1800,7 @@ fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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), @@ -1820,7 +1820,7 @@ fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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), @@ -1959,7 +1959,7 @@ fn finalize<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> MetadataCreationResult { set_members_of_composite_type(cx, metadata_stub, llvm_type, - &member_descriptions[]); + &member_descriptions[..]); return MetadataCreationResult::new(metadata_stub, true); } } @@ -2031,7 +2031,7 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let struct_metadata_stub = create_struct_stub(cx, struct_llvm_type, - &struct_name[], + &struct_name[..], unique_type_id, containing_scope); @@ -2098,7 +2098,7 @@ fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, unique_type_id, create_struct_stub(cx, tuple_llvm_type, - &tuple_name[], + &tuple_name[..], unique_type_id, UNKNOWN_SCOPE_METADATA), tuple_llvm_type, @@ -2158,7 +2158,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>) 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, @@ -2191,7 +2191,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>) set_members_of_composite_type(cx, variant_type_metadata, variant_llvm_type, - &member_descriptions[]); + &member_descriptions[..]); vec![ MemberDescription { name: "".to_string(), @@ -2291,7 +2291,7 @@ fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>) 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. @@ -2445,7 +2445,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, .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), @@ -2475,7 +2475,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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), @@ -2518,8 +2518,8 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, .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), @@ -2644,7 +2644,8 @@ fn set_members_of_composite_type(cx: &CrateContext, 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), @@ -2662,7 +2663,7 @@ fn set_members_of_composite_type(cx: &CrateContext, .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); } } @@ -2681,8 +2682,8 @@ fn create_struct_stub(cx: &CrateContext, 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 @@ -2763,7 +2764,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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 { @@ -2789,7 +2790,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, let metadata = composite_type_metadata(cx, slice_llvm_type, - &slice_type_name[], + &slice_type_name[..], unique_type_id, &member_descriptions, UNKNOWN_SCOPE_METADATA, @@ -2838,7 +2839,7 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, llvm::LLVMDIBuilderCreateSubroutineType( DIB(cx), UNKNOWN_FILE_METADATA, - create_DIArray(DIB(cx), &signature_metadata[])) + create_DIArray(DIB(cx), &signature_metadata[..])) }, false); } @@ -2864,7 +2865,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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[..])[]); } }; @@ -2878,7 +2879,7 @@ fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, composite_type_metadata(cx, trait_llvm_type, - &trait_type_name[], + &trait_type_name[..], unique_type_id, &[], containing_scope, @@ -2998,7 +2999,7 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty::ty_tup(ref elements) => { prepare_tuple_metadata(cx, t, - &elements[], + &elements[..], unique_type_id, usage_site_span).finalize(cx) } @@ -3022,9 +3023,9 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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[..]); } }; @@ -3037,9 +3038,9 @@ fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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 => { @@ -3128,7 +3129,7 @@ fn contains_nodebug_attribute(attributes: &[ast::Attribute]) -> bool { 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 } }) @@ -3971,8 +3972,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc 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), @@ -4020,7 +4020,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc(bcx: Block<'blk, 'tcx>, 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, @@ -1118,7 +1118,7 @@ fn make_field(field_name: &str, expr: P) -> ast::Field { trans_adt(bcx, expr_ty(bcx, expr), 0, - &numbered_fields[], + &numbered_fields[..], None, dest, expr.debug_loc()) @@ -1153,13 +1153,13 @@ fn make_field(field_name: &str, expr: P) -> ast::Field { trans_overloaded_call(bcx, expr, &**f, - &args[], + &args[..], Some(dest)) } else { callee::trans_call(bcx, expr, &**f, - callee::ArgExprs(&args[]), + callee::ArgExprs(&args[..]), dest) } } @@ -1167,7 +1167,7 @@ fn make_field(field_name: &str, expr: P) -> ast::Field { callee::trans_method_call(bcx, expr, &*args[0], - callee::ArgExprs(&args[]), + callee::ArgExprs(&args[..]), dest) } ast::ExprBinary(op, ref lhs, ref rhs) => { @@ -1197,7 +1197,7 @@ fn make_field(field_name: &str, expr: P) -> ast::Field { 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)); @@ -1354,11 +1354,11 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>, 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) => { @@ -1378,7 +1378,7 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>, 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 \ diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs index 8f0e4e647b5..4508fe21a65 100644 --- a/src/librustc_trans/trans/foreign.rs +++ b/src/librustc_trans/trans/foreign.rs @@ -135,7 +135,7 @@ pub fn register_static(ccx: &CrateContext, }; 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); @@ -148,7 +148,7 @@ pub fn register_static(ccx: &CrateContext, // 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); @@ -158,7 +158,7 @@ pub fn register_static(ccx: &CrateContext, } 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()) } } @@ -238,7 +238,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, _ => 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, @@ -370,7 +370,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, let llforeign_retval = CallWithConv(bcx, llfn, - &llargs_foreign[], + &llargs_foreign[..], cc, Some(attrs), call_debug_loc); @@ -611,7 +611,7 @@ fn build_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, 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 @@ -974,7 +974,7 @@ fn lltype_for_fn_from_foreign_types(ccx: &CrateContext, tys: &ForeignTypes) -> T 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) } } diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index af90e1ec5c5..268b65c6ceb 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -170,7 +170,7 @@ pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Val 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 => { @@ -304,7 +304,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, 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 @@ -513,7 +513,7 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) 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()) @@ -541,7 +541,7 @@ fn declare_generic_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, 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); } diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs index 5687247561e..a1b66ed94f0 100644 --- a/src/librustc_trans/trans/intrinsic.rs +++ b/src/librustc_trans/trans/intrinsic.rs @@ -166,7 +166,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, 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) => { @@ -274,13 +274,13 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, 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)); @@ -307,7 +307,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, }; 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) } diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs index 30797344da8..ec48ab0d34a 100644 --- a/src/librustc_trans/trans/monomorphize.rs +++ b/src/librustc_trans/trans/monomorphize.rs @@ -131,7 +131,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, hash = format!("h{}", state.finish()); ccx.tcx().map.with_path(fn_id.node, |path| { - exported_name(path, &hash[]) + exported_name(path, &hash[..]) }) }; @@ -141,9 +141,9 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, 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); @@ -182,7 +182,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, 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, &[]); } @@ -206,7 +206,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, trans_enum_variant(ccx, parent, &*v, - &args[], + &args[..], this_tv.disr_val, psubsts, d); diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index 456e27967f5..7b59e0258ee 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -171,33 +171,27 @@ pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, 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() @@ -426,49 +420,27 @@ pub fn iter_vec_loop<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>, 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 } diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs index e3e4ca62c26..ad83135a0d4 100644 --- a/src/librustc_trans/trans/type_.rs +++ b/src/librustc_trans/trans/type_.rs @@ -163,7 +163,7 @@ pub fn struct_(ccx: &CrateContext, els: &[Type], packed: bool) -> Type { } 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())) } diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index 9d1c0fadefc..489b56bbe68 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -67,7 +67,7 @@ pub fn untuple_arguments_if_necessary<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, abi: abi::Abi) -> Vec> { if abi != abi::RustCall { - return inputs.iter().map(|x| (*x).clone()).collect() + return inputs.iter().cloned().collect() } if inputs.len() == 0 { @@ -144,7 +144,7 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, 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 @@ -332,7 +332,7 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty 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 @@ -343,7 +343,7 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty // 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, ..}) => { @@ -399,7 +399,7 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> 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[..]) } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 0183b3474a5..e3c1c66f78c 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -404,17 +404,30 @@ fn create_substs_for_ast_path<'tcx>( 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"); } } @@ -1139,14 +1152,14 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, 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 @@ -1185,7 +1198,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>, 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) { @@ -1424,7 +1437,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>, // 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); @@ -1623,7 +1636,7 @@ fn conv_ty_poly_trait_ref<'tcx>( 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() { diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs index 0d30741978a..34c52981b79 100644 --- a/src/librustc_typeck/check/_match.rs +++ b/src/librustc_typeck/check/_match.rs @@ -162,7 +162,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, 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) => { diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs index 7354ea7377c..0ad15456df9 100644 --- a/src/librustc_typeck/check/callee.rs +++ b/src/librustc_typeck/check/callee.rs @@ -256,7 +256,7 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, check_argument_types(fcx, call_expr.span, &fn_sig.inputs, - &expected_arg_tys[], + &expected_arg_tys[..], arg_exprs, AutorefArgs::No, fn_sig.variadic, diff --git a/src/librustc_typeck/check/implicator.rs b/src/librustc_typeck/check/implicator.rs index da25719baaa..4aaaf4ffe5a 100644 --- a/src/librustc_typeck/check/implicator.rs +++ b/src/librustc_typeck/check/implicator.rs @@ -329,6 +329,9 @@ fn accumulate_from_adt(&mut self, 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); } @@ -340,6 +343,9 @@ fn accumulate_from_assoc_types_transitive(&mut self, fn accumulate_from_assoc_types(&mut self, trait_ref: Rc>) { + 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<_> = @@ -347,6 +353,8 @@ fn accumulate_from_assoc_types(&mut self, .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; } diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 82bd4ae87ff..978fbbbcffc 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -901,7 +901,7 @@ fn consider_candidates(&self, 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 => { } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 063300a1d72..1639772103b 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -172,7 +172,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, 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, @@ -218,7 +218,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, 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, @@ -306,10 +306,10 @@ pub fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> { // 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(..) => { diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3c2888e2278..e443b4d0e60 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -638,7 +638,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, // Remember return type so that regionck can access it later. let mut fn_sig_tys: Vec = arg_tys.iter() - .map(|&ty| ty) + .cloned() .collect(); if let ty::FnConverging(ret_ty) = ret_ty { @@ -2208,7 +2208,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, check_argument_types(fcx, sp, - &err_inputs[], + &err_inputs[..], &[], args_no_rcvr, autoref_args, @@ -2227,7 +2227,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, 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, @@ -3054,7 +3054,7 @@ fn check_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, 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 @@ -3154,7 +3154,7 @@ fn check_tup_field<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, 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 @@ -3219,7 +3219,7 @@ fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, 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( @@ -3327,7 +3327,7 @@ fn check_struct_constructor<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, class_id, id, fcx.ccx.tcx.mk_substs(struct_substs), - &class_fields[], + &class_fields[..], fields, base_expr.is_none(), None); @@ -3370,7 +3370,7 @@ fn check_struct_enum_variant<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, variant_id, id, fcx.ccx.tcx.mk_substs(substitutions), - &variant_fields[], + &variant_fields[..], fields, true, Some(enum_id)); @@ -3731,10 +3731,10 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, 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| { @@ -3821,7 +3821,7 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, 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 } }); @@ -3851,11 +3851,11 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, } 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)) => { @@ -3864,7 +3864,7 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, pprust::path_to_string(path)); check_struct_fields_on_error(fcx, id, - &fields[], + &fields[..], base_expr); def_id }, @@ -3877,7 +3877,7 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, id, expr.span, struct_did, - &fields[], + &fields[..], base_expr.as_ref().map(|e| &**e)); } _ => { @@ -3886,7 +3886,7 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, pprust::path_to_string(path)); check_struct_fields_on_error(fcx, id, - &fields[], + &fields[..], base_expr); } } @@ -5231,10 +5231,10 @@ fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> { } }; (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), @@ -5259,7 +5259,7 @@ fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> { "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, diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 4e5550a2106..82abff8c425 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -294,8 +294,8 @@ fn visit_fn_body(&mut self, 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); @@ -626,6 +626,20 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { 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); @@ -690,7 +704,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) { } ast::ExprMatch(ref discr, ref arms, _) => { - link_match(rcx, &**discr, &arms[]); + link_match(rcx, &**discr, &arms[..]); visit::walk_expr(rcx, expr); } diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 2e7eff68bd5..3666b69d1c6 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -126,6 +126,13 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>, "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, diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs index d124282d391..2601c4d2752 100644 --- a/src/librustc_typeck/check/wf.rs +++ b/src/librustc_typeck/check/wf.rs @@ -10,21 +10,22 @@ 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; @@ -38,6 +39,10 @@ pub fn new(ccx: &'ccx CrateCtxt<'ccx, 'tcx>) -> CheckTypeWellFormedVisitor<'ccx, 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: @@ -96,19 +101,29 @@ fn check_item_well_formed(&mut self, item: &ast::Item) { 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()); } _ => {} } @@ -276,6 +291,123 @@ fn check_impl(&mut self, } }); } + + 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) + { + 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) + { + 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. @@ -343,9 +475,9 @@ fn visit_fn(&mut self, 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) } _ => {} } @@ -359,14 +491,14 @@ fn visit_trait_item(&mut self, t: &'v ast::TraitItem) { &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); } diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 44e850a0738..0b78af18e26 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -87,6 +87,7 @@ trait hierarchy is only necessary for shorthands like `T::X` or 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; @@ -268,7 +269,7 @@ fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, 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(_) => { @@ -313,7 +314,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, trait_id, &trait_def.generics, &trait_predicates, - &trait_items[], + &trait_items[..], &m.id, &m.ident.name, &m.explicit_self, @@ -328,7 +329,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, trait_id, &trait_def.generics, &trait_predicates, - &trait_items[], + &trait_items[..], &m.id, &m.pe_ident().name, m.pe_explicit_self(), @@ -871,7 +872,7 @@ fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, 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), @@ -1358,7 +1359,7 @@ fn ty_generics_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>, 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) @@ -1960,51 +1961,15 @@ fn enforce_impl_ty_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>, 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, @@ -2025,11 +1990,4 @@ impl trait, self type, or predicates", } } } - - fn to_opt_param_ty<'tcx>(ty: Ty<'tcx>) -> Option { - match ty.sty { - ty::ty_param(ref d) => Some(d.clone()), - _ => None, - } - } } diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs new file mode 100644 index 00000000000..83d7e985000 --- /dev/null +++ b/src/librustc_typeck/constrained_type_params.rs @@ -0,0 +1,61 @@ +// 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 or the MIT license +// , 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>>, + input_parameters: &mut HashSet) +{ + 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; + } + } +} diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 7498dc8179d..b5dca0bd4f6 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -123,6 +123,7 @@ mod rscope; mod astconv; mod collect; +mod constrained_type_params; mod coherence; mod variance; diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index d5883d8bf86..1adcf133bf3 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -187,6 +187,22 @@ //! 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` is `V3 = V1.xform(V2)`. +//! +//! ### Constraints +//! +//! If I have a struct or enum with where clauses: +//! +//! struct Foo { ... } +//! +//! 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` that is upcast to `Foo`, 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` 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::*; @@ -199,7 +215,6 @@ 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; @@ -258,6 +273,11 @@ struct TermsContext<'a, 'tcx: 'a> { empty_variances: Rc, + // 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)>, + // Maps from the node id of a type/generic parameter to the // corresponding inferred index. inferred_map: NodeMap, @@ -269,7 +289,7 @@ struct TermsContext<'a, 'tcx: 'a> { #[derive(Copy, Debug, PartialEq)] enum ParamKind { TypeParam, - RegionParam + RegionParam, } struct InferredInfo<'a> { @@ -279,6 +299,11 @@ 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>, @@ -291,6 +316,8 @@ 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 { @@ -304,7 +331,78 @@ fn determine_parameters_to_be_inferred<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>, terms_cx } +fn lang_items(tcx: &ty::ctxt) -> Vec<(ast::NodeId,Vec)> { + 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, @@ -313,21 +411,48 @@ fn add_inferred(&mut self, 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 { @@ -339,44 +464,13 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> { 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); } @@ -404,16 +498,6 @@ fn visit_item(&mut self, item: &ast::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; 2], - covariant_lang_items: [Option; 2], - contravariant_lang_items: [Option; 2], - unsafe_cell_lang_item: Option, - // These are pointers to common `ConstantTerm` instances covariant: VarianceTermPtr<'a>, contravariant: VarianceTermPtr<'a>, @@ -433,40 +517,14 @@ struct Constraint<'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, @@ -487,7 +545,13 @@ fn visit_item(&mut self, item: &ast::Item) { 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 @@ -505,29 +569,48 @@ fn visit_item(&mut self, item: &ast::Item) { &**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(_) => {} } @@ -544,9 +627,10 @@ fn visit_item(&mut self, item: &ast::Item) { ast::ItemTy(..) | ast::ItemImpl(..) | ast::ItemMac(..) => { - visit::walk_item(self, item); } } + + visit::walk_item(self, item); } } @@ -648,15 +732,7 @@ fn declared_variance(&self, -> 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. @@ -724,6 +800,25 @@ fn xform(&mut self, } } + 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` @@ -731,7 +826,9 @@ fn add_constraints_from_ty(&mut self, 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 | @@ -754,6 +851,7 @@ fn add_constraints_from_ty(&mut self, self.add_constraints_from_ty(generics, typ, variance); } + ty::ty_ptr(ref mt) => { self.add_constraints_from_mt(generics, mt, variance); } @@ -797,27 +895,16 @@ fn add_constraints_from_ty(&mut self, } 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` 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); @@ -845,7 +932,12 @@ fn add_constraints_from_ty(&mut self, 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: {}", @@ -864,7 +956,10 @@ fn add_constraints_from_substs(&mut self, 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 = @@ -872,6 +967,8 @@ fn add_constraints_from_substs(&mut self, 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); } @@ -885,6 +982,51 @@ fn add_constraints_from_substs(&mut self, } } + 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, @@ -969,7 +1111,12 @@ struct SolveContext<'a, 'tcx: 'a> { 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, @@ -1034,20 +1181,16 @@ fn write(&self) { 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; } @@ -1065,7 +1208,7 @@ fn write(&self) { // 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() @@ -1144,3 +1287,4 @@ fn glb(v1: ty::Variance, v2: ty::Variance) -> ty::Variance { (x, ty::Bivariant) | (ty::Bivariant, x) => x, } } + diff --git a/src/librustdoc/flock.rs b/src/librustdoc/flock.rs index a7cf5eb8918..ad91c3cb2c3 100644 --- a/src/librustdoc/flock.rs +++ b/src/librustdoc/flock.rs @@ -112,7 +112,7 @@ pub struct Lock { 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) diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 6acd1537946..44c0acda66f 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -34,7 +34,7 @@ pub fn highlight(src: &str, class: Option<&str>, id: Option<&str>) -> String { 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`. diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index c513fe2e8eb..7ea5bd569e1 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -236,7 +236,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { 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()); }) } @@ -293,7 +293,7 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result { format!("{} ", sec) }); - let text = CString::from_vec(text.into_bytes()); + let text = CString::new(text).unwrap(); unsafe { hoedown_buffer_puts(ob, text.as_ptr()) } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 95994af7dc8..fc3c8738991 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -1404,8 +1404,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { try!(write!(fmt, r##" - [-] -  [+] + [-] [+] "##)); // Write `src` tag diff --git a/src/librustdoc/html/static/main.css b/src/librustdoc/html/static/main.css index a4263badb01..2f0755ecb89 100644 --- a/src/librustdoc/html/static/main.css +++ b/src/librustdoc/html/static/main.css @@ -374,8 +374,8 @@ a { 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; } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index bab734db126..f9e0948d7bc 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -23,7 +23,6 @@ #![feature(collections)] #![feature(core)] #![feature(env)] -#![feature(hash)] #![feature(int_uint)] #![feature(old_io)] #![feature(libc)] diff --git a/src/librustdoc/passes.rs b/src/librustdoc/passes.rs index abd73fcfb70..722f14fa6d4 100644 --- a/src/librustdoc/passes.rs +++ b/src/librustdoc/passes.rs @@ -293,7 +293,7 @@ fn fold_item(&mut self, i: Item) -> Option { let mut a: Vec = 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)); } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index ac1a0285412..c52b0bab1fa 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -333,7 +333,7 @@ pub fn visit_item(&mut self, item: &ast::Item, 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, diff --git a/src/libserialize/collection_impls.rs b/src/libserialize/collection_impls.rs index f81edca8371..10cf02f85e8 100644 --- a/src/libserialize/collection_impls.rs +++ b/src/libserialize/collection_impls.rs @@ -12,16 +12,17 @@ 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 { +> Encodable for LinkedList { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_seq(self.len(), |s| { for (i, e) in self.iter().enumerate() { @@ -32,10 +33,10 @@ fn encode(&self, s: &mut S) -> Result<(), S::Error> { } } -impl Decodable for DList { - fn decode(d: &mut D) -> Result, D::Error> { +impl Decodable for LinkedList { + fn decode(d: &mut D) -> Result, 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)))); } @@ -44,7 +45,7 @@ fn decode(d: &mut D) -> Result, D::Error> { } } -impl Encodable for RingBuf { +impl Encodable for VecDeque { fn encode(&self, s: &mut S) -> Result<(), S::Error> { s.emit_seq(self.len(), |s| { for (i, e) in self.iter().enumerate() { @@ -55,10 +56,10 @@ fn encode(&self, s: &mut S) -> Result<(), S::Error> { } } -impl Decodable for RingBuf { - fn decode(d: &mut D) -> Result, D::Error> { +impl Decodable for VecDeque { + fn decode(d: &mut D) -> Result, D::Error> { d.read_seq(|d, len| { - let mut deque: RingBuf = RingBuf::new(); + let mut deque: VecDeque = VecDeque::new(); for i in 0..len { deque.push_back(try!(d.read_seq_elt(i, |d| Decodable::decode(d)))); } @@ -157,6 +158,7 @@ fn decode(d: &mut D) -> Result, D::Error> { } } +#[cfg(stage0)] impl Encodable for HashMap where K: Encodable + Hash< ::Hasher> + Eq, V: Encodable, @@ -175,7 +177,26 @@ fn encode(&self, e: &mut E) -> Result<(), E::Error> { }) } } +#[cfg(not(stage0))] +impl Encodable for HashMap + where K: Encodable + Hash + Eq, + V: Encodable, + S: HashState, +{ + fn encode(&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 Decodable for HashMap where K: Decodable + Hash< ::Hasher> + Eq, V: Decodable, @@ -195,7 +216,27 @@ fn decode(d: &mut D) -> Result, D::Error> { }) } } +#[cfg(not(stage0))] +impl Decodable for HashMap + where K: Decodable + Hash + Eq, + V: Decodable, + S: HashState + Default, +{ + fn decode(d: &mut D) -> Result, 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 Encodable for HashSet where T: Encodable + Hash< ::Hasher> + Eq, S: HashState, @@ -212,7 +253,24 @@ fn encode(&self, s: &mut E) -> Result<(), E::Error> { }) } } +#[cfg(not(stage0))] +impl Encodable for HashSet + where T: Encodable + Hash + Eq, + S: HashState, +{ + fn encode(&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 Decodable for HashSet where T: Decodable + Hash< ::Hasher> + Eq, S: HashState + Default, @@ -229,6 +287,22 @@ fn decode(d: &mut D) -> Result, D::Error> { }) } } +#[cfg(not(stage0))] +impl Decodable for HashSet + where T: Decodable + Hash + Eq, + S: HashState + Default, +{ + fn decode(d: &mut D) -> Result, 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 Encodable for VecMap { fn encode(&self, e: &mut S) -> Result<(), S::Error> { diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 68b28784b42..a0f42815b43 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -1120,7 +1120,7 @@ pub fn is_string<'a>(&'a self) -> bool { /// 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 } } @@ -2237,7 +2237,7 @@ fn read_enum_variant(&mut self, names: &[&str], 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)) }; @@ -3461,7 +3461,7 @@ fn test_encode_hashmap_with_numeric_key() { 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 @@ -3477,7 +3477,7 @@ fn test_prettyencode_hashmap_with_numeric_key() { 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 @@ -3517,7 +3517,7 @@ fn indents(source: &str) -> uint { 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(); @@ -3549,7 +3549,7 @@ enum Enum { 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 = json::decode(&result).unwrap(); assert_eq!(map, decoded); } diff --git a/src/libserialize/lib.rs b/src/libserialize/lib.rs index 853da598ab5..d476fd72abc 100644 --- a/src/libserialize/lib.rs +++ b/src/libserialize/lib.rs @@ -31,7 +31,6 @@ #![feature(int_uint)] #![feature(old_io)] #![feature(old_path)] -#![feature(hash)] #![feature(rustc_private)] #![feature(staged_api)] #![feature(std_misc)] diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index 517907bcf58..70f0ba4bb23 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -326,7 +326,7 @@ fn encode(&self, s: &mut S) -> Result<(), S::Error> { impl Encodable for String { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_str(&self[]) + s.emit_str(&self[..]) } } diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index 1b9f8b99017..ade4f1f0533 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -14,12 +14,12 @@ 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}; @@ -440,12 +440,10 @@ fn into_option(self) -> Option> { } } -impl HashMap - where K: Eq + Hash, - S: HashState, - H: hash::Hasher +impl HashMap + where K: Eq + Hash, S: HashState { - fn make_hash(&self, x: &X) -> SafeHash where X: Hash { + fn make_hash(&self, x: &X) -> SafeHash where X: Hash { table::make_hash(&self.hash_state, x) } @@ -453,18 +451,18 @@ fn make_hash(&self, x: &X) -> SafeHash where X: Hash { /// If you already have the hash for the key lying around, use /// search_hashed. fn search<'a, Q: ?Sized>(&'a self, q: &Q) -> Option> - where Q: BorrowFrom + Eq + Hash + where K: Borrow, Q: Eq + Hash { let hash = self.make_hash(q); - search_hashed(&self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k))) + search_hashed(&self.table, hash, |k| q.eq(k.borrow())) .into_option() } fn search_mut<'a, Q: ?Sized>(&'a mut self, q: &Q) -> Option> - where Q: BorrowFrom + Eq + Hash + where K: Borrow, Q: Eq + Hash { let hash = self.make_hash(q); - search_hashed(&mut self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k))) + search_hashed(&mut self.table, hash, |k| q.eq(k.borrow())) .into_option() } @@ -490,7 +488,7 @@ fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) { } } -impl + Eq, V> HashMap { +impl HashMap { /// Create an empty HashMap. /// /// # Example @@ -520,10 +518,8 @@ pub fn with_capacity(capacity: usize) -> HashMap { } } -impl HashMap - where K: Eq + Hash, - S: HashState, - H: hash::Hasher +impl HashMap + where K: Eq + Hash, S: HashState { /// Creates an empty hashmap which will use the given hasher to hash keys. /// @@ -1037,7 +1033,7 @@ pub fn clear(&mut self) { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self, k: &Q) -> Option<&V> - where Q: Hash + Eq + BorrowFrom + where K: Borrow, Q: Hash + Eq { self.search(k).map(|bucket| bucket.into_refs().1) } @@ -1060,7 +1056,7 @@ pub fn get(&self, k: &Q) -> Option<&V> /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn contains_key(&self, k: &Q) -> bool - where Q: Hash + Eq + BorrowFrom + where K: Borrow, Q: Hash + Eq { self.search(k).is_some() } @@ -1086,7 +1082,7 @@ pub fn contains_key(&self, k: &Q) -> bool /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self, k: &Q) -> Option<&mut V> - where Q: Hash + Eq + BorrowFrom + where K: Borrow, Q: Hash + Eq { self.search_mut(k).map(|bucket| bucket.into_mut_refs().1) } @@ -1138,7 +1134,7 @@ pub fn insert(&mut self, k: K, v: V) -> Option { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, k: &Q) -> Option - where Q: Hash + Eq + BorrowFrom + where K: Borrow, Q: Hash + Eq { if self.table.size() == 0 { return None @@ -1195,10 +1191,8 @@ fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable, hash: SafeHas } } -impl PartialEq for HashMap - where K: Eq + Hash, V: PartialEq, - S: HashState, - H: hash::Hasher +impl PartialEq for HashMap + where K: Eq + Hash, V: PartialEq, S: HashState { fn eq(&self, other: &HashMap) -> bool { if self.len() != other.len() { return false; } @@ -1210,17 +1204,13 @@ fn eq(&self, other: &HashMap) -> bool { } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for HashMap - where K: Eq + Hash, V: Eq, - S: HashState, - H: hash::Hasher +impl Eq for HashMap + where K: Eq + Hash, V: Eq, S: HashState {} #[stable(feature = "rust1", since = "1.0.0")] -impl Debug for HashMap - where K: Eq + Hash + Debug, V: Debug, - S: HashState, - H: hash::Hasher +impl Debug for HashMap + where K: Eq + Hash + Debug, V: Debug, S: HashState { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "HashMap {{")); @@ -1235,10 +1225,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for HashMap - where K: Eq + Hash, - S: HashState + Default, - H: hash::Hasher +impl Default for HashMap + where K: Eq + Hash, + S: HashState + Default, { fn default() -> HashMap { HashMap::with_hash_state(Default::default()) @@ -1246,11 +1235,10 @@ fn default() -> HashMap { } #[stable(feature = "rust1", since = "1.0.0")] -impl Index for HashMap - where K: Eq + Hash, - Q: Eq + Hash + BorrowFrom, - S: HashState, - H: hash::Hasher +impl Index for HashMap + where K: Eq + Hash + Borrow, + Q: Eq + Hash, + S: HashState, { type Output = V; @@ -1261,11 +1249,10 @@ fn index<'a>(&'a self, index: &Q) -> &'a V { } #[stable(feature = "rust1", since = "1.0.0")] -impl IndexMut for HashMap - where K: Eq + Hash, - Q: Eq + Hash + BorrowFrom, - S: HashState, - H: hash::Hasher +impl IndexMut for HashMap + where K: Eq + Hash + Borrow, + Q: Eq + Hash, + S: HashState, { #[inline] fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V { @@ -1373,10 +1360,8 @@ enum VacantEntryState { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V, S, H> IntoIterator for &'a HashMap - where K: Eq + Hash, - S: HashState, - H: hash::Hasher +impl<'a, K, V, S> IntoIterator for &'a HashMap + where K: Eq + Hash, S: HashState { type Item = (&'a K, &'a V); type IntoIter = Iter<'a, K, V>; @@ -1387,10 +1372,8 @@ fn into_iter(self) -> Iter<'a, K, V> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V, S, H> IntoIterator for &'a mut HashMap - where K: Eq + Hash, - S: HashState, - H: hash::Hasher +impl<'a, K, V, S> IntoIterator for &'a mut HashMap + where K: Eq + Hash, S: HashState { type Item = (&'a K, &'a mut V); type IntoIter = IterMut<'a, K, V>; @@ -1401,10 +1384,8 @@ fn into_iter(mut self) -> IterMut<'a, K, V> { } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for HashMap - where K: Eq + Hash, - S: HashState, - H: hash::Hasher +impl IntoIterator for HashMap + where K: Eq + Hash, S: HashState { type Item = (K, V); type IntoIter = IntoIter; @@ -1550,12 +1531,11 @@ pub fn insert(self, value: V) -> &'a mut V { } #[stable(feature = "rust1", since = "1.0.0")] -impl FromIterator<(K, V)> for HashMap - where K: Eq + Hash, - S: HashState + Default, - H: hash::Hasher +impl FromIterator<(K, V)> for HashMap + where K: Eq + Hash, S: HashState + Default { - fn from_iter>(iter: T) -> HashMap { + fn from_iter>(iterable: T) -> HashMap { + let iter = iterable.into_iter(); let lower = iter.size_hint().0; let mut map = HashMap::with_capacity_and_hash_state(lower, Default::default()); @@ -1565,12 +1545,10 @@ fn from_iter>(iter: T) -> HashMap { } #[stable(feature = "rust1", since = "1.0.0")] -impl Extend<(K, V)> for HashMap - where K: Eq + Hash, - S: HashState, - H: hash::Hasher +impl Extend<(K, V)> for HashMap + where K: Eq + Hash, S: HashState { - fn extend>(&mut self, iter: T) { + fn extend>(&mut self, iter: T) { for (k, v) in iter { self.insert(k, v); } @@ -1606,9 +1584,9 @@ pub fn new() -> RandomState { #[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) } } @@ -1621,25 +1599,6 @@ fn default() -> RandomState { } } -/// 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::*; diff --git a/src/libstd/collections/hash/map_stage0.rs b/src/libstd/collections/hash/map_stage0.rs new file mode 100644 index 00000000000..f9e5044c597 --- /dev/null +++ b/src/libstd/collections/hash/map_stage0.rs @@ -0,0 +1,2330 @@ +// 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 or the MIT license +// , 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 { + // All hashes are keyed on these values, to prevent hash collision attacks. + hash_state: S, + + table: RawTable, + + resize_policy: DefaultResizePolicy, +} + +/// Search for a pre-hashed key. +fn search_hashed(table: M, + hash: SafeHash, + mut is_match: F) + -> SearchResult where + M: Deref>, + 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(starting_bucket: FullBucketMut) -> (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> but preserves +/// the reference that grants us access to the table in any case. +enum SearchResult { + // This is an entry that holds the given key: + FoundExisting(FullBucket), + + // There was no such entry. The reference is given back: + TableRef(M) +} + +impl SearchResult { + fn into_option(self) -> Option> { + match self { + FoundExisting(bucket) => Some(bucket), + TableRef(_) => None + } + } +} + +impl HashMap + where K: Eq + Hash, + S: HashState, + H: hash::Hasher +{ + fn make_hash(&self, x: &X) -> SafeHash where X: Hash { + 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> + where K: Borrow, Q: Eq + Hash + { + 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> + where K: Borrow, Q: Eq + Hash + { + 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 + Eq, V> HashMap { + /// 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 { + 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 { + HashMap::with_capacity_and_hash_state(capacity, Default::default()) + } +} + +impl HashMap + where K: Eq + Hash, + S: HashState, + H: hash::Hasher +{ + /// 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 { + 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 { + 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 = 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 = 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, _): (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((_, 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 { + 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 { + 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 { + fn last_two((_, 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 { + // 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 { + fn last_two((_, 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(&self, k: &Q) -> Option<&V> + where K: Borrow, Q: Hash + 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(&self, k: &Q) -> bool + where K: Borrow, Q: Hash + 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(&mut self, k: &Q) -> Option<&mut V> + where K: Borrow, Q: Hash + 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 { + 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(&mut self, k: &Q) -> Option + where K: Borrow, Q: Hash + 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, 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 PartialEq for HashMap + where K: Eq + Hash, V: PartialEq, + S: HashState, + H: hash::Hasher +{ + fn eq(&self, other: &HashMap) -> 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 Eq for HashMap + where K: Eq + Hash, V: Eq, + S: HashState, + H: hash::Hasher +{} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Debug for HashMap + where K: Eq + Hash + Debug, V: Debug, + S: HashState, + H: hash::Hasher +{ + 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 Default for HashMap + where K: Eq + Hash, + S: HashState + Default, + H: hash::Hasher +{ + fn default() -> HashMap { + HashMap::with_hash_state(Default::default()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Index for HashMap + where K: Eq + Hash + Borrow, + Q: Eq + Hash, + S: HashState, + H: hash::Hasher +{ + 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 IndexMut for HashMap + where K: Eq + Hash + Borrow, + Q: Eq + Hash, + S: HashState, + H: hash::Hasher +{ + #[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 { + inner: iter::Map, 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, 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, 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, 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>, +} + +/// 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>, +} + +/// 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 { + /// The index is occupied, but the key to insert has precedence, + /// and will kick the current one out on insertion. + NeqElem(FullBucket, usize), + /// The index is genuinely vacant. + NoElem(EmptyBucket), +} + +impl<'a, K, V, S, H> IntoIterator for &'a HashMap + where K: Eq + Hash, + S: HashState, + H: hash::Hasher +{ + 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 + where K: Eq + Hash, + S: HashState, + H: hash::Hasher +{ + 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 IntoIterator for HashMap + where K: Eq + Hash, + S: HashState, + H: hash::Hasher +{ + type Item = (K, V); + type IntoIter = IntoIter; + + fn into_iter(self) -> IntoIter { + 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) { 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) { 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 Iterator for IntoIter { + type Item = (K, V); + + #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() } + #[inline] fn size_hint(&self) -> (usize, Option) { self.inner.size_hint() } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + #[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) { 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) { 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) { 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 FromIterator<(K, V)> for HashMap + where K: Eq + Hash, + S: HashState + Default, + H: hash::Hasher +{ + fn from_iter>(iter: T) -> HashMap { + 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 Extend<(K, V)> for HashMap + where K: Eq + Hash, + S: HashState, + H: hash::Hasher +{ + fn extend>(&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> = 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 = 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 = 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) { + 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); + } + } +} diff --git a/src/libstd/collections/hash/mod.rs b/src/libstd/collections/hash/mod.rs index 47e300af269..39c1458b720 100644 --- a/src/libstd/collections/hash/mod.rs +++ b/src/libstd/collections/hash/mod.rs @@ -12,6 +12,14 @@ 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; diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs index 5fbbcb3b347..e0631a64d44 100644 --- a/src/libstd/collections/hash/set.rs +++ b/src/libstd/collections/hash/set.rs @@ -10,21 +10,21 @@ // // 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!) @@ -97,7 +97,7 @@ pub struct HashSet { map: HashMap } -impl + Eq> HashSet { +impl HashSet { /// Create an empty HashSet. /// /// # Example @@ -128,10 +128,8 @@ pub fn with_capacity(capacity: usize) -> HashSet { } } -impl HashSet - where T: Eq + Hash, - S: HashState, - H: hash::Hasher +impl HashSet + where T: Eq + Hash, S: HashState { /// Creates a new empty hash set which will use the given hasher to hash /// keys. @@ -462,7 +460,7 @@ pub fn clear(&mut self) { self.map.clear() } /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn contains(&self, value: &Q) -> bool - where Q: BorrowFrom + Hash + Eq + where T: Borrow, Q: Hash + Eq { self.map.contains_key(value) } @@ -572,17 +570,15 @@ pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()).is_none( /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, value: &Q) -> bool - where Q: BorrowFrom + Hash + Eq + where T: Borrow, Q: Hash + Eq { self.map.remove(value).is_some() } } #[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for HashSet - where T: Eq + Hash, - S: HashState, - H: hash::Hasher +impl PartialEq for HashSet + where T: Eq + Hash, S: HashState { fn eq(&self, other: &HashSet) -> bool { if self.len() != other.len() { return false; } @@ -592,17 +588,14 @@ fn eq(&self, other: &HashSet) -> bool { } #[stable(feature = "rust1", since = "1.0.0")] -impl Eq for HashSet - where T: Eq + Hash, - S: HashState, - H: hash::Hasher +impl Eq for HashSet + where T: Eq + Hash, S: HashState {} #[stable(feature = "rust1", since = "1.0.0")] -impl fmt::Debug for HashSet - where T: Eq + Hash + fmt::Debug, - S: HashState, - H: hash::Hasher +impl fmt::Debug for HashSet + where T: Eq + Hash + fmt::Debug, + S: HashState { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { try!(write!(f, "HashSet {{")); @@ -617,12 +610,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } #[stable(feature = "rust1", since = "1.0.0")] -impl FromIterator for HashSet - where T: Eq + Hash, - S: HashState + Default, - H: hash::Hasher +impl FromIterator for HashSet + where T: Eq + Hash, + S: HashState + Default, { - fn from_iter>(iter: I) -> HashSet { + fn from_iter>(iterable: I) -> HashSet { + 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); @@ -631,12 +624,11 @@ fn from_iter>(iter: I) -> HashSet { } #[stable(feature = "rust1", since = "1.0.0")] -impl Extend for HashSet - where T: Eq + Hash, - S: HashState, - H: hash::Hasher +impl Extend for HashSet + where T: Eq + Hash, + S: HashState, { - fn extend>(&mut self, iter: I) { + fn extend>(&mut self, iter: I) { for k in iter { self.insert(k); } @@ -644,10 +636,9 @@ fn extend>(&mut self, iter: I) { } #[stable(feature = "rust1", since = "1.0.0")] -impl Default for HashSet - where T: Eq + Hash, - S: HashState + Default, - H: hash::Hasher +impl Default for HashSet + where T: Eq + Hash, + S: HashState + Default, { #[stable(feature = "rust1", since = "1.0.0")] fn default() -> HashSet { @@ -656,10 +647,9 @@ fn default() -> HashSet { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S, H> BitOr<&'b HashSet> for &'a HashSet - where T: Eq + Hash + Clone, - S: HashState + Default, - H: hash::Hasher +impl<'a, 'b, T, S> BitOr<&'b HashSet> for &'a HashSet + where T: Eq + Hash + Clone, + S: HashState + Default, { type Output = HashSet; @@ -689,10 +679,9 @@ fn bitor(self, rhs: &HashSet) -> HashSet { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S, H> BitAnd<&'b HashSet> for &'a HashSet - where T: Eq + Hash + Clone, - S: HashState + Default, - H: hash::Hasher +impl<'a, 'b, T, S> BitAnd<&'b HashSet> for &'a HashSet + where T: Eq + Hash + Clone, + S: HashState + Default, { type Output = HashSet; @@ -722,10 +711,9 @@ fn bitand(self, rhs: &HashSet) -> HashSet { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S, H> BitXor<&'b HashSet> for &'a HashSet - where T: Eq + Hash + Clone, - S: HashState + Default, - H: hash::Hasher +impl<'a, 'b, T, S> BitXor<&'b HashSet> for &'a HashSet + where T: Eq + Hash + Clone, + S: HashState + Default, { type Output = HashSet; @@ -755,10 +743,9 @@ fn bitxor(self, rhs: &HashSet) -> HashSet { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, 'b, T, S, H> Sub<&'b HashSet> for &'a HashSet - where T: Eq + Hash + Clone, - S: HashState + Default, - H: hash::Hasher +impl<'a, 'b, T, S> Sub<&'b HashSet> for &'a HashSet + where T: Eq + Hash + Clone, + S: HashState + Default, { type Output = HashSet; @@ -836,10 +823,8 @@ pub struct Union<'a, T: 'a, S: 'a> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, S, H> IntoIterator for &'a HashSet - where T: Eq + Hash, - S: HashState, - H: hash::Hasher +impl<'a, T, S> IntoIterator for &'a HashSet + where T: Eq + Hash, S: HashState { type Item = &'a T; type IntoIter = Iter<'a, T>; @@ -850,10 +835,9 @@ fn into_iter(self) -> Iter<'a, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for HashSet - where T: Eq + Hash, - S: HashState, - H: hash::Hasher +impl IntoIterator for HashSet + where T: Eq + Hash, + S: HashState { type Item = T; type IntoIter = IntoIter; @@ -900,10 +884,8 @@ 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, - S: HashState, - H: hash::Hasher +impl<'a, T, S> Iterator for Intersection<'a, T, S> + where T: Eq + Hash, S: HashState { type Item = &'a T; @@ -925,10 +907,8 @@ fn size_hint(&self) -> (usize, Option) { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, S, H> Iterator for Difference<'a, T, S> - where T: Eq + Hash, - S: HashState, - H: hash::Hasher +impl<'a, T, S> Iterator for Difference<'a, T, S> + where T: Eq + Hash, S: HashState { type Item = &'a T; @@ -950,10 +930,8 @@ fn size_hint(&self) -> (usize, Option) { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, S> - where T: Eq + Hash, - S: HashState, - H: hash::Hasher +impl<'a, T, S> Iterator for SymmetricDifference<'a, T, S> + where T: Eq + Hash, S: HashState { type Item = &'a T; @@ -962,10 +940,8 @@ fn size_hint(&self) -> (usize, Option) { 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, - S: HashState, - H: hash::Hasher +impl<'a, T, S> Iterator for Union<'a, T, S> + where T: Eq + Hash, S: HashState { type Item = &'a T; diff --git a/src/libstd/collections/hash/set_stage0.rs b/src/libstd/collections/hash/set_stage0.rs new file mode 100644 index 00000000000..68c9e02d8ad --- /dev/null +++ b/src/libstd/collections/hash/set_stage0.rs @@ -0,0 +1,1252 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// 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 { + map: HashMap +} + +impl + Eq> HashSet { + /// Create an empty HashSet. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// let mut set: HashSet = HashSet::new(); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn new() -> HashSet { + 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 = HashSet::with_capacity(10); + /// ``` + #[inline] + #[stable(feature = "rust1", since = "1.0.0")] + pub fn with_capacity(capacity: usize) -> HashSet { + HashSet { map: HashMap::with_capacity(capacity) } + } +} + +impl HashSet + where T: Eq + Hash, + S: HashState, + H: hash::Hasher +{ + /// 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 { + 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 { + 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 = 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 = 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 = 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 { + 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 with a regular `.iter()`. + /// let v: Vec = 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 { + fn first((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 = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [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 = 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 = 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) -> 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 = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [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 = a.symmetric_difference(&b).map(|&x| x).collect(); + /// let diff2: HashSet = 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) + -> 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 = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [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 = 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) -> Intersection<'a, T, S> { + Intersection { + iter: self.iter(), + other: other, + } + } + + /// Visit the values representing the union. + /// + /// # Example + /// + /// ``` + /// use std::collections::HashSet; + /// let a: HashSet = [1, 2, 3].iter().map(|&x| x).collect(); + /// let b: HashSet = [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 = 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) -> 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 { + fn first((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(&self, value: &Q) -> bool + where T: Borrow, Q: Hash + 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) -> 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) -> 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) -> 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(&mut self, value: &Q) -> bool + where T: Borrow, Q: Hash + Eq + { + self.map.remove(value).is_some() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for HashSet + where T: Eq + Hash, + S: HashState, + H: hash::Hasher +{ + fn eq(&self, other: &HashSet) -> bool { + if self.len() != other.len() { return false; } + + self.iter().all(|key| other.contains(key)) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Eq for HashSet + where T: Eq + Hash, + S: HashState, + H: hash::Hasher +{} + +#[stable(feature = "rust1", since = "1.0.0")] +impl fmt::Debug for HashSet + where T: Eq + Hash + fmt::Debug, + S: HashState, + H: hash::Hasher +{ + 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 FromIterator for HashSet + where T: Eq + Hash, + S: HashState + Default, + H: hash::Hasher +{ + fn from_iter>(iter: I) -> HashSet { + 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 Extend for HashSet + where T: Eq + Hash, + S: HashState, + H: hash::Hasher +{ + fn extend>(&mut self, iter: I) { + for k in iter { + self.insert(k); + } + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl Default for HashSet + where T: Eq + Hash, + S: HashState + Default, + H: hash::Hasher +{ + #[stable(feature = "rust1", since = "1.0.0")] + fn default() -> HashSet { + HashSet::with_hash_state(Default::default()) + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, T, S, H> BitOr<&'b HashSet> for &'a HashSet + where T: Eq + Hash + Clone, + S: HashState + Default, + H: hash::Hasher +{ + type Output = HashSet; + + /// Returns the union of `self` and `rhs` as a new `HashSet`. + /// + /// # 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) -> HashSet { + self.union(rhs).cloned().collect() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, T, S, H> BitAnd<&'b HashSet> for &'a HashSet + where T: Eq + Hash + Clone, + S: HashState + Default, + H: hash::Hasher +{ + type Output = HashSet; + + /// Returns the intersection of `self` and `rhs` as a new `HashSet`. + /// + /// # 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) -> HashSet { + self.intersection(rhs).cloned().collect() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, T, S, H> BitXor<&'b HashSet> for &'a HashSet + where T: Eq + Hash + Clone, + S: HashState + Default, + H: hash::Hasher +{ + type Output = HashSet; + + /// Returns the symmetric difference of `self` and `rhs` as a new `HashSet`. + /// + /// # 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) -> HashSet { + self.symmetric_difference(rhs).cloned().collect() + } +} + +#[stable(feature = "rust1", since = "1.0.0")] +impl<'a, 'b, T, S, H> Sub<&'b HashSet> for &'a HashSet + where T: Eq + Hash + Clone, + S: HashState + Default, + H: hash::Hasher +{ + type Output = HashSet; + + /// Returns the difference of `self` and `rhs` as a new `HashSet`. + /// + /// # 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) -> HashSet { + 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 { + iter: Map, fn((K, ())) -> K> +} + +/// HashSet drain iterator +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Drain<'a, K: 'a> { + iter: Map, 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, +} + +/// 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, +} + +/// Symmetric difference iterator. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct SymmetricDifference<'a, T: 'a, S: 'a> { + iter: Chain, Difference<'a, T, S>> +} + +/// Set union iterator. +#[stable(feature = "rust1", since = "1.0.0")] +pub struct Union<'a, T: 'a, S: 'a> { + iter: Chain, Difference<'a, T, S>> +} + +impl<'a, T, S, H> IntoIterator for &'a HashSet + where T: Eq + Hash, + S: HashState, + H: hash::Hasher +{ + type Item = &'a T; + type IntoIter = Iter<'a, T>; + + fn into_iter(self) -> Iter<'a, T> { + self.iter() + } +} + +impl IntoIterator for HashSet + where T: Eq + Hash, + S: HashState, + H: hash::Hasher +{ + type Item = T; + type IntoIter = IntoIter; + + fn into_iter(self) -> IntoIter { + 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) { 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 Iterator for IntoIter { + type Item = K; + + fn next(&mut self) -> Option { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } +} +#[stable(feature = "rust1", since = "1.0.0")] +impl ExactSizeIterator for IntoIter { + 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 { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { 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, + S: HashState, + H: hash::Hasher +{ + 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) { + 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, + S: HashState, + H: hash::Hasher +{ + 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) { + 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, + S: HashState, + H: hash::Hasher +{ + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { 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, + S: HashState, + H: hash::Hasher +{ + type Item = &'a T; + + fn next(&mut self) -> Option<&'a T> { self.iter.next() } + fn size_hint(&self) -> (usize, Option) { 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::>(); + 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::::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::::new(); + for _ in s.drain() {} + assert!(s.is_empty()); + drop(s); + + let mut s = HashSet::::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); + } + } +} diff --git a/src/libstd/collections/hash/state.rs b/src/libstd/collections/hash/state.rs index 79e01304fb8..7e6dd45b51e 100644 --- a/src/libstd/collections/hash/state.rs +++ b/src/libstd/collections/hash/state.rs @@ -11,6 +11,7 @@ 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`. @@ -37,7 +38,7 @@ pub trait HashState { /// /// This struct has is 0-sized and does not need construction. #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")] -pub struct DefaultState; +pub struct DefaultState(marker::PhantomData); impl HashState for DefaultState { type Hasher = H; @@ -45,9 +46,9 @@ fn hasher(&self) -> H { Default::default() } } impl Clone for DefaultState { - fn clone(&self) -> DefaultState { DefaultState } + fn clone(&self) -> DefaultState { DefaultState(marker::PhantomData) } } impl Default for DefaultState { - fn default() -> DefaultState { DefaultState } + fn default() -> DefaultState { DefaultState(marker::PhantomData) } } diff --git a/src/libstd/collections/hash/table.rs b/src/libstd/collections/hash/table.rs index 0bb6bd4cf35..f301f6db92f 100644 --- a/src/libstd/collections/hash/table.rs +++ b/src/libstd/collections/hash/table.rs @@ -23,8 +23,8 @@ 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; @@ -69,10 +69,11 @@ pub struct RawTable { capacity: usize, size: usize, - hashes: *mut u64, + hashes: Unique, + // 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 Send for RawTable {} @@ -81,7 +82,8 @@ unsafe impl Sync for RawTable {} struct RawBucket { hash: *mut u64, key: *mut K, - val: *mut V + val: *mut V, + _marker: marker::PhantomData<(K,V)>, } impl Copy for RawBucket {} @@ -141,6 +143,7 @@ pub fn inspect(&self) -> u64 { self.hash } /// 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(hash_state: &S, t: &T) -> SafeHash where T: Hash, S: HashState, @@ -155,6 +158,22 @@ pub fn make_hash(hash_state: &S, t: &T) -> SafeHash 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(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 @@ -170,11 +189,12 @@ fn can_alias_safehash_as_u64() { } impl RawBucket { - unsafe fn offset(self, count: int) -> RawBucket { + unsafe fn offset(self, count: isize) -> RawBucket { RawBucket { hash: self.hash.offset(count), key: self.key.offset(count), val: self.val.offset(count), + _marker: marker::PhantomData, } } } @@ -567,10 +587,11 @@ unsafe fn new_uninitialized(capacity: usize) -> RawTable { 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::(); @@ -606,8 +627,8 @@ unsafe fn new_uninitialized(capacity: usize) -> RawTable { RawTable { capacity: capacity, size: 0, - hashes: hashes, - marker: marker::CovariantType, + hashes: Unique::new(hashes), + marker: marker::PhantomData, } } @@ -615,16 +636,17 @@ fn first_bucket_raw(&self) -> RawBucket { let hashes_size = self.capacity * size_of::(); let keys_size = self.capacity * size_of::(); - 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::(), min_align_of::()); 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, } } } @@ -634,7 +656,7 @@ fn first_bucket_raw(&self) -> RawBucket { pub fn new(capacity: usize) -> RawTable { unsafe { let ret = RawTable::new_uninitialized(capacity); - zero_memory(ret.hashes, capacity); + zero_memory(*ret.hashes, capacity); ret } } @@ -656,7 +678,7 @@ fn raw_buckets(&self) -> RawBuckets { hashes_end: unsafe { self.hashes.offset(self.capacity as isize) }, - marker: marker::ContravariantLifetime, + marker: marker::PhantomData, } } @@ -681,7 +703,7 @@ pub fn into_iter(self) -> IntoIter { iter: RawBuckets { raw: raw, hashes_end: hashes_end, - marker: marker::ContravariantLifetime, + marker: marker::PhantomData, }, table: self, } @@ -694,7 +716,7 @@ pub fn drain(&mut self) -> Drain { iter: RawBuckets { raw: raw, hashes_end: hashes_end, - marker: marker::ContravariantLifetime::<'static>, + marker: marker::PhantomData, }, table: self, } @@ -708,7 +730,7 @@ unsafe fn rev_move_buckets(&mut self) -> RevMoveBuckets { raw: raw_bucket.offset(self.capacity as isize), hashes_end: raw_bucket.hash, elems_left: self.size, - marker: marker::ContravariantLifetime, + marker: marker::PhantomData, } } } @@ -718,7 +740,13 @@ unsafe fn rev_move_buckets(&mut self) -> RevMoveBuckets { struct RawBuckets<'a, K, V> { raw: RawBucket, 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)]` @@ -727,7 +755,7 @@ fn clone(&self) -> RawBuckets<'a, K, V> { RawBuckets { raw: self.raw, hashes_end: self.hashes_end, - marker: marker::ContravariantLifetime, + marker: marker::PhantomData, } } } @@ -759,7 +787,11 @@ struct RevMoveBuckets<'a, K, V> { raw: RawBucket, 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> { @@ -966,9 +998,10 @@ fn clone(&self) -> RawTable { #[unsafe_destructor] impl Drop for RawTable { 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 @@ -986,7 +1019,7 @@ fn drop(&mut self) { vals_size, min_align_of::()); 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. } diff --git a/src/libstd/collections/mod.rs b/src/libstd/collections/mod.rs index be441bfec88..0e64370df60 100644 --- a/src/libstd/collections/mod.rs +++ b/src/libstd/collections/mod.rs @@ -23,7 +23,7 @@ //! //! 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` @@ -43,13 +43,13 @@ //! * 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. //! @@ -75,7 +75,7 @@ //! //! ### 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`. @@ -106,20 +106,20 @@ //! //! ## 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 | @@ -166,7 +166,7 @@ //! //! 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. @@ -240,10 +240,10 @@ //! ``` //! //! ``` -//! 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 @@ -362,11 +362,11 @@ #![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; diff --git a/src/libstd/dynamic_lib.rs b/src/libstd/dynamic_lib.rs index c5dd66630b4..b0fb9c29403 100644 --- a/src/libstd/dynamic_lib.rs +++ b/src/libstd/dynamic_lib.rs @@ -112,7 +112,7 @@ pub unsafe fn symbol(&self, symbol: &str) -> Result<*mut T, String> { // 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()) }); @@ -187,7 +187,7 @@ fn test_errors_do_not_crash() { mod dl { use prelude::v1::*; - use ffi::{self, CString}; + use ffi::{CString, CStr}; use str; use libc; use ptr; @@ -206,7 +206,7 @@ pub fn open(filename: Option<&[u8]>) -> Result<*mut u8, String> { 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 } @@ -231,7 +231,7 @@ pub fn check_for_errors_in(f: F) -> Result where 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()) }; diff --git a/src/libstd/env.rs b/src/libstd/env.rs index 93dc3efe2c4..8676586e7dc 100644 --- a/src/libstd/env.rs +++ b/src/libstd/env.rs @@ -926,7 +926,7 @@ fn check_parse(unparsed: &str, parsed: &[&str]) -> bool { #[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) } @@ -935,14 +935,14 @@ fn test_eq(input: &[&str], output: &str) -> bool { "/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) } @@ -953,6 +953,6 @@ fn test_eq(input: &[&str], output: &str) -> bool { 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()); } } diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs index 45089176cba..8976813d3f9 100644 --- a/src/libstd/ffi/c_str.rs +++ b/src/libstd/ffi/c_str.rs @@ -8,18 +8,25 @@ // 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. @@ -44,8 +51,8 @@ /// 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()); /// } @@ -53,19 +60,135 @@ /// ``` #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash)] pub struct CString { - inner: Vec, + inner: Vec, +} + +/// 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); + +/// 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; } 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: T) -> Result { + 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()) } @@ -77,11 +200,15 @@ pub fn from_slice(v: &[u8]) -> CString { /// /// # 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) -> 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 @@ -91,31 +218,29 @@ pub fn from_vec(v: Vec) -> CString { /// is made that `v` contains no 0 bytes. pub unsafe fn from_vec_unchecked(mut v: Vec) -> 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()) } } } @@ -126,54 +251,172 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } } -/// 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 { 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 for io::Error { + fn from_error(_: NulError) -> io::Error { + io::Error::new(io::ErrorKind::InvalidInput, + "data provided contains a nul byte", None) + } +} + +impl FromError 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 { + 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 { self.as_bytes().to_vec() } +} +impl<'a> IntoBytes for &'a [u8] { + fn into_bytes(self) -> Vec { self.to_vec() } +} +impl IntoBytes for String { + fn into_bytes(self) -> Vec { self.into_bytes() } +} +impl IntoBytes for Vec { + fn into_bytes(self) -> Vec { self } +} + #[cfg(test)] mod tests { use prelude::v1::*; @@ -193,21 +436,19 @@ fn c_to_rust() { #[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() { @@ -219,7 +460,16 @@ 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"); + } + } } diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs index 07a4f17796c..1bff6afb776 100644 --- a/src/libstd/ffi/mod.rs +++ b/src/libstd/ffi/mod.rs @@ -14,8 +14,10 @@ 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; diff --git a/src/libstd/ffi/os_str.rs b/src/libstd/ffi/os_str.rs index 1d14b141778..84149a2eb8e 100644 --- a/src/libstd/ffi/os_str.rs +++ b/src/libstd/ffi/os_str.rs @@ -34,13 +34,14 @@ 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}; @@ -103,7 +104,7 @@ impl ops::Deref for OsString { #[inline] fn deref(&self) -> &OsStr { - &self[] + &self[..] } } @@ -162,12 +163,21 @@ fn cmp(&self, other: &OsString) -> cmp::Ordering { } } +#[cfg(stage0)] impl<'a, S: Hasher + Writer> Hash 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(&self, state: &mut H) { + (&**self).hash(state) + } +} impl OsStr { /// Coerce directly from a `&str` slice to a `&OsStr` slice. @@ -253,12 +263,21 @@ impl Ord for OsStr { fn cmp(&self, other: &OsStr) -> cmp::Ordering { self.bytes().cmp(other.bytes()) } } +#[cfg(stage0)] impl<'a, S: Hasher + Writer> Hash 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(&self, state: &mut H) { + self.bytes().hash(state) + } +} impl Debug for OsStr { fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { @@ -266,11 +285,12 @@ fn fmt(&self, formatter: &mut fmt::Formatter) -> Result<(), fmt::Error> { } } -impl BorrowFrom for OsStr { - fn borrow_from(owned: &OsString) -> &OsStr { &owned[] } +impl Borrow for OsString { + fn borrow(&self) -> &OsStr { &self[..] } } -impl ToOwned for OsStr { +impl ToOwned for OsStr { + type Owned = OsString; fn to_owned(&self) -> OsString { self.to_os_string() } } @@ -288,7 +308,7 @@ fn as_os_str(&self) -> &OsStr { impl AsOsStr for OsString { fn as_os_str(&self) -> &OsStr { - &self[] + &self[..] } } @@ -300,7 +320,7 @@ fn as_os_str(&self) -> &OsStr { impl AsOsStr for String { fn as_os_str(&self) -> &OsStr { - OsStr::from_str(&self[]) + OsStr::from_str(&self[..]) } } diff --git a/src/libstd/io/buffered.rs b/src/libstd/io/buffered.rs index 2fd6631ecc4..e9a8dbb4098 100644 --- a/src/libstd/io/buffered.rs +++ b/src/libstd/io/buffered.rs @@ -618,14 +618,14 @@ fn test_short_reads() { #[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'))); diff --git a/src/libstd/io/cursor.rs b/src/libstd/io/cursor.rs index 9f3655de20f..f6cb4a8c9f3 100644 --- a/src/libstd/io/cursor.rs +++ b/src/libstd/io/cursor.rs @@ -180,7 +180,7 @@ fn test_mem_writer() { 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); @@ -201,7 +201,7 @@ fn test_buf_writer() { 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); @@ -229,7 +229,7 @@ fn test_buf_writer_seek() { #[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)); @@ -331,7 +331,7 @@ fn test_read_bad_char() { #[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)); @@ -340,7 +340,7 @@ fn seek_past_end() { 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)); } @@ -348,14 +348,14 @@ fn seek_past_end() { #[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()); } diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 7c9a8a7b4b5..fbd403ea593 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -161,7 +161,6 @@ // NB: These reexports are in the order they should be listed in rustdoc pub use core::any; -pub use core::borrow; pub use core::cell; pub use core::clone; #[cfg(not(test))] pub use core::cmp; @@ -184,6 +183,7 @@ #[cfg(not(test))] pub use alloc::boxed; pub use alloc::rc; +pub use core_collections::borrow; pub use core_collections::fmt; pub use core_collections::slice; pub use core_collections::str; diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs index 66d4d34f8eb..51944adf3b4 100644 --- a/src/libstd/net/addr.rs +++ b/src/libstd/net/addr.rs @@ -147,6 +147,7 @@ fn eq(&self, other: &Repr) -> bool { } impl Eq for Repr {} +#[cfg(stage0)] impl hash::Hash for Repr { fn hash(&self, s: &mut S) { match *self { @@ -160,6 +161,21 @@ fn hash(&self, s: &mut S) { } } } +#[cfg(not(stage0))] +#[stable(feature = "rust1", since = "1.0.0")] +impl hash::Hash for Repr { + fn hash(&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. diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 08f7a6e2e96..571a1b03ef0 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -189,11 +189,19 @@ fn eq(&self, other: &Ipv4Addr) -> bool { } impl Eq for Ipv4Addr {} +#[cfg(stage0)] impl hash::Hash 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(&self, s: &mut H) { + self.inner.s_addr.hash(s) + } +} impl PartialOrd for Ipv4Addr { fn partial_cmp(&self, other: &Ipv4Addr) -> Option { @@ -421,11 +429,19 @@ fn eq(&self, other: &Ipv6Addr) -> bool { } impl Eq for Ipv6Addr {} +#[cfg(stage0)] impl hash::Hash 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(&self, s: &mut H) { + self.inner.s6_addr.hash(s) + } +} impl PartialOrd for Ipv6Addr { fn partial_cmp(&self, other: &Ipv6Addr) -> Option { diff --git a/src/libstd/old_io/buffered.rs b/src/libstd/old_io/buffered.rs index 59a437ad916..2d2d0d8b33a 100644 --- a/src/libstd/old_io/buffered.rs +++ b/src/libstd/old_io/buffered.rs @@ -546,7 +546,7 @@ fn test_buffered_writer_inner_flushes() { 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 @@ -643,14 +643,14 @@ fn test_short_reads() { #[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'))); diff --git a/src/libstd/old_io/mod.rs b/src/libstd/old_io/mod.rs index 21282a0c28a..fc3deb67f41 100644 --- a/src/libstd/old_io/mod.rs +++ b/src/libstd/old_io/mod.rs @@ -252,7 +252,7 @@ use fmt; use isize; use iter::{Iterator, IteratorExt}; -use marker::Sized; +use marker::{PhantomFn, Sized}; use mem::transmute; use ops::FnOnce; use option::Option; @@ -433,7 +433,7 @@ pub enum IoErrorKind { } /// A trait that lets you add a `detail` to an IoError easily -trait UpdateIoError { +trait UpdateIoError { /// Returns an IoError with updated description and detail fn update_err(self, desc: &'static str, detail: D) -> Self where D: FnOnce(&IoError) -> String; @@ -446,7 +446,7 @@ fn update_detail(self, detail: D) -> Self where fn update_desc(self, desc: &'static str) -> Self; } -impl UpdateIoError for IoResult { +impl UpdateIoError for IoResult { fn update_err(self, desc: &'static str, detail: D) -> IoResult where D: FnOnce(&IoError) -> String, { @@ -1572,7 +1572,9 @@ pub trait Seek { /// connections. /// /// Doing so produces some sort of Acceptor. -pub trait Listener> { +pub trait Listener> + : PhantomFn // FIXME should be an assoc type anyhow +{ /// Spin up the listener and start queuing incoming connections /// /// # Error diff --git a/src/libstd/old_io/net/pipe.rs b/src/libstd/old_io/net/pipe.rs index 8a4e8668b10..d05669d32b8 100644 --- a/src/libstd/old_io/net/pipe.rs +++ b/src/libstd/old_io/net/pipe.rs @@ -55,7 +55,7 @@ impl UnixStream { /// stream.write(&[1, 2, 3]); /// ``` pub fn connect(path: P) -> IoResult { - 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 }) } @@ -77,7 +77,7 @@ pub fn connect_timeout

(path: P, timeout: Duration) 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 }) } @@ -184,7 +184,7 @@ impl UnixListener { /// # } /// ``` pub fn bind(path: P) -> IoResult { - 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 }) } diff --git a/src/libstd/old_io/process.rs b/src/libstd/old_io/process.rs index ea6510c61b7..c803cfbcb7d 100644 --- a/src/libstd/old_io/process.rs +++ b/src/libstd/old_io/process.rs @@ -104,7 +104,7 @@ pub struct Process { #[derive(Eq, Clone, Debug)] struct EnvKey(CString); -#[cfg(windows)] +#[cfg(all(windows, stage0))] impl hash::Hash for EnvKey { fn hash(&self, state: &mut H) { let &EnvKey(ref x) = self; @@ -116,6 +116,18 @@ fn hash(&self, state: &mut H) { } } } +#[cfg(all(windows, not(stage0)))] +impl hash::Hash for EnvKey { + fn hash(&self, state: &mut H) { + let &EnvKey(ref x) = self; + match str::from_utf8(x.as_bytes()) { + Ok(s) => for ch in s.chars() { + (ch as u8 as char).to_lowercase().hash(state); + }, + Err(..) => x.hash(state) + } + } +} #[cfg(windows)] impl PartialEq for EnvKey { @@ -204,7 +216,7 @@ impl Command { /// otherwise configure the process. pub fn new(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, @@ -219,14 +231,14 @@ pub fn new(program: T) -> Command { /// 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 } @@ -239,8 +251,8 @@ fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap { // 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() } @@ -254,8 +266,8 @@ fn get_env_map<'a>(&'a mut self) -> &'a mut EnvMap { 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 } @@ -263,7 +275,7 @@ pub fn env<'a, T, U>(&'a mut self, key: T, val: U) /// 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 } @@ -276,15 +288,15 @@ pub fn env_set_all<'a, T, U>(&'a mut self, env: &[(T,U)]) -> &'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 } @@ -1226,7 +1238,7 @@ fn env_map_keys_ci() { 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()); } } diff --git a/src/libstd/old_path/mod.rs b/src/libstd/old_path/mod.rs index 37de2993c4d..e9005aa22bc 100644 --- a/src/libstd/old_path/mod.rs +++ b/src/libstd/old_path/mod.rs @@ -877,7 +877,7 @@ fn container_as_bytes(&self) -> &[u8] { } #[inline] fn container_as_str(&self) -> Option<&str> { - Some(&self[]) + Some(&self[..]) } #[inline] fn is_str(_: Option<&String>) -> bool { true } @@ -893,7 +893,7 @@ fn container_as_bytes(&self) -> &[u8] { impl BytesContainer for Vec { #[inline] fn container_as_bytes(&self) -> &[u8] { - &self[] + &self[..] } } diff --git a/src/libstd/old_path/posix.rs b/src/libstd/old_path/posix.rs index 0a184a01a1d..15eee9e4a0c 100644 --- a/src/libstd/old_path/posix.rs +++ b/src/libstd/old_path/posix.rs @@ -100,12 +100,21 @@ fn from_str(s: &str) -> Result { #[derive(Debug, Clone, PartialEq, Copy)] pub struct ParsePathError; +#[cfg(stage0)] impl hash::Hash 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(&self, state: &mut H) { + self.repr.hash(state) + } +} impl BytesContainer for Path { #[inline] @@ -1172,7 +1181,7 @@ macro_rules! t { let exp: &[&[u8]] = &[$($exp),*]; assert_eq!(comps, exp); let comps = path.components().rev().collect::>(); - let exp = exp.iter().rev().map(|&x|x).collect::>(); + let exp = exp.iter().rev().cloned().collect::>(); assert_eq!(comps, exp) } ) @@ -1204,7 +1213,7 @@ macro_rules! t { let exp: &[Option<&str>] = &$exp; assert_eq!(comps, exp); let comps = path.str_components().rev().collect::>>(); - let exp = exp.iter().rev().map(|&x|x).collect::>>(); + let exp = exp.iter().rev().cloned().collect::>>(); assert_eq!(comps, exp); } ) diff --git a/src/libstd/old_path/windows.rs b/src/libstd/old_path/windows.rs index 02a21321c4c..887dc804c7a 100644 --- a/src/libstd/old_path/windows.rs +++ b/src/libstd/old_path/windows.rs @@ -127,6 +127,7 @@ fn from_str(s: &str) -> Result { #[derive(Debug, Clone, PartialEq, Copy)] pub struct ParsePathError; +#[cfg(stage0)] impl hash::Hash for Path { #[cfg(not(test))] #[inline] @@ -140,6 +141,21 @@ fn hash(&self, _: &mut S) { // 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(&self, state: &mut H) { + self.repr.hash(state) + } + + #[cfg(test)] + #[inline] + fn hash(&self, _: &mut H) { + // No-op because the `hash` implementation will be wrong. + } +} impl BytesContainer for Path { #[inline] @@ -182,7 +198,7 @@ unsafe fn set_filename_unchecked(&mut self, filename: T) { s.push_str(".."); s.push(SEP); s.push_str(filename); - self.update_normalized(&s[]); + self.update_normalized(&s[..]); } None => { self.update_normalized(filename); @@ -192,20 +208,20 @@ unsafe fn set_filename_unchecked(&mut self, filename: T) { 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[..]); } } } @@ -229,7 +245,7 @@ fn is_vol_abs(path: &str, prefix: Option) -> bool { } 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() @@ -261,7 +277,7 @@ fn append_path(me: &mut Path, path: &str) { 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 { @@ -273,9 +289,9 @@ fn append_path(me: &mut Path, path: &str) { } 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() { @@ -329,7 +345,7 @@ fn new_opt(path: T) -> Option { /// Always returns a `Some` value. #[inline] fn as_str<'a>(&'a self) -> Option<&'a str> { - Some(&self.repr[]) + Some(&self.repr[..]) } #[inline] @@ -351,13 +367,13 @@ fn dirname<'a>(&'a self) -> &'a [u8] { /// 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,_)) => { @@ -379,7 +395,7 @@ fn filename<'a>(&'a self) -> Option<&'a [u8]> { /// 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), @@ -639,7 +655,7 @@ pub fn new_opt(path: T) -> Option { /// 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(); @@ -667,8 +683,8 @@ fn convert<'a>(x: Option<&'a str>) -> &'a [u8] { } 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() && @@ -823,7 +839,7 @@ fn normalize__(s: &str, prefix: Option) -> Option { 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 { @@ -902,7 +918,7 @@ pub fn is_verbatim(path: &Path) -> bool { /// non-verbatim, the non-verbatim version is returned. /// Otherwise, None is returned. pub fn make_non_verbatim(path: &Path) -> Option { - 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()), @@ -2226,7 +2242,7 @@ macro_rules! t { assert_eq!(comps, exp); let comps = path.str_components().rev().map(|x|x.unwrap()) .collect::>(); - let exp = exp.iter().rev().map(|&x|x).collect::>(); + let exp = exp.iter().rev().cloned().collect::>(); assert_eq!(comps, exp); } ); @@ -2282,7 +2298,7 @@ macro_rules! t { let exp: &[&[u8]] = &$exp; assert_eq!(comps, exp); let comps = path.components().rev().collect::>(); - let exp = exp.iter().rev().map(|&x|x).collect::>(); + let exp = exp.iter().rev().cloned().collect::>(); assert_eq!(comps, exp); } ) diff --git a/src/libstd/os.rs b/src/libstd/os.rs index a4213e7373b..f181fc5df57 100644 --- a/src/libstd/os.rs +++ b/src/libstd/os.rs @@ -561,10 +561,11 @@ pub fn get_exit_status() -> int { #[cfg(target_os = "macos")] unsafe fn load_argc_and_argv(argc: int, argv: *const *const c_char) -> Vec> { + 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() } diff --git a/src/libstd/panicking.rs b/src/libstd/panicking.rs index 35221a7e647..2e05f6d974e 100644 --- a/src/libstd/panicking.rs +++ b/src/libstd/panicking.rs @@ -37,7 +37,7 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: uint) { let msg = match obj.downcast_ref::<&'static str>() { Some(s) => *s, None => match obj.downcast_ref::() { - Some(s) => &s[], + Some(s) => &s[..], None => "Box", } }; diff --git a/src/libstd/path.rs b/src/libstd/path.rs index 1d992668900..49a5efec7c2 100755 --- a/src/libstd/path.rs +++ b/src/libstd/path.rs @@ -108,12 +108,11 @@ use core::prelude::*; use ascii::*; -use borrow::BorrowFrom; +use borrow::{Borrow, ToOwned, Cow}; use cmp; -use iter; +use iter::{self, IntoIterator}; use mem; use ops::{self, Deref}; -use string::CowString; use vec::Vec; use fmt; @@ -953,7 +952,7 @@ pub fn into_os_string(self) -> OsString { } impl<'a, P: ?Sized + 'a> iter::FromIterator<&'a P> for PathBuf where P: AsPath { - fn from_iter>(iter: I) -> PathBuf { + fn from_iter>(iter: I) -> PathBuf { let mut buf = PathBuf::new(""); buf.extend(iter); buf @@ -961,7 +960,7 @@ fn from_iter>(iter: I) -> PathBuf { } impl<'a, P: ?Sized + 'a> iter::Extend<&'a P> for PathBuf where P: AsPath { - fn extend>(&mut self, iter: I) { + fn extend>(&mut self, iter: I) { for p in iter { self.push(p) } @@ -978,16 +977,21 @@ impl ops::Deref for PathBuf { type Target = Path; fn deref(&self) -> &Path { - unsafe { mem::transmute(&self.inner[]) } + unsafe { mem::transmute(&self.inner[..]) } } } -impl BorrowFrom for Path { - fn borrow_from(owned: &PathBuf) -> &Path { - owned.deref() +impl Borrow for PathBuf { + fn borrow(&self) -> &Path { + self.deref() } } +impl ToOwned for Path { + type Owned = PathBuf; + fn to_owned(&self) -> PathBuf { self.to_path_buf() } +} + impl cmp::PartialEq for PathBuf { fn eq(&self, other: &PathBuf) -> bool { self.components() == other.components() @@ -1010,7 +1014,7 @@ fn cmp(&self, other: &PathBuf) -> cmp::Ordering { impl AsOsStr for PathBuf { fn as_os_str(&self) -> &OsStr { - &self.inner[] + &self.inner[..] } } @@ -1066,10 +1070,10 @@ pub fn to_str(&self) -> Option<&str> { self.inner.to_str() } - /// Convert a `Path` to a `CowString`. + /// Convert a `Path` to a `Cow`. /// /// Any non-Unicode sequences are replaced with U+FFFD REPLACEMENT CHARACTER. - pub fn to_string_lossy(&self) -> CowString { + pub fn to_string_lossy(&self) -> Cow { self.inner.to_string_lossy() } diff --git a/src/libstd/rand/mod.rs b/src/libstd/rand/mod.rs index 25d372b406f..5c891441198 100644 --- a/src/libstd/rand/mod.rs +++ b/src/libstd/rand/mod.rs @@ -547,7 +547,7 @@ fn test_gen_vec() { #[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); diff --git a/src/libstd/rt/args.rs b/src/libstd/rt/args.rs index c2f5133eaf3..61f5bd0f013 100644 --- a/src/libstd/rt/args.rs +++ b/src/libstd/rt/args.rs @@ -49,7 +49,7 @@ mod imp { use libc; use mem; - use ffi; + use ffi::CStr; use sync::{StaticMutex, MUTEX_INIT}; @@ -96,10 +96,11 @@ fn get_global_ptr() -> *mut Option>>> { unsafe { mem::transmute(&GLOBAL_ARGS_PTR) } } - unsafe fn load_argc_and_argv(argc: int, argv: *const *const u8) -> Vec> { + unsafe fn load_argc_and_argv(argc: isize, + argv: *const *const u8) -> Vec> { 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() } diff --git a/src/libstd/sys/common/net.rs b/src/libstd/sys/common/net.rs index 7325e0a5ac8..e2ac5ac24f8 100644 --- a/src/libstd/sys/common/net.rs +++ b/src/libstd/sys/common/net.rs @@ -12,8 +12,7 @@ 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}; @@ -235,9 +234,15 @@ pub fn get_host_addresses(host: Option<&str>, servname: Option<&str>, 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| { @@ -325,8 +330,8 @@ pub fn get_address_name(addr: IpAddr) -> Result { } 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()) } } diff --git a/src/libstd/sys/common/net2.rs b/src/libstd/sys/common/net2.rs index 5af59ec6d2b..713f79c5d08 100644 --- a/src/libstd/sys/common/net2.rs +++ b/src/libstd/sys/common/net2.rs @@ -121,7 +121,7 @@ fn drop(&mut self) { pub fn lookup_host(host: &str) -> io::Result { 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 _, diff --git a/src/libstd/sys/common/wtf8.rs b/src/libstd/sys/common/wtf8.rs index b610f6c370b..ca3ae1a7a34 100644 --- a/src/libstd/sys/common/wtf8.rs +++ b/src/libstd/sys/common/wtf8.rs @@ -31,8 +31,9 @@ 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; @@ -356,9 +357,9 @@ pub fn into_string_lossy(mut self) -> String { /// This replaces surrogate code point pairs with supplementary code points, /// like concatenating ill-formed UTF-16 strings effectively would. impl FromIterator for Wtf8Buf { - fn from_iter>(iterator: T) -> Wtf8Buf { + fn from_iter>(iter: T) -> Wtf8Buf { let mut string = Wtf8Buf::new(); - string.extend(iterator); + string.extend(iter); string } } @@ -368,7 +369,8 @@ fn from_iter>(iterator: T) -> Wtf8Buf { /// This replaces surrogate code point pairs with supplementary code points, /// like concatenating ill-formed UTF-16 strings effectively would. impl Extend for Wtf8Buf { - fn extend>(&mut self, iterator: T) { + fn extend>(&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); @@ -794,13 +796,22 @@ fn size_hint(&self) -> (uint, Option) { } } +#[cfg(stage0)] impl Hash for CodePoint { #[inline] fn hash(&self, state: &mut S) { self.value.hash(state) } } +#[cfg(not(stage0))] +impl Hash for CodePoint { + #[inline] + fn hash(&self, state: &mut H) { + self.value.hash(state) + } +} +#[cfg(stage0)] impl Hash for Wtf8Buf { #[inline] fn hash(&self, state: &mut S) { @@ -808,7 +819,16 @@ fn hash(&self, state: &mut S) { 0xfeu8.hash(state) } } +#[cfg(not(stage0))] +impl Hash for Wtf8Buf { + #[inline] + fn hash(&self, state: &mut H) { + state.write(&self.bytes); + 0xfeu8.hash(state) + } +} +#[cfg(stage0)] impl<'a, S: Writer + Hasher> Hash for Wtf8 { #[inline] fn hash(&self, state: &mut S) { @@ -816,6 +836,14 @@ fn hash(&self, state: &mut S) { 0xfeu8.hash(state) } } +#[cfg(not(stage0))] +impl Hash for Wtf8 { + #[inline] + fn hash(&self, state: &mut H) { + state.write(&self.bytes); + 0xfeu8.hash(state) + } +} impl AsciiExt for Wtf8 { type Owned = Wtf8Buf; diff --git a/src/libstd/sys/unix/backtrace.rs b/src/libstd/sys/unix/backtrace.rs index 5e512e9261b..8b560339f30 100644 --- a/src/libstd/sys/unix/backtrace.rs +++ b/src/libstd/sys/unix/backtrace.rs @@ -85,7 +85,7 @@ use prelude::v1::*; -use ffi; +use ffi::CStr; use old_io::IoResult; use libc; use mem; @@ -233,7 +233,7 @@ fn dladdr(addr: *const libc::c_void, 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() })) } } @@ -364,7 +364,7 @@ unsafe fn init_state() -> *mut backtrace_state { 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() })) } } diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs index bbbe022fbaf..b8b9dcfb3c6 100644 --- a/src/libstd/sys/unix/ext.rs +++ b/src/libstd/sys/unix/ext.rs @@ -33,7 +33,7 @@ use prelude::v1::*; -use ffi::{CString, OsStr, OsString}; +use ffi::{CString, NulError, OsStr, OsString}; use fs::{self, Permissions, OpenOptions}; use net; use mem; @@ -155,7 +155,7 @@ pub trait OsStrExt { fn as_bytes(&self) -> &[u8]; /// Convert the `OsStr` slice into a `CString`. - fn to_cstring(&self) -> CString; + fn to_cstring(&self) -> Result; } impl OsStrExt for OsStr { @@ -166,8 +166,8 @@ fn as_bytes(&self) -> &[u8] { &self.as_inner().inner } - fn to_cstring(&self) -> CString { - CString::from_slice(self.as_bytes()) + fn to_cstring(&self) -> Result { + CString::new(self.as_bytes()) } } @@ -249,5 +249,7 @@ fn signal(&self) -> Option { /// 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}; } diff --git a/src/libstd/sys/unix/fs.rs b/src/libstd/sys/unix/fs.rs index 0ee2b5b6809..5c847002d23 100644 --- a/src/libstd/sys/unix/fs.rs +++ b/src/libstd/sys/unix/fs.rs @@ -12,7 +12,7 @@ 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}; @@ -151,8 +151,8 @@ fn drop(&mut self) { } } -fn cstr(path: &Path) -> CString { - CString::from_slice(path.as_vec()) +fn cstr(path: &Path) -> IoResult { + Ok(try!(CString::new(path.as_vec()))) } pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult { @@ -170,7 +170,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult { 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)), @@ -178,7 +178,7 @@ pub fn open(path: &Path, fm: FileMode, fa: FileAccess) -> IoResult { } 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) }) } @@ -203,7 +203,7 @@ fn prune(root: &CString, dirs: Vec) -> Vec { let mut buf = Vec::::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 { @@ -212,7 +212,7 @@ fn prune(root: &CString, dirs: Vec) -> Vec { 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); @@ -223,39 +223,39 @@ fn prune(root: &CString, dirs: Vec) -> Vec { } 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 { - 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 { @@ -276,14 +276,14 @@ pub fn readlink(p: &Path) -> IoResult { } 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()) }) } @@ -331,7 +331,7 @@ fn gen(_stat: &libc::stat) -> u64 { 0 } } pub fn stat(p: &Path) -> IoResult { - 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)), @@ -340,7 +340,7 @@ pub fn stat(p: &Path) -> IoResult { } pub fn lstat(p: &Path) -> IoResult { - 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)), @@ -349,7 +349,7 @@ pub fn lstat(p: &Path) -> IoResult { } 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, diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs index e5904b074bc..92a47c6c385 100644 --- a/src/libstd/sys/unix/fs2.rs +++ b/src/libstd/sys/unix/fs2.rs @@ -12,7 +12,7 @@ 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; @@ -147,8 +147,7 @@ fn name_bytes(&self) -> &[u8] { 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() } } } @@ -204,7 +203,7 @@ pub fn open(path: &Path, opts: &OpenOptions) -> io::Result { (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) })); @@ -268,19 +267,20 @@ pub fn seek(&self, pos: SeekFrom) -> io::Result { 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 { + 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 { 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() { @@ -292,32 +292,32 @@ pub fn readdir(p: &Path) -> io::Result { } 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) })); @@ -325,7 +325,7 @@ pub fn chown(p: &Path, uid: isize, gid: isize) -> io::Result<()> { } pub fn readlink(p: &Path) -> io::Result { - 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 { @@ -343,35 +343,35 @@ pub fn readlink(p: &Path) -> io::Result { } 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 { - 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 { - 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(()) diff --git a/src/libstd/sys/unix/mod.rs b/src/libstd/sys/unix/mod.rs index 850189140d1..b79ad7031fa 100644 --- a/src/libstd/sys/unix/mod.rs +++ b/src/libstd/sys/unix/mod.rs @@ -17,7 +17,7 @@ use prelude::v1::*; -use ffi; +use ffi::CStr; use io::{self, ErrorKind}; use libc; use num::{Int, SignedInt}; @@ -91,7 +91,8 @@ pub fn last_gai_error(s: libc::c_int) -> IoError { 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 } diff --git a/src/libstd/sys/unix/net.rs b/src/libstd/sys/unix/net.rs index 54aec7cf4b1..83b6a14b78d 100644 --- a/src/libstd/sys/unix/net.rs +++ b/src/libstd/sys/unix/net.rs @@ -10,7 +10,7 @@ use prelude::v1::*; -use ffi; +use ffi::CStr; use io; use libc::{self, c_int, size_t}; use str; @@ -31,7 +31,7 @@ pub fn cvt_gai(err: c_int) -> io::Result<()> { 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, diff --git a/src/libstd/sys/unix/os.rs b/src/libstd/sys/unix/os.rs index 5fe84cafb71..3d1ef3a2c37 100644 --- a/src/libstd/sys/unix/os.rs +++ b/src/libstd/sys/unix/os.rs @@ -14,7 +14,7 @@ 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}; @@ -88,7 +88,7 @@ fn strerror_r(errnum: c_int, buf: *mut c_char, } 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() } } @@ -98,13 +98,13 @@ pub fn getcwd() -> IoResult { 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(()), @@ -211,7 +211,7 @@ pub fn current_exe() -> IoResult { 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())) } } } @@ -266,7 +266,7 @@ pub fn args() -> Args { 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::>() }; @@ -324,7 +324,7 @@ pub fn args() -> Args { 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())) } } @@ -380,7 +380,7 @@ pub fn env() -> Env { } 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 _ } @@ -397,20 +397,20 @@ fn parse(input: &[u8]) -> (OsString, OsString) { pub fn getenv(k: &OsStr) -> Option { 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()); } @@ -419,7 +419,7 @@ pub fn setenv(k: &OsStr, v: &OsStr) { 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()); } @@ -480,7 +480,7 @@ unsafe fn fallback() -> Option { _ => 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)) } } diff --git a/src/libstd/sys/unix/pipe.rs b/src/libstd/sys/unix/pipe.rs index 45d5b1506c3..3c9cdc65975 100644 --- a/src/libstd/sys/unix/pipe.rs +++ b/src/libstd/sys/unix/pipe.rs @@ -38,7 +38,7 @@ fn addr_to_sockaddr_un(addr: &CString, mem::size_of::()); 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, @@ -47,8 +47,8 @@ fn addr_to_sockaddr_un(addr: &CString, }) } 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 diff --git a/src/libstd/sys/unix/process.rs b/src/libstd/sys/unix/process.rs index f954024b0e9..b30ac889120 100644 --- a/src/libstd/sys/unix/process.rs +++ b/src/libstd/sys/unix/process.rs @@ -12,6 +12,7 @@ use self::Req::*; use collections::HashMap; +#[cfg(stage0)] use collections::hash_map::Hasher; use ffi::CString; use hash::Hash; @@ -63,6 +64,7 @@ pub unsafe fn killpid(pid: pid_t, signal: int) -> IoResult<()> { mkerr_libc(r) } + #[cfg(stage0)] pub fn spawn(cfg: &C, in_fd: Option

, out_fd: Option

, err_fd: Option

) -> IoResult @@ -278,6 +280,214 @@ fn setgroups(ngroups: libc::c_int, }) }) } + #[cfg(not(stage0))] + pub fn spawn(cfg: &C, in_fd: Option

, + out_fd: Option

, err_fd: Option

) + -> IoResult + where C: ProcessConfig, P: AsInner, + 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,&'static ProcessConfig>(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

, 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 { use cmp; @@ -556,6 +766,7 @@ fn with_argv(prog: &CString, args: &[CString], cb(ptrs.as_ptr()) } +#[cfg(stage0)] fn with_envp(env: Option<&HashMap>, cb: F) -> T @@ -593,6 +804,44 @@ fn with_envp(env: Option<&HashMap>, _ => cb(ptr::null()) } } +#[cfg(not(stage0))] +fn with_envp(env: Option<&HashMap>, + 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)] diff --git a/src/libstd/sys/unix/process2.rs b/src/libstd/sys/unix/process2.rs index 5e2c207f375..06fa5c4bba7 100644 --- a/src/libstd/sys/unix/process2.rs +++ b/src/libstd/sys/unix/process2.rs @@ -11,7 +11,6 @@ use prelude::v1::*; use collections::HashMap; -use collections::hash_map::Hasher; use env; use ffi::{OsString, OsStr, CString}; use fmt; @@ -46,7 +45,7 @@ pub struct Command { 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, @@ -57,10 +56,10 @@ pub fn new(program: &OsStr) -> Command { } 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>(&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() { @@ -79,7 +78,7 @@ pub fn env_clear(&mut self) { 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()) } } diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 82c52471d10..c90ba7645fe 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -237,7 +237,7 @@ pub unsafe fn create(stack: uint, p: Thunk) -> io::Result { 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"] @@ -255,14 +255,14 @@ pub unsafe fn set_name(name: &str) { 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()); } diff --git a/src/libstd/sys/windows/backtrace.rs b/src/libstd/sys/windows/backtrace.rs index 92e309da34b..51cf3032423 100644 --- a/src/libstd/sys/windows/backtrace.rs +++ b/src/libstd/sys/windows/backtrace.rs @@ -25,7 +25,7 @@ #![allow(dead_code)] use dynamic_lib::DynamicLibrary; -use ffi; +use ffi::CStr; use intrinsics; use old_io::{IoResult, Writer}; use libc; @@ -362,7 +362,7 @@ macro_rules! sym{ ($e:expr, $t:ident) => (unsafe { 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])), diff --git a/src/libstd/sys/windows/c.rs b/src/libstd/sys/windows/c.rs index f861255a00a..2d1a5e10bd6 100644 --- a/src/libstd/sys/windows/c.rs +++ b/src/libstd/sys/windows/c.rs @@ -283,7 +283,7 @@ fn store_func(ptr: &AtomicUsize, module: &str, symbol: &str, fallback: usize) -> usize { let mut module: Vec = 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 diff --git a/src/libstd/sys/windows/mod.rs b/src/libstd/sys/windows/mod.rs index 4d6d033deee..a756fb29f81 100644 --- a/src/libstd/sys/windows/mod.rs +++ b/src/libstd/sys/windows/mod.rs @@ -265,12 +265,12 @@ fn fill_utf16_buf_base(mut f1: F1, f2: F2) -> Result 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 diff --git a/src/libstd/sys/windows/os.rs b/src/libstd/sys/windows/os.rs index 502d70d4e1a..6520d30487c 100644 --- a/src/libstd/sys/windows/os.rs +++ b/src/libstd/sys/windows/os.rs @@ -114,7 +114,7 @@ fn next(&mut self) -> Option<(OsString, OsString)> { 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))) } @@ -186,7 +186,7 @@ fn next(&mut self) -> Option { if !must_yield && in_progress.is_empty() { None } else { - Some(super::os2path(&in_progress[])) + Some(super::os2path(&in_progress[..])) } } } @@ -208,14 +208,14 @@ pub fn join_paths(paths: I) -> Result 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 { diff --git a/src/libstd/sys/windows/process.rs b/src/libstd/sys/windows/process.rs index 96ffc4daddd..60d24e6174f 100644 --- a/src/libstd/sys/windows/process.rs +++ b/src/libstd/sys/windows/process.rs @@ -10,7 +10,7 @@ use prelude::v1::*; -use collections::hash_map::Hasher; +#[cfg(stage0)] use collections::hash_map::Hasher; use collections; use env; use ffi::CString; @@ -106,6 +106,7 @@ pub unsafe fn killpid(pid: pid_t, signal: int) -> IoResult<()> { } #[allow(deprecated)] + #[cfg(stage0)] pub fn spawn(cfg: &C, in_fd: Option

, out_fd: Option

, err_fd: Option

) -> IoResult @@ -267,6 +268,169 @@ pub fn spawn(cfg: &C, in_fd: Option

, }) } } + #[allow(deprecated)] + #[cfg(not(stage0))] + pub fn spawn(cfg: &C, in_fd: Option

, + out_fd: Option

, err_fd: Option

) + -> IoResult + where C: ProcessConfig, P: AsInner, + 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::() 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

, 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::(); + let mut sa = libc::SECURITY_ATTRIBUTES { + nLength: size as libc::DWORD, + lpSecurityDescriptor: ptr::null_mut(), + bInheritHandle: 1, + }; + let mut filename: Vec = "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 = 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. @@ -425,6 +589,7 @@ fn backslash_run_ends_in_quote(s: &[char], mut i: uint) -> bool { } } +#[cfg(stage0)] fn with_envp(env: Option<&collections::HashMap>, cb: F) -> T where K: BytesContainer + Eq + Hash, V: BytesContainer, @@ -452,6 +617,34 @@ fn with_envp(env: Option<&collections::HashMap>, cb: F) -> T _ => cb(ptr::null_mut()) } } +#[cfg(not(stage0))] +fn with_envp(env: Option<&collections::HashMap>, 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(d: Option<&CString>, cb: F) -> T where F: FnOnce(*const u16) -> T, diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index 3137d779c40..3653e7e31d5 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -153,7 +153,7 @@ 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}; @@ -260,7 +260,7 @@ pub fn scoped<'a, T, F>(self, f: F) -> io::Result> where 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 } }) } @@ -642,7 +642,7 @@ fn drop(&mut self) { #[stable(feature = "rust1", since = "1.0.0")] pub struct JoinGuard<'a, T: 'a> { inner: JoinInner, - _marker: marker::CovariantType<&'a T>, + _marker: PhantomData<&'a T>, } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index d6778be553e..140e21b5d04 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -198,7 +198,7 @@ fn encode(&self, s: &mut S) -> Result<(), S::Error> { impl Decodable for Ident { fn decode(d: &mut D) -> Result { - Ok(str_to_ident(&try!(d.read_str())[])) + Ok(str_to_ident(&try!(d.read_str())[..])) } } diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs index 5535e5911e0..ba08f61b557 100644 --- a/src/libsyntax/ast_map/mod.rs +++ b/src/libsyntax/ast_map/mod.rs @@ -86,7 +86,7 @@ pub fn path_to_string>(path: PI) -> String { if !s.is_empty() { s.push_str("::"); } - s.push_str(&e[]); + s.push_str(&e[..]); s }) } @@ -251,7 +251,7 @@ fn entry_count(&self) -> usize { } fn find_entry(&self, id: NodeId) -> Option> { - self.map.borrow().get(id as usize).map(|e| *e) + self.map.borrow().get(id as usize).cloned() } pub fn krate(&self) -> &'ast Crate { @@ -463,20 +463,20 @@ pub fn with_attrs(&self, id: NodeId, f: F) -> T where 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). @@ -577,7 +577,7 @@ fn suffix_matches(&self, parent: NodeId) -> bool { 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); @@ -615,7 +615,7 @@ fn item_is_mod(item: &Item) -> bool { // 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) } } @@ -1026,7 +1026,7 @@ fn print_node(&mut self, node: &Node) -> IoResult<()> { 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)) => { diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs index 117507ad8b7..f660296fcd7 100644 --- a/src/libsyntax/ast_util.rs +++ b/src/libsyntax/ast_util.rs @@ -257,11 +257,11 @@ pub fn impl_pretty_name(trait_ref: &Option, ty: &Ty) -> Ident { 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 { @@ -673,7 +673,7 @@ pub fn pat_is_ident(pat: P) -> bool { 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? diff --git a/src/libsyntax/attr.rs b/src/libsyntax/attr.rs index a3afe5780d0..62e676891a0 100644 --- a/src/libsyntax/attr.rs +++ b/src/libsyntax/attr.rs @@ -26,11 +26,11 @@ 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 = RefCell::new(BitvSet::new()) } +thread_local! { static USED_ATTRS: RefCell = RefCell::new(BitSet::new()) } pub fn mark_used(attr: &Attribute) { let AttrId(id) = attr.node.id; @@ -44,7 +44,7 @@ pub fn is_used(attr: &Attribute) -> bool { 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]`, @@ -62,7 +62,7 @@ fn check_name(&self, name: &str) -> bool { 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); } @@ -101,7 +101,7 @@ fn value_str(&self) -> Option { fn meta_item_list<'a>(&'a self) -> Option<&'a [P]> { match self.node { - MetaList(_, ref l) => Some(&l[]), + MetaList(_, ref l) => Some(&l[..]), _ => None } } @@ -142,7 +142,7 @@ fn with_desugared_doc(&self, f: F) -> T where 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 { @@ -302,9 +302,9 @@ pub fn find_inline_attr(attrs: &[Attribute]) -> InlineAttr { } 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 @@ -326,11 +326,11 @@ pub fn requests_inline(attrs: &[Attribute]) -> bool { /// Tests if a cfg-pattern matches the cfg set pub fn cfg_matches(diagnostic: &SpanHandler, cfgs: &[P], 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; @@ -382,7 +382,7 @@ fn find_stability_generic<'a, '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 } @@ -404,7 +404,7 @@ fn find_stability_generic<'a, } } } - if &meta.name()[] == "since" { + if &meta.name()[..] == "since" { match meta.value_str() { Some(v) => since = Some(v), None => { @@ -413,7 +413,7 @@ fn find_stability_generic<'a, } } } - if &meta.name()[] == "reason" { + if &meta.name()[..] == "reason" { match meta.value_str() { Some(v) => reason = Some(v), None => { @@ -501,7 +501,7 @@ pub fn require_unique_names(diagnostic: &SpanHandler, metas: &[P]) { if !set.insert(name.clone()) { diagnostic.span_fatal(meta.span, - &format!("duplicate meta item `{}`", name)[]); + &format!("duplicate meta item `{}`", name)); } } } @@ -521,7 +521,7 @@ pub fn find_repr_attrs(diagnostic: &SpanHandler, attr: &Attribute) -> Vec { - 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), diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 3231342cb50..099f6462942 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -360,7 +360,7 @@ pub fn new_filemap(&self, filename: FileName, src: String) -> Rc { 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. diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs index 7ca0591be50..dfe3477bddc 100644 --- a/src/libsyntax/config.rs +++ b/src/libsyntax/config.rs @@ -311,7 +311,7 @@ fn fold_attribute(&mut self, attr: ast::Attribute) -> Option { } }; - 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, diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 83a4d938bb5..27219774cf1 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -129,7 +129,7 @@ pub fn span_bug(&self, sp: Span, msg: &str) -> ! { 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 @@ -173,7 +173,7 @@ pub fn abort_if_errors(&self) { 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); @@ -189,7 +189,7 @@ pub fn bug(&self, msg: &str) -> ! { 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)>, @@ -311,16 +311,16 @@ fn print_diagnostic(dst: &mut EmitterWriter, topic: &str, lvl: Level, } 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 => () } @@ -419,12 +419,12 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan, // 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))); } @@ -436,9 +436,9 @@ fn emit(dst: &mut EmitterWriter, cm: &codemap::CodeMap, rsp: RenderSpan, 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 => () }, @@ -455,7 +455,7 @@ fn highlight_lines(err: &mut EmitterWriter, 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; @@ -542,7 +542,7 @@ fn highlight_lines(err: &mut EmitterWriter, } try!(print_maybe_styled(err, - &format!("{}\n", s)[], + &format!("{}\n", s), term::attr::ForegroundColor(lvl.color()))); } } @@ -563,7 +563,7 @@ fn custom_highlight_lines(w: &mut EmitterWriter, -> 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, @@ -610,7 +610,7 @@ fn custom_highlight_lines(w: &mut EmitterWriter, s.push('^'); s.push('\n'); print_maybe_styled(w, - &s[], + &s[..], term::attr::ForegroundColor(lvl.color())) } @@ -618,22 +618,25 @@ fn print_macro_backtrace(w: &mut EmitterWriter, 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)) } @@ -643,6 +646,6 @@ pub fn expect(diag: &SpanHandler, opt: Option, msg: M) -> T where { match opt { Some(t) => t, - None => diag.handler().bug(&msg()[]), + None => diag.handler().bug(&msg()), } } diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index 833a6d52acb..b3afc3fc4dd 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -59,7 +59,7 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt, Some(previous_span) => { ecx.span_warn(span, &format!( "diagnostic code {} already used", &token::get_ident(code) - )[]); + )); ecx.span_note(previous_span, "previous invocation"); }, None => () @@ -70,7 +70,7 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt, 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, ())) @@ -95,12 +95,12 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, 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()) } diff --git a/src/libsyntax/diagnostics/registry.rs b/src/libsyntax/diagnostics/registry.rs index 62d48189c43..a6cfd1a5a9a 100644 --- a/src/libsyntax/diagnostics/registry.rs +++ b/src/libsyntax/diagnostics/registry.rs @@ -17,10 +17,10 @@ pub struct Registry { 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() } } diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index 8800ffd1e9b..d4ccabbd63b 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -640,7 +640,7 @@ pub fn original_span_in_file(&self) -> Span { pub fn mod_path(&self) -> Vec { 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) { diff --git a/src/libsyntax/ext/concat.rs b/src/libsyntax/ext/concat.rs index 80d128959ea..38098e50dee 100644 --- a/src/libsyntax/ext/concat.rs +++ b/src/libsyntax/ext/concat.rs @@ -62,5 +62,5 @@ pub fn expand_syntax_ext(cx: &mut base::ExtCtxt, } base::MacExpr::new(cx.expr_str( sp, - token::intern_and_get_ident(&accumulator[]))) + token::intern_and_get_ident(&accumulator[..]))) } diff --git a/src/libsyntax/ext/concat_idents.rs b/src/libsyntax/ext/concat_idents.rs index 63a8bd9ddf1..9410a51e7a5 100644 --- a/src/libsyntax/ext/concat_idents.rs +++ b/src/libsyntax/ext/concat_idents.rs @@ -49,7 +49,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree] } } } - let res = str_to_ident(&res_str[]); + let res = str_to_ident(&res_str[..]); let e = P(ast::Expr { id: ast::DUMMY_NODE_ID, diff --git a/src/libsyntax/ext/deriving/bounds.rs b/src/libsyntax/ext/deriving/bounds.rs index 879718a6399..93098484ae0 100644 --- a/src/libsyntax/ext/deriving/bounds.rs +++ b/src/libsyntax/ext/deriving/bounds.rs @@ -24,7 +24,7 @@ pub fn expand_deriving_bound(cx: &mut ExtCtxt, { let name = match mitem.node { MetaWord(ref tname) => { - match &tname[] { + match &tname[..] { "Copy" => "Copy", "Send" | "Sync" => { return cx.span_err(span, diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs index f878cb5ca8b..b912ed34ae0 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -367,7 +367,7 @@ pub fn expand(&self, "allow" | "warn" | "deny" | "forbid" => true, _ => false, } - }).map(|a| a.clone())); + }).cloned()); push(P(ast::Item { attrs: attrs, ..(*newitem).clone() @@ -410,7 +410,7 @@ fn create_derived_impl(&self, 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| { @@ -445,14 +445,14 @@ fn create_derived_impl(&self, 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) => { @@ -500,7 +500,7 @@ fn create_derived_impl(&self, 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, @@ -536,15 +536,15 @@ fn expand_struct_def(&self, 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, @@ -576,15 +576,15 @@ fn expand_enum_def(&self, 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, @@ -934,22 +934,22 @@ fn build_enum_match_tuple( .collect::>(); let self_arg_idents = self_arg_names.iter() - .map(|name|cx.ident_of(&name[])) + .map(|name|cx.ident_of(&name[..])) .collect::>(); // 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 = 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::>(); // 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 @@ -976,7 +976,7 @@ fn build_enum_match_tuple( 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); } @@ -1032,7 +1032,7 @@ fn build_enum_match_tuple( &**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) @@ -1085,7 +1085,7 @@ fn build_enum_match_tuple( } 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: @@ -1391,7 +1391,7 @@ pub fn cs_fold(use_foldl: bool, } }, 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`") @@ -1431,7 +1431,7 @@ pub fn cs_same_method(f: F, 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`") diff --git a/src/libsyntax/ext/deriving/hash.rs b/src/libsyntax/ext/deriving/hash.rs index 5aa9f9a0c3e..2149c7a7f77 100644 --- a/src/libsyntax/ext/deriving/hash.rs +++ b/src/libsyntax/ext/deriving/hash.rs @@ -14,7 +14,6 @@ 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(cx: &mut ExtCtxt, @@ -26,30 +25,26 @@ pub fn expand_deriving_hash(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) }) diff --git a/src/libsyntax/ext/deriving/mod.rs b/src/libsyntax/ext/deriving/mod.rs index 0ed9e85e576..f8bc331bfcf 100644 --- a/src/libsyntax/ext/deriving/mod.rs +++ b/src/libsyntax/ext/deriving/mod.rs @@ -102,7 +102,7 @@ macro_rules! expand { |i| push(i))) } - match &tname[] { + match &tname[..] { "Clone" => expand!(clone::expand_deriving_clone), "Hash" => expand!(hash::expand_deriving_hash), diff --git a/src/libsyntax/ext/deriving/show.rs b/src/libsyntax/ext/deriving/show.rs index 3f5947672e0..281f23f9e61 100644 --- a/src/libsyntax/ext/deriving/show.rs +++ b/src/libsyntax/ext/deriving/show.rs @@ -128,7 +128,7 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span, 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! diff --git a/src/libsyntax/ext/env.rs b/src/libsyntax/ext/env.rs index 5d56707c87a..9c04d1e9282 100644 --- a/src/libsyntax/ext/env.rs +++ b/src/libsyntax/ext/env.rs @@ -30,7 +30,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT Some(v) => v }; - let e = match env::var(&var[]) { + let e = match env::var(&var[..]) { Err(..) => { cx.expr_path(cx.path_all(sp, true, @@ -56,7 +56,7 @@ pub fn expand_option_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenT cx.ident_of("Some")), vec!(cx.expr_str(sp, token::intern_and_get_ident( - &s[])))) + &s[..])))) } }; MacExpr::new(e) @@ -101,7 +101,7 @@ pub fn expand_env<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) } } - let e = match env::var(&var[]) { + let e = match env::var(&var[..]) { Err(_) => { cx.span_err(sp, &msg); cx.expr_usize(sp, 0) diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs index 6b7cecee815..d4dda7390a5 100644 --- a/src/libsyntax/ext/expand.rs +++ b/src/libsyntax/ext/expand.rs @@ -405,7 +405,7 @@ fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, }, }); 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 @@ -416,7 +416,7 @@ fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, let opt_parsed = { let expanded = expandfun.expand(fld.cx, mac_span, - &marked_before[]); + &marked_before[..]); parse_thunk(expanded) }; let parsed = match opt_parsed { @@ -425,7 +425,7 @@ fn expand_mac_invoc(mac: ast::Mac, span: codemap::Span, fld.cx.span_err( pth.span, &format!("non-expression macro in expression position: {}", - &extnamestr[] + &extnamestr[..] )[]); return None; } @@ -633,8 +633,8 @@ pub fn expand_item_mac(it: P, } }); // 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 { @@ -652,7 +652,7 @@ pub fn expand_item_mac(it: P, } }); // 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 => { @@ -971,11 +971,11 @@ fn expand_pat(p: P, fld: &mut MacroExpander) -> P { }); 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( @@ -1128,7 +1128,7 @@ fn expand_annotatable(a: Annotatable, 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)); @@ -1508,7 +1508,7 @@ fn fold_mac(&mut self, Spanned {node, span}: ast::Mac) -> ast::Mac { 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)) } }, @@ -1914,7 +1914,7 @@ fn run_renaming_test(t: &RenamingTest, test_idx: usize) { .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)); @@ -1967,10 +1967,10 @@ fn run_renaming_test(t: &RenamingTest, test_idx: usize) { 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") diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 170a455a913..e17329d7d33 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -118,7 +118,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) } }; let interned_name = token::get_ident(ident); - let name = &interned_name[]; + let name = &interned_name[..]; p.expect(&token::Eq); let e = p.parse_expr(); @@ -218,7 +218,7 @@ fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) { 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; } { @@ -238,7 +238,7 @@ fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) { 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; } }; @@ -587,7 +587,7 @@ fn format_arg(ecx: &ExtCtxt, sp: Span, -> P { let trait_ = match *ty { Known(ref tyname) => { - match &tyname[] { + match &tyname[..] { "" => "Display", "?" => "Debug", "e" => "LowerExp", diff --git a/src/libsyntax/ext/quote.rs b/src/libsyntax/ext/quote.rs index 67990895d07..2c7bf713aad 100644 --- a/src/libsyntax/ext/quote.rs +++ b/src/libsyntax/ext/quote.rs @@ -668,7 +668,7 @@ fn mk_tt(cx: &ExtCtxt, tt: &ast::TokenTree) -> Vec> { 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")); @@ -757,7 +757,7 @@ fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree]) 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, diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index 7a3a3562bdf..c8d48750c75 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -65,7 +65,7 @@ pub fn expand_stringify(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) -> Box { 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]) @@ -78,7 +78,7 @@ 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 @@ -117,7 +117,7 @@ fn make_items(mut self: Box>) None => self.p.span_fatal( self.p.span, &format!("expected item, found `{}`", - self.p.this_token_to_string())[] + self.p.this_token_to_string()) ) } } @@ -141,7 +141,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) cx.span_err(sp, &format!("couldn't read {}: {}", file.display(), - e)[]); + e)); return DummyResult::expr(sp); } Ok(bytes) => bytes, @@ -151,7 +151,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) // 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)) @@ -159,7 +159,7 @@ pub fn expand_include_str(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) Err(_) => { cx.span_err(sp, &format!("{} wasn't a utf-8 file", - file.display())[]); + file.display())); return DummyResult::expr(sp); } } @@ -175,11 +175,11 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]) 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)))) } } diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index d649e497ef7..664f7b3e088 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -165,7 +165,7 @@ pub fn count_names(ms: &[TokenTree]) -> usize { pub fn initial_matcher_pos(ms: Rc>, sep: Option, lo: BytePos) -> Box { - 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![], @@ -229,7 +229,7 @@ fn n_rec(p_s: &ParseSess, m: &TokenTree, res: &[Rc], p_s.span_diagnostic .span_fatal(sp, &format!("duplicated bind name: {}", - &string)[]) + &string)) } } } @@ -254,13 +254,13 @@ pub fn parse_or_else(sess: &ParseSess, rdr: TtReader, ms: Vec ) -> HashMap> { - 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[..]) } } } @@ -283,7 +283,7 @@ pub fn parse(sess: &ParseSess, -> 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)); @@ -447,7 +447,7 @@ pub fn parse(sess: &ParseSess, 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 { @@ -533,7 +533,7 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal { _ => { let token_str = pprust::token_to_string(&p.token); p.fatal(&format!("expected ident, found {}", - &token_str[])[]) + &token_str[..])) } }, "path" => { @@ -542,7 +542,7 @@ pub fn parse_nt(p: &mut Parser, sp: Span, name: &str) -> Nonterminal { "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`") diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index f322cf8bad0..fa6d934a457 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -50,7 +50,7 @@ fn ensure_complete_parse(&self, allow_semi: bool) { following", token_str); let span = parser.span; - parser.span_err(span, &msg[]); + parser.span_err(span, &msg[..]); } } } @@ -123,8 +123,8 @@ fn expand<'cx>(&self, self.name, self.imported_from, arg, - &self.lhses[], - &self.rhses[]) + &self.lhses, + &self.rhses) } } @@ -151,7 +151,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, 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 @@ -159,7 +159,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, None, None, arg.iter() - .map(|x| (*x).clone()) + .cloned() .collect(), true); match parse(cx.parse_sess(), cx.cfg(), arg_rdr, lhs_tt) { @@ -192,13 +192,13 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, 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: diff --git a/src/libsyntax/ext/tt/transcribe.rs b/src/libsyntax/ext/tt/transcribe.rs index 83234e3b7a5..0d92bd761b4 100644 --- a/src/libsyntax/ext/tt/transcribe.rs +++ b/src/libsyntax/ext/tt/transcribe.rs @@ -255,7 +255,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { } 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 { @@ -309,7 +309,7 @@ pub fn tt_next_token(r: &mut TtReader) -> TokenAndSpan { 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))); } } } diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs index 0110823ae98..071158fcebb 100644 --- a/src/libsyntax/feature_gate.rs +++ b/src/libsyntax/feature_gate.rs @@ -356,7 +356,7 @@ pub fn emit_feature_err(diag: &SpanHandler, feature: &str, span: Span, explain: 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) { @@ -364,7 +364,7 @@ pub fn emit_feature_warn(diag: &SpanHandler, feature: &str, span: Span, explain: if diag.handler.can_emit_warnings { diag.span_help(span, &format!("add #![feature({})] to the \ crate attributes to silence this warning", - feature)[]); + feature)); } } @@ -438,7 +438,7 @@ fn visit_name(&mut self, sp: Span, name: ast::Name) { 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"); @@ -446,7 +446,7 @@ fn visit_item(&mut self, i: &ast::Item) { } 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 \ @@ -460,17 +460,17 @@ fn visit_item(&mut self, i: &ast::Item) { } 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 \ @@ -479,7 +479,7 @@ fn visit_item(&mut self, i: &ast::Item) { } 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"); } @@ -505,7 +505,7 @@ fn visit_item(&mut self, i: &ast::Item) { 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", @@ -513,7 +513,7 @@ fn visit_item(&mut self, i: &ast::Item) { "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, @@ -528,7 +528,7 @@ fn visit_item(&mut self, i: &ast::Item) { } 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") diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index e8bdcd62b58..3a7fa54edbd 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -28,7 +28,6 @@ #![feature(collections)] #![feature(core)] #![feature(env)] -#![feature(hash)] #![feature(int_uint)] #![feature(old_io)] #![feature(libc)] diff --git a/src/libsyntax/owned_slice.rs b/src/libsyntax/owned_slice.rs index 0f9a56baa17..f5201d4a8bc 100644 --- a/src/libsyntax/owned_slice.rs +++ b/src/libsyntax/owned_slice.rs @@ -10,7 +10,7 @@ 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}; @@ -77,8 +77,8 @@ fn clone(&self) -> OwnedSlice { } impl FromIterator for OwnedSlice { - fn from_iter>(iter: I) -> OwnedSlice { - OwnedSlice::from_vec(iter.collect()) + fn from_iter>(iter: I) -> OwnedSlice { + OwnedSlice::from_vec(iter.into_iter().collect()) } } diff --git a/src/libsyntax/parse/lexer/comments.rs b/src/libsyntax/parse/lexer/comments.rs index b17fc7fe82e..1f06db60027 100644 --- a/src/libsyntax/parse/lexer/comments.rs +++ b/src/libsyntax/parse/lexer/comments.rs @@ -61,7 +61,7 @@ pub fn doc_comment_style(comment: &str) -> ast::AttrStyle { pub fn strip_doc_comment_decoration(comment: &str) -> String { /// remove whitespace-only lines from the start/end of lines - fn vertical_trim(lines: Vec ) -> Vec { + fn vertical_trim(lines: Vec) -> Vec { let mut i = 0; let mut j = lines.len(); // first line of all-stars should be omitted @@ -82,7 +82,7 @@ fn vertical_trim(lines: Vec ) -> Vec { 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 @@ -187,7 +187,7 @@ fn read_line_comments(rdr: &mut StringReader, code_to_the_left: bool, 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); @@ -224,7 +224,7 @@ fn all_whitespace(s: &str, col: CharPos) -> Option { fn trim_whitespace_prefix_and_push_line(lines: &mut Vec , 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() @@ -261,7 +261,7 @@ fn read_block_comment(rdr: &mut StringReader, 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')); diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 38ba0b38df5..fd08cbd161b 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -16,14 +16,13 @@ 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}; @@ -196,7 +195,7 @@ fn fatal_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) 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 @@ -205,7 +204,7 @@ fn err_span_char(&self, from_pos: BytePos, to_pos: BytePos, m: &str, c: char) { 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 @@ -215,7 +214,7 @@ fn fatal_span_verbose(&self, from_pos: BytePos, to_pos: BytePos, mut m: String) 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 @@ -278,7 +277,7 @@ fn with_str_from_to(&self, start: BytePos, end: BytePos, f: F) -> T where /// 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); @@ -556,7 +555,7 @@ fn scan_block_comment(&mut self) -> Option { 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 }; diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 6ea23cf3f04..7ed48bdbb92 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -258,7 +258,7 @@ pub fn file_to_filemap(sess: &ParseSess, path: &Path, spanopt: Option) 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()) @@ -398,7 +398,7 @@ pub fn char_lit(lit: &str) -> (char, isize) { } 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() @@ -662,7 +662,7 @@ pub fn integer_lit(s: &str, suffix: Option<&str>, sd: &SpanHandler, sp: Span) -> // s can only be ascii, byte indexing is fine let s2 = s.chars().filter(|&c| c != '_').collect::(); - let mut s = &s2[]; + let mut s = &s2[..]; debug!("integer_lit: {}, {:?}", s, suffix); @@ -819,7 +819,7 @@ fn sp(a: u32, b: u32) -> Span { #[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), @@ -1114,24 +1114,24 @@ fn parser_done(p: Parser){ 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 { @@ -1203,19 +1203,19 @@ fn wb() -> c_int { O_WRONLY as c_int } 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::>(); 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] @@ -1235,7 +1235,7 @@ fn ttdelim_span() { 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"), } } diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs index 1df2e762ee7..8480772ce6c 100644 --- a/src/libsyntax/parse/obsolete.rs +++ b/src/libsyntax/parse/obsolete.rs @@ -28,6 +28,7 @@ pub enum ObsoleteSyntax { ProcExpr, ClosureType, ClosureKind, + EmptyIndex, } pub trait ParserObsoleteMethods { @@ -40,7 +41,8 @@ fn report(&mut self, 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; } @@ -48,35 +50,46 @@ fn report(&mut self, 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 @@ -90,9 +103,13 @@ fn report(&mut self, 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 diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 407740e580d..370201e5382 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -240,9 +240,8 @@ macro_rules! maybe_whole { fn maybe_append(mut lhs: Vec, rhs: Option>) -> Vec { - 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 } @@ -362,7 +361,7 @@ pub fn unexpected_last(&self, t: &token::Token) -> ! { 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) -> ! { @@ -381,7 +380,7 @@ pub fn expect(&mut self, t: &token::Token) { 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), &[]); @@ -422,7 +421,7 @@ fn tokens_to_string(tokens: &[TokenType]) -> String { 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 { @@ -436,7 +435,7 @@ fn tokens_to_string(tokens: &[TokenType]) -> String { (format!("expected {}, found `{}`", expect, actual)) - }[]) + })[..] ) } } @@ -467,9 +466,9 @@ pub fn commit_expr(&mut self, e: &Expr, edible: &[token::Token], inedible: &[tok 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::>(); + let mut expected = edible.iter().cloned().collect::>(); 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) } @@ -485,10 +484,9 @@ pub fn commit_stmt(&mut self, edible: &[token::Token], inedible: &[token::Token] 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::>(); - expected.push_all(&inedible[]); - self.check_for_erroneous_unit_struct_expecting( - &expected[]); + let mut expected = edible.iter().cloned().collect::>(); + expected.push_all(&inedible); + self.check_for_erroneous_unit_struct_expecting(&expected); } self.expect_one_of(edible, inedible) } @@ -511,7 +509,7 @@ pub fn parse_ident(&mut self) -> ast::Ident { _ => { let token_str = self.this_token_to_string(); self.fatal(&format!("expected ident, found `{}`", - token_str)[]) + token_str)) } } } @@ -599,7 +597,7 @@ pub fn check_strict_keywords(&mut self) { let span = self.span; self.span_err(span, &format!("expected identifier, found keyword `{}`", - token_str)[]); + token_str)); } } @@ -608,7 +606,7 @@ pub fn check_reserved_keywords(&mut self) { 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)) } } @@ -734,7 +732,7 @@ pub fn expect_gt(&mut self) { let this_token_str = self.this_token_to_string(); self.fatal(&format!("expected `{}`, found `{}`", gt_str, - this_token_str)[]) + this_token_str)) } } } @@ -1364,7 +1362,7 @@ pub fn parse_trait_items(&mut self) -> Vec { 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, @@ -1383,7 +1381,7 @@ pub fn parse_trait_items(&mut self) -> Vec { _ => { let token_str = p.this_token_to_string(); p.fatal(&format!("expected `;` or `{{`, found `{}`", - token_str)[]) + token_str)[..]) } } } @@ -1551,7 +1549,7 @@ pub fn parse_ty(&mut self) -> P { } 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); @@ -1699,14 +1697,14 @@ pub fn lit_from_token(&self, tok: &token::Token) -> Lit_ { 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 { @@ -1944,7 +1942,7 @@ pub fn parse_lifetime(&mut self) -> ast::Lifetime { }; } _ => { - self.fatal(&format!("expected a lifetime name")[]); + self.fatal(&format!("expected a lifetime name")); } } } @@ -1982,7 +1980,7 @@ pub fn parse_lifetime_defs(&mut self) -> Vec { let msg = format!("expected `,` or `>` after lifetime \ name, found `{}`", this_token_str); - self.fatal(&msg[]); + self.fatal(&msg[..]); } } } @@ -2497,7 +2495,7 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: P) -> P { 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::().ok() { Some(f) => f, @@ -2506,7 +2504,7 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: P) -> P { 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(); @@ -2552,8 +2550,9 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: P) -> P { 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, }; @@ -2562,10 +2561,8 @@ pub fn parse_dot_or_call_expr_with(&mut self, e0: P) -> P { 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; @@ -2639,7 +2636,7 @@ pub fn check_unknown_macro_variable(&mut self) { match self.token { token::SubstNt(name, _) => self.fatal(&format!("unknown macro variable `{}`", - token::get_ident(name))[]), + token::get_ident(name))), _ => {} } } @@ -2701,7 +2698,7 @@ fn parse_non_delim_tt_tok(p: &mut Parser) -> TokenTree { }; 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 => { @@ -2822,7 +2819,7 @@ pub fn parse_prefix_expr(&mut self) -> P { 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?"); @@ -3275,7 +3272,7 @@ fn parse_pat_fields(&mut self) -> (Vec> , bool) 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; @@ -3576,7 +3573,7 @@ fn parse_pat_ident(&mut self, 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; @@ -3673,7 +3670,7 @@ fn check_expected_item(p: &mut Parser, attrs: &[Attribute]) { 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))) @@ -3682,7 +3679,7 @@ fn check_expected_item(p: &mut Parser, attrs: &[Attribute]) { && 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... @@ -3710,7 +3707,7 @@ fn check_expected_item(p: &mut Parser, attrs: &[Attribute]) { let tok_str = self.this_token_to_string(); self.fatal(&format!("expected {}`(` or `{{`, found `{}`", ident_str, - tok_str)[]) + tok_str)) }, }; @@ -3758,7 +3755,7 @@ fn check_expected_item(p: &mut Parser, attrs: &[Attribute]) { } } 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; @@ -3795,7 +3792,7 @@ pub fn parse_block(&mut self) -> P { 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"); } @@ -3830,13 +3827,13 @@ fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode, 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 @@ -3928,7 +3925,7 @@ fn parse_block_tail_(&mut self, lo: BytePos, s: BlockCheckMode, 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; @@ -4383,7 +4380,7 @@ fn expect_self_ident(&mut self) -> ast::Ident { _ => { let token_str = self.this_token_to_string(); self.fatal(&format!("expected `self`, found `{}`", - token_str)[]) + token_str)) } } } @@ -4404,7 +4401,7 @@ fn expect_self_type_ident(&mut self) -> ast::Ident { _ => { let token_str = self.this_token_to_string(); self.fatal(&format!("expected `Self`, found `{}`", - token_str)[]) + token_str)) } } } @@ -4539,7 +4536,7 @@ macro_rules! parse_remaining_arguments { _ => { let token_str = self.this_token_to_string(); self.fatal(&format!("expected `,` or `)`, found `{}`", - token_str)[]) + token_str)) } } } @@ -4712,7 +4709,7 @@ pub fn parse_method(&mut self, 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, @@ -4942,7 +4939,7 @@ pub fn parse_record_struct_body(&mut self, class_name: &ast::Ident) -> Vec Vec items.push(item), Err(_) => { let token_str = self.this_token_to_string(); self.fatal(&format!("expected item, found `{}`", - token_str)[]) + token_str)) } } } @@ -5124,7 +5121,7 @@ fn parse_mod_items(&mut self, // 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 { @@ -5203,8 +5200,8 @@ fn eval_src_mod(&mut self, 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(); @@ -5219,13 +5216,13 @@ fn eval_src_mod(&mut self, &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(); } @@ -5236,12 +5233,12 @@ fn eval_src_mod(&mut self, (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( @@ -5250,7 +5247,7 @@ fn eval_src_mod(&mut self, and {}", mod_name, default_path_str, - secondary_path_str)[], + secondary_path_str), "delete or rename one of them to remove the ambiguity"); } } @@ -5272,11 +5269,11 @@ fn eval_src_mod_from_path(&mut self, 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 => () } @@ -5381,7 +5378,7 @@ fn parse_item_extern_crate(&mut self, 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 @@ -5407,7 +5404,7 @@ fn parse_item_extern_crate(&mut self, self.span_fatal(span, &format!("expected extern crate name but \ found `{}`", - token_str)[]); + token_str)); } }; @@ -5505,7 +5502,7 @@ fn parse_enum_def(&mut self, _generics: &ast::Generics) -> EnumDef { 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)) { @@ -5583,7 +5580,7 @@ fn parse_opt_abi(&mut self) -> Option { &format!("illegal ABI: expected one of [{}], \ found `{}`", abi::all_names().connect(", "), - the_string)[]); + the_string)); None } } @@ -5663,7 +5660,7 @@ fn parse_item_(&mut self, attrs: Vec, 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) { @@ -5772,7 +5769,7 @@ fn parse_item_(&mut self, attrs: Vec, 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, @@ -6057,7 +6054,7 @@ fn parse_view_path(&mut self) -> P { fn parse_foreign_items(&mut self, first_item_attrs: Vec) -> Vec> { 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) { @@ -6078,7 +6075,7 @@ fn parse_foreign_items(&mut self, first_item_attrs: Vec) 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 diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 0747a97fa37..433c013591c 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -482,7 +482,7 @@ fn mk_fresh_ident_interner() -> IdentInterner { $(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[..]) } }} @@ -644,7 +644,7 @@ fn container_as_bytes<'a>(&'a self) -> &'a [u8] { // 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()) } } diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index 6c6cf186e70..1593bfb97fe 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -539,8 +539,8 @@ pub fn print_str(&mut self, s: &str) -> old_io::IoResult<()> { 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)); @@ -607,7 +607,7 @@ pub fn print(&mut self, token: Token, l: isize) -> old_io::IoResult<()> { 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. diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 4b021f2434f..f26578e7401 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -134,7 +134,7 @@ pub fn print_crate<'a>(cm: &'a CodeMap, 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) } @@ -602,7 +602,7 @@ pub fn break_offset_if_not_bol(&mut self, n: usize, 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, "*/") } @@ -701,7 +701,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> { } 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, ",")); @@ -734,10 +734,10 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> { } 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)) @@ -765,7 +765,7 @@ pub fn print_foreign_item(&mut self, 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, @@ -776,7 +776,7 @@ pub fn print_foreign_item(&mut self, } ast::ForeignItemStatic(ref t, m) => { try!(self.head(&visibility_qualified(item.vis, - "static")[])); + "static"))); if m { try!(self.word_space("mut")); } @@ -793,7 +793,7 @@ pub fn print_foreign_item(&mut self, 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, ";") @@ -812,12 +812,12 @@ fn print_typedef(&mut self, typedef: &ast::Typedef) -> IoResult<()> { 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)); @@ -831,7 +831,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> { } 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 @@ -839,7 +839,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> { } 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")); } @@ -856,7 +856,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> { } 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)); @@ -879,28 +879,28 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> { 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 @@ -922,7 +922,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> { )); } 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)); } @@ -963,7 +963,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> { 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) => { @@ -983,18 +983,17 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> { 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()); @@ -1012,7 +1011,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> { 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()); @@ -1050,12 +1049,12 @@ pub fn print_enum_def(&mut self, enum_definition: &ast::EnumDef, 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, @@ -1065,7 +1064,7 @@ 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, ",")); @@ -1093,7 +1092,7 @@ pub fn print_struct(&mut self, 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"), @@ -1123,7 +1122,7 @@ pub fn print_struct(&mut self, 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(":")); @@ -1147,7 +1146,7 @@ pub fn print_struct(&mut self, 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) @@ -1156,11 +1155,11 @@ pub fn print_tt(&mut self, tt: &ast::TokenTree) -> IoResult<()> { } } 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, "$(")); @@ -1170,7 +1169,7 @@ pub fn print_tt(&mut self, tt: &ast::TokenTree) -> IoResult<()> { 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 => {}, } @@ -1210,7 +1209,7 @@ pub fn print_variant(&mut self, v: &ast::Variant) -> IoResult<()> { if !args.is_empty() { try!(self.popen()); try!(self.commasep(Consistent, - &args[], + &args[..], |s, arg| s.print_type(&*arg.ty))); try!(self.pclose()); } @@ -1234,7 +1233,7 @@ pub fn print_variant(&mut self, v: &ast::Variant) -> IoResult<()> { 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, @@ -1263,7 +1262,7 @@ pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> IoResult<()> { 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, @@ -1281,7 +1280,7 @@ pub fn print_method(&mut self, meth: &ast::Method) -> IoResult<()> { 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, _), ..}) => { @@ -1290,7 +1289,7 @@ pub fn print_method(&mut self, meth: &ast::Method) -> IoResult<()> { 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() @@ -1552,7 +1551,7 @@ fn print_expr_box(&mut self, fn print_expr_vec(&mut self, exprs: &[P]) -> 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() } @@ -1578,7 +1577,7 @@ fn print_expr_struct(&mut self, 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)); @@ -1607,7 +1606,7 @@ fn print_expr_struct(&mut self, fn print_expr_tup(&mut self, exprs: &[P]) -> 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, ",")); } @@ -1672,22 +1671,22 @@ pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> { 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)); @@ -1875,11 +1874,11 @@ pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> { 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)) @@ -1892,7 +1891,7 @@ pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> { 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()); @@ -1903,7 +1902,7 @@ pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> { 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(()) @@ -1977,7 +1976,7 @@ pub fn print_decl(&mut self, decl: &ast::Decl) -> IoResult<()> { 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))) } @@ -1985,7 +1984,7 @@ pub fn print_ident(&mut self, ident: ast::Ident) -> IoResult<()> { } 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<()> { @@ -2075,7 +2074,7 @@ fn print_path_parameters(&mut self, } try!(self.commasep( Inconsistent, - &data.types[], + &data.types, |s, ty| s.print_type(&**ty))); comma = true; } @@ -2098,7 +2097,7 @@ fn print_path_parameters(&mut self, try!(word(&mut self.s, "(")); try!(self.commasep( Inconsistent, - &data.inputs[], + &data.inputs, |s, ty| s.print_type(&**ty))); try!(word(&mut self.s, ")")); @@ -2151,7 +2150,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> { 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()); } @@ -2163,7 +2162,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> { 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 { @@ -2184,7 +2183,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> { 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, ",")); @@ -2212,7 +2211,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> { 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(",")); } @@ -2226,7 +2225,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> { 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, "]")); } @@ -2243,7 +2242,7 @@ fn print_arm(&mut self, arm: &ast::Arm) -> IoResult<()> { } 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 { @@ -2475,7 +2474,7 @@ pub fn print_generics(&mut self, 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) @@ -2492,7 +2491,7 @@ pub fn print_generics(&mut self, 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)); @@ -2562,7 +2561,7 @@ pub fn print_meta_item(&mut self, item: &ast::MetaItem) -> IoResult<()> { 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)); } @@ -2570,7 +2569,7 @@ pub fn print_meta_item(&mut self, item: &ast::MetaItem) -> IoResult<()> { 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()); } @@ -2606,7 +2605,7 @@ pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> { 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) @@ -2753,7 +2752,7 @@ pub fn print_literal(&mut self, lit: &ast::Lit) -> IoResult<()> { 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); } _ => () } @@ -2763,33 +2762,33 @@ pub fn print_literal(&mut self, lit: &ast::Lit) -> IoResult<()> { 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)) } } } @@ -2798,9 +2797,9 @@ pub fn print_literal(&mut self, lit: &ast::Lit) -> IoResult<()> { &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") } } @@ -2810,7 +2809,7 @@ pub fn print_literal(&mut self, lit: &ast::Lit) -> IoResult<()> { 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)) } } } @@ -2851,7 +2850,7 @@ pub fn print_comment(&mut self, 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 => { @@ -2860,7 +2859,7 @@ pub fn print_comment(&mut self, // 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)); } @@ -2869,13 +2868,13 @@ pub fn print_comment(&mut self, 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)); } @@ -2908,7 +2907,7 @@ pub fn print_string(&mut self, st: &str, string=st)) } }; - word(&mut self.s, &st[]) + word(&mut self.s, &st[..]) } pub fn next_comment(&mut self) -> Option { @@ -2939,7 +2938,7 @@ pub fn print_opt_abi_and_extern_if_nondefault(&mut self, 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(()) } @@ -2950,7 +2949,7 @@ pub fn print_extern_opt_abi(&mut self, match opt_abi { Some(abi) => { try!(self.word_nbsp("extern")); - self.word_nbsp(&abi.to_string()[]) + self.word_nbsp(&abi.to_string()) } None => Ok(()) } @@ -2965,7 +2964,7 @@ pub fn print_fn_header_info(&mut self, 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") diff --git a/src/libsyntax/ptr.rs b/src/libsyntax/ptr.rs index 01f3839b039..adb5383a8fd 100644 --- a/src/libsyntax/ptr.rs +++ b/src/libsyntax/ptr.rs @@ -111,11 +111,18 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { } } +#[cfg(stage0)] impl> Hash for P { fn hash(&self, state: &mut S) { (**self).hash(state); } } +#[cfg(not(stage0))] +impl Hash for P { + fn hash(&self, state: &mut H) { + (**self).hash(state); + } +} impl Decodable for P { fn decode(d: &mut D) -> Result, D::Error> { diff --git a/src/libsyntax/std_inject.rs b/src/libsyntax/std_inject.rs index 98c193c7e6b..4e4a571ede7 100644 --- a/src/libsyntax/std_inject.rs +++ b/src/libsyntax/std_inject.rs @@ -45,16 +45,16 @@ fn no_prelude(attrs: &[ast::Attribute]) -> bool { attr::contains_name(attrs, "no_implicit_prelude") } -struct StandardLibraryInjector<'a> { - alt_std_name: Option +struct StandardLibraryInjector { + alt_std_name: Option, } -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"), }; @@ -80,9 +80,10 @@ fn inject_crates_ref(krate: ast::Crate, alt_std_name: Option) -> ast::Cr 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. diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs index 6511dffa6bf..7b1fc91e45b 100644 --- a/src/libsyntax/test.rs +++ b/src/libsyntax/test.rs @@ -119,7 +119,7 @@ fn fold_item(&mut self, i: P) -> SmallVector> { 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 { @@ -274,8 +274,8 @@ fn strip_test_functions(krate: ast::Crate) -> ast::Crate { // 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") }) } @@ -563,7 +563,7 @@ fn mk_tests(cx: &TestCtxt) -> P { 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 } } @@ -603,11 +603,11 @@ fn mk_test_desc_and_fn_rec(cx: &TestCtxt, test: &Test) -> P { // 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, diff --git a/src/libsyntax/util/interner.rs b/src/libsyntax/util/interner.rs index 51144267519..dffeac6f3f7 100644 --- a/src/libsyntax/util/interner.rs +++ b/src/libsyntax/util/interner.rs @@ -14,13 +14,13 @@ 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; @@ -30,6 +30,7 @@ pub struct Interner { } // when traits can extend traits, we should extend index to get [] +#[cfg(stage0)] impl + Clone + 'static> Interner { pub fn new() -> Interner { Interner { @@ -79,7 +80,71 @@ pub fn len(&self) -> usize { } pub fn find(&self, val: &Q) -> Option - where Q: BorrowFrom + Eq + Hash { + where T: Borrow, Q: Eq + Hash { + let map = self.map.borrow(); + match (*map).get(val) { + Some(v) => Some(*v), + 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 to get [] +#[cfg(not(stage0))] +impl Interner { + pub fn new() -> Interner { + Interner { + map: RefCell::new(HashMap::new()), + vect: RefCell::new(Vec::new()), + } + } + + pub fn prefill(init: &[T]) -> Interner { + 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(&self, val: &Q) -> Option + where T: Borrow, Q: Eq + Hash { let map = self.map.borrow(); match (*map).get(val) { Some(v) => Some(*v), @@ -110,34 +175,34 @@ impl Eq for RcStr {} 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 for str { - fn borrow_from(owned: &RcStr) -> &str { - &owned.string[] +impl Borrow 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 in that it accepts @@ -210,8 +275,17 @@ pub fn len(&self) -> usize { self.vect.borrow().len() } + #[cfg(stage0)] + pub fn find(&self, val: &Q) -> Option + where RcStr: Borrow, Q: Eq + Hash { + match (*self.map.borrow()).get(val) { + Some(v) => Some(*v), + None => None, + } + } + #[cfg(not(stage0))] pub fn find(&self, val: &Q) -> Option - where Q: BorrowFrom + Eq + Hash { + where RcStr: Borrow, Q: Eq + Hash { match (*self.map.borrow()).get(val) { Some(v) => Some(*v), None => None, diff --git a/src/libsyntax/util/small_vector.rs b/src/libsyntax/util/small_vector.rs index b2009a7e848..0a39d380904 100644 --- a/src/libsyntax/util/small_vector.rs +++ b/src/libsyntax/util/small_vector.rs @@ -11,7 +11,7 @@ use self::SmallVectorRepr::*; use self::IntoIterRepr::*; -use std::iter::FromIterator; +use std::iter::{IntoIterator, FromIterator}; use std::mem; use std::slice; use std::vec; @@ -30,7 +30,7 @@ enum SmallVectorRepr { } impl FromIterator for SmallVector { - fn from_iter>(iter: I) -> SmallVector { + fn from_iter>(iter: I) -> SmallVector { let mut v = SmallVector::zero(); v.extend(iter); v @@ -38,7 +38,7 @@ fn from_iter>(iter: I) -> SmallVector { } impl Extend for SmallVector { - fn extend>(&mut self, iter: I) { + fn extend>(&mut self, iter: I) { for val in iter { self.push(val); } diff --git a/src/libterm/lib.rs b/src/libterm/lib.rs index 304f370a199..5418533aff1 100644 --- a/src/libterm/lib.rs +++ b/src/libterm/lib.rs @@ -50,7 +50,6 @@ html_playground_url = "http://play.rust-lang.org/")] #![deny(missing_docs)] -#![feature(core)] #![feature(box_syntax)] #![feature(collections)] #![feature(int_uint)] diff --git a/src/libterm/terminfo/mod.rs b/src/libterm/terminfo/mod.rs index b978d2d8054..be1c623c859 100644 --- a/src/libterm/terminfo/mod.rs +++ b/src/libterm/terminfo/mod.rs @@ -180,7 +180,7 @@ pub fn new(out: T) -> Option+Send+'static>> { } }; - let entry = open(&term[]); + let entry = open(&term[..]); if entry.is_err() { if env::var("MSYSCON").ok().map_or(false, |s| { "mintty.exe" == s diff --git a/src/libterm/terminfo/parm.rs b/src/libterm/terminfo/parm.rs index 82b5ec11d95..0b577f8de74 100644 --- a/src/libterm/terminfo/parm.rs +++ b/src/libterm/terminfo/parm.rs @@ -608,7 +608,7 @@ fn get_res(fmt: &str, cap: &str, params: &[Param], vars: &mut Variables) -> Result, 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) } diff --git a/src/libterm/terminfo/searcher.rs b/src/libterm/terminfo/searcher.rs index fd6e6a843e1..c40a5534efb 100644 --- a/src/libterm/terminfo/searcher.rs +++ b/src/libterm/terminfo/searcher.rs @@ -60,13 +60,13 @@ pub fn get_dbpath_for_term(term: &str) -> Option> { 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); } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 2cb30ad9804..82c1a4b1195 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -37,7 +37,6 @@ #![feature(collections)] #![feature(core)] #![feature(env)] -#![feature(hash)] #![feature(int_uint)] #![feature(old_io)] #![feature(old_path)] @@ -721,7 +720,7 @@ fn should_sort_failures_before_printing_them() { 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!() }; @@ -834,7 +833,7 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec) -> Vec filtered, Some(ref filter) => { filtered.into_iter().filter(|test| { - test.desc.name.as_slice().contains(&filter[]) + test.desc.name.as_slice().contains(&filter[..]) }).collect() } }; diff --git a/src/libtest/stats.rs b/src/libtest/stats.rs index 31ce3e91a77..4e94be59ade 100644 --- a/src/libtest/stats.rs +++ b/src/libtest/stats.rs @@ -12,7 +12,7 @@ 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}; @@ -333,7 +333,7 @@ pub fn winsorize(samples: &mut [T], pct: T) { /// Returns a HashMap with the number of occurrences of every element in the /// sequence that the iterator exposes. pub fn freq_count(iter: T) -> hash_map::HashMap - where T: Iterator, U: Eq + Clone + Hash + where T: Iterator, U: Eq + Clone + Hash { let mut map: hash_map::HashMap = hash_map::HashMap::new(); for elem in iter { diff --git a/src/llvm b/src/llvm index 2089cab13e7..4891e6382e3 160000 --- a/src/llvm +++ b/src/llvm @@ -1 +1 @@ -Subproject commit 2089cab13e7f92b487ba0dc1df9f6c05116b004a +Subproject commit 4891e6382e3e8aa89d530aa18427836428c47157 diff --git a/src/rustbook/build.rs b/src/rustbook/build.rs index 6f5fc5c1969..224f1ef1a8b 100644 --- a/src/rustbook/build.rs +++ b/src/rustbook/build.rs @@ -92,7 +92,7 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> { { 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 diff --git a/src/rustbook/error.rs b/src/rustbook/error.rs index 1c10a270acc..43c882c7d5b 100644 --- a/src/rustbook/error.rs +++ b/src/rustbook/error.rs @@ -52,7 +52,7 @@ fn description<'b>(&'b self) -> &'b str { impl Error for String { fn description<'a>(&'a self) -> &'a str { - &self[] + &self[..] } } @@ -75,7 +75,7 @@ fn description(&self) -> &str { self.desc } fn detail(&self) -> Option<&str> { - self.detail.as_ref().map(|s| &s[]) + self.detail.as_ref().map(|s| &s[..]) } } diff --git a/src/rustbook/test.rs b/src/rustbook/test.rs index d3cb8a7316e..c5d4875423a 100644 --- a/src/rustbook/test.rs +++ b/src/rustbook/test.rs @@ -65,7 +65,7 @@ fn execute(&mut self, term: &mut Term) -> CommandResult<()> { } Err(errors) => { for err in errors { - term.err(&err[]); + term.err(&err[..]); } return Err(box "There was an error." as Box); } diff --git a/src/test/auxiliary/coherence-orphan-lib.rs b/src/test/auxiliary/coherence-orphan-lib.rs index 2e5d18b58f2..cc42b288e66 100644 --- a/src/test/auxiliary/coherence-orphan-lib.rs +++ b/src/test/auxiliary/coherence-orphan-lib.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait TheTrait { +pub trait TheTrait : ::std::marker::PhantomFn { fn the_fn(&self); } diff --git a/src/test/auxiliary/default_type_params_xc.rs b/src/test/auxiliary/default_type_params_xc.rs index d12f716decf..0a65174911e 100644 --- a/src/test/auxiliary/default_type_params_xc.rs +++ b/src/test/auxiliary/default_type_params_xc.rs @@ -12,4 +12,5 @@ pub struct FakeHeap; -pub struct FakeVec; +pub struct FakeVec { pub f: Option<(T,A)> } + diff --git a/src/test/auxiliary/inner_static.rs b/src/test/auxiliary/inner_static.rs index 94acea06618..ca5c6072cb3 100644 --- a/src/test/auxiliary/inner_static.rs +++ b/src/test/auxiliary/inner_static.rs @@ -8,11 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub struct A; -pub struct B; +pub struct A { pub v: T } +pub struct B { pub v: T } pub mod test { - pub struct A; + pub struct A { pub v: T } impl A { pub fn foo(&self) -> int { @@ -52,9 +52,9 @@ pub fn bar(&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(); diff --git a/src/test/auxiliary/issue-14421.rs b/src/test/auxiliary/issue-14421.rs index 7c69cba179c..a48088609f9 100644 --- a/src/test/auxiliary/issue-14421.rs +++ b/src/test/auxiliary/issue-14421.rs @@ -10,6 +10,7 @@ #![crate_type="lib"] #![deny(warnings)] +#![allow(dead_code)] pub use src::aliases::B; pub use src::hidden_core::make; @@ -23,9 +24,9 @@ pub mod aliases { pub mod hidden_core { use super::aliases::B; - pub struct A; + pub struct A { t: T } - pub fn make() -> B { A } + pub fn make() -> B { A { t: 1.0 } } impl A { pub fn foo(&mut self) { println!("called foo"); } diff --git a/src/test/auxiliary/issue-16643.rs b/src/test/auxiliary/issue-16643.rs index c5b3fceaf4a..b590160a0c2 100644 --- a/src/test/auxiliary/issue-16643.rs +++ b/src/test/auxiliary/issue-16643.rs @@ -10,7 +10,7 @@ #![crate_type = "lib"] -pub struct TreeBuilder; +pub struct TreeBuilder { pub h: H } impl TreeBuilder { pub fn process_token(&mut self) { diff --git a/src/test/auxiliary/issue-17662.rs b/src/test/auxiliary/issue-17662.rs index be10ca1dd8f..fb55a077005 100644 --- a/src/test/auxiliary/issue-17662.rs +++ b/src/test/auxiliary/issue-17662.rs @@ -11,7 +11,7 @@ #![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 { diff --git a/src/test/auxiliary/issue-2380.rs b/src/test/auxiliary/issue-2380.rs index 8eb6cd6e263..96f33f97a69 100644 --- a/src/test/auxiliary/issue-2380.rs +++ b/src/test/auxiliary/issue-2380.rs @@ -14,7 +14,10 @@ #![allow(unknown_features)] #![feature(box_syntax)] -pub trait i { } +pub trait i +{ + fn dummy(&self, t: T) -> T { panic!() } +} pub fn f() -> Box+'static> { impl i for () { } diff --git a/src/test/auxiliary/issue-2526.rs b/src/test/auxiliary/issue-2526.rs index e3ce4e8f656..89b3b56121a 100644 --- a/src/test/auxiliary/issue-2526.rs +++ b/src/test/auxiliary/issue-2526.rs @@ -13,8 +13,11 @@ #![feature(unsafe_destructor)] +use std::marker; + struct arc_destruct { - _data: int, + _data: int, + _marker: marker::PhantomData } #[unsafe_destructor] @@ -24,7 +27,8 @@ fn drop(&mut self) {} fn arc_destruct(data: int) -> arc_destruct { arc_destruct { - _data: data + _data: data, + _marker: marker::PhantomData } } diff --git a/src/test/auxiliary/issue_20389.rs b/src/test/auxiliary/issue_20389.rs index 7a378b06df9..4ce7e3079e3 100644 --- a/src/test/auxiliary/issue_20389.rs +++ b/src/test/auxiliary/issue_20389.rs @@ -10,4 +10,5 @@ pub trait T { type C; + fn dummy(&self) { } } diff --git a/src/test/auxiliary/issue_3907.rs b/src/test/auxiliary/issue_3907.rs index 2e254e5431d..545e15fe166 100644 --- a/src/test/auxiliary/issue_3907.rs +++ b/src/test/auxiliary/issue_3907.rs @@ -8,7 +8,9 @@ // 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(); } diff --git a/src/test/auxiliary/issue_8401.rs b/src/test/auxiliary/issue_8401.rs index 0831993119a..9006a5d1775 100644 --- a/src/test/auxiliary/issue_8401.rs +++ b/src/test/auxiliary/issue_8401.rs @@ -12,7 +12,9 @@ use std::mem; -trait A {} +trait A { + fn dummy(&self) { } +} struct B; impl A for B {} diff --git a/src/test/auxiliary/issue_9123.rs b/src/test/auxiliary/issue_9123.rs index 000cc100a12..4f2792aebcd 100644 --- a/src/test/auxiliary/issue_9123.rs +++ b/src/test/auxiliary/issue_9123.rs @@ -15,5 +15,6 @@ fn x() { fn f() { } f(); } + fn dummy(&self) { } } diff --git a/src/test/auxiliary/lang-item-public.rs b/src/test/auxiliary/lang-item-public.rs index 834667968c8..b9cc20b63cc 100644 --- a/src/test/auxiliary/lang-item-public.rs +++ b/src/test/auxiliary/lang-item-public.rs @@ -12,8 +12,12 @@ #![no_std] #![feature(lang_items)] +#[lang="phantom_fn"] +pub trait PhantomFn { } +impl PhantomFn for U { } + #[lang="sized"] -pub trait Sized {} +pub trait Sized : PhantomFn {} #[lang="panic"] fn panic(_: &(&'static str, &'static str, uint)) -> ! { loop {} } @@ -25,6 +29,8 @@ fn panic(_: &(&'static str, &'static str, uint)) -> ! { loop {} } extern fn eh_personality() {} #[lang="copy"] -pub trait Copy {} +pub trait Copy : PhantomFn { + // Empty. +} diff --git a/src/test/auxiliary/lint_group_plugin_test.rs b/src/test/auxiliary/lint_group_plugin_test.rs index 36b3091852b..e9d98889ff8 100644 --- a/src/test/auxiliary/lint_group_plugin_test.rs +++ b/src/test/auxiliary/lint_group_plugin_test.rs @@ -37,9 +37,9 @@ fn get_lints(&self) -> LintArray { 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'"); } } diff --git a/src/test/auxiliary/lint_plugin_test.rs b/src/test/auxiliary/lint_plugin_test.rs index 9020bb7b0fb..ffb234f70c8 100644 --- a/src/test/auxiliary/lint_plugin_test.rs +++ b/src/test/auxiliary/lint_plugin_test.rs @@ -35,7 +35,7 @@ fn get_lints(&self) -> LintArray { 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'"); } } diff --git a/src/test/auxiliary/lint_stability.rs b/src/test/auxiliary/lint_stability.rs index 01b2b748ba9..fb535eb8336 100644 --- a/src/test/auxiliary/lint_stability.rs +++ b/src/test/auxiliary/lint_stability.rs @@ -96,7 +96,7 @@ fn trait_stable_text(&self) {} 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")] diff --git a/src/test/auxiliary/nested_item.rs b/src/test/auxiliary/nested_item.rs index 21784bda27a..fc1bea5a9fd 100644 --- a/src/test/auxiliary/nested_item.rs +++ b/src/test/auxiliary/nested_item.rs @@ -25,7 +25,7 @@ pub fn foo(&self) { } // issue 8134 -pub struct Parser; +pub struct Parser(T); impl> Parser { fn in_doctype(&mut self) { static DOCTYPEPattern: [char; 6] = ['O', 'C', 'T', 'Y', 'P', 'E']; diff --git a/src/test/auxiliary/orphan_check_diagnostics.rs b/src/test/auxiliary/orphan_check_diagnostics.rs index 7647f159401..cf3e9903b5a 100644 --- a/src/test/auxiliary/orphan_check_diagnostics.rs +++ b/src/test/auxiliary/orphan_check_diagnostics.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub trait RemoteTrait {} +pub trait RemoteTrait { fn dummy(&self) { } } diff --git a/src/test/auxiliary/overloaded_autoderef_xc.rs b/src/test/auxiliary/overloaded_autoderef_xc.rs index caa9bbe5736..3c8cba13ae7 100644 --- a/src/test/auxiliary/overloaded_autoderef_xc.rs +++ b/src/test/auxiliary/overloaded_autoderef_xc.rs @@ -11,7 +11,8 @@ use std::ops::Deref; struct DerefWithHelper { - pub helper: H + pub helper: H, + pub value: Option } trait Helper { @@ -34,6 +35,6 @@ fn deref(&self) -> &T { // Test cross-crate autoderef + vtable. pub fn check(x: T, y: T) -> bool { - let d: DerefWithHelper, T> = DerefWithHelper { helper: Some(x) }; + let d: DerefWithHelper, T> = DerefWithHelper { helper: Some(x), value: None }; d.eq(&y) } diff --git a/src/test/auxiliary/plugin_args.rs b/src/test/auxiliary/plugin_args.rs index 907d80b50db..d0ab944813a 100644 --- a/src/test/auxiliary/plugin_args.rs +++ b/src/test/auxiliary/plugin_args.rs @@ -37,7 +37,7 @@ fn expand<'cx>(&self, _: &[ast::TokenTree]) -> Box { let args = self.args.iter().map(|i| pprust::meta_item_to_string(&*i)) .collect::>().connect(", "); - let interned = token::intern_and_get_ident(&args[]); + let interned = token::intern_and_get_ident(&args[..]); MacExpr::new(ecx.expr_str(sp, interned)) } } diff --git a/src/test/auxiliary/private_trait_xc.rs b/src/test/auxiliary/private_trait_xc.rs index 37ee10c8d37..42691579491 100644 --- a/src/test/auxiliary/private_trait_xc.rs +++ b/src/test/auxiliary/private_trait_xc.rs @@ -8,4 +8,4 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo {} +trait Foo : ::std::marker::MarkerTrait {} diff --git a/src/test/auxiliary/svh-a-base.rs b/src/test/auxiliary/svh-a-base.rs index 12833daf604..04f1062c16f 100644 --- a/src/test/auxiliary/svh-a-base.rs +++ b/src/test/auxiliary/svh-a-base.rs @@ -15,12 +15,14 @@ #![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 () {} diff --git a/src/test/auxiliary/svh-a-change-lit.rs b/src/test/auxiliary/svh-a-change-lit.rs index 9e74bf28135..fabd2289e9a 100644 --- a/src/test/auxiliary/svh-a-change-lit.rs +++ b/src/test/auxiliary/svh-a-change-lit.rs @@ -15,12 +15,14 @@ #![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 () {} diff --git a/src/test/auxiliary/svh-a-change-significant-cfg.rs b/src/test/auxiliary/svh-a-change-significant-cfg.rs index c900550041b..3fdb861bd40 100644 --- a/src/test/auxiliary/svh-a-change-significant-cfg.rs +++ b/src/test/auxiliary/svh-a-change-significant-cfg.rs @@ -15,12 +15,14 @@ #![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 () {} diff --git a/src/test/auxiliary/svh-a-change-trait-bound.rs b/src/test/auxiliary/svh-a-change-trait-bound.rs index 04f8eb3cf9b..3116d24673d 100644 --- a/src/test/auxiliary/svh-a-change-trait-bound.rs +++ b/src/test/auxiliary/svh-a-change-trait-bound.rs @@ -15,12 +15,14 @@ #![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 () {} diff --git a/src/test/auxiliary/svh-a-change-type-arg.rs b/src/test/auxiliary/svh-a-change-type-arg.rs index c7e0a18768a..b49a1533628 100644 --- a/src/test/auxiliary/svh-a-change-type-arg.rs +++ b/src/test/auxiliary/svh-a-change-type-arg.rs @@ -15,12 +15,14 @@ #![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 () {} diff --git a/src/test/auxiliary/svh-a-change-type-ret.rs b/src/test/auxiliary/svh-a-change-type-ret.rs index 5100af32318..6562a93135f 100644 --- a/src/test/auxiliary/svh-a-change-type-ret.rs +++ b/src/test/auxiliary/svh-a-change-type-ret.rs @@ -15,12 +15,14 @@ #![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 () {} diff --git a/src/test/auxiliary/svh-a-change-type-static.rs b/src/test/auxiliary/svh-a-change-type-static.rs index 077c33cb90d..c7b392c6ee8 100644 --- a/src/test/auxiliary/svh-a-change-type-static.rs +++ b/src/test/auxiliary/svh-a-change-type-static.rs @@ -15,12 +15,14 @@ #![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 () {} diff --git a/src/test/auxiliary/svh-a-comment.rs b/src/test/auxiliary/svh-a-comment.rs index d481fa5a1fa..450f6102026 100644 --- a/src/test/auxiliary/svh-a-comment.rs +++ b/src/test/auxiliary/svh-a-comment.rs @@ -15,12 +15,14 @@ #![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 () {} diff --git a/src/test/auxiliary/svh-a-doc.rs b/src/test/auxiliary/svh-a-doc.rs index 9e99a355ac1..c000737c854 100644 --- a/src/test/auxiliary/svh-a-doc.rs +++ b/src/test/auxiliary/svh-a-doc.rs @@ -15,12 +15,14 @@ #![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 () {} diff --git a/src/test/auxiliary/svh-a-macro.rs b/src/test/auxiliary/svh-a-macro.rs index b8dd497ac99..1e12659dc4b 100644 --- a/src/test/auxiliary/svh-a-macro.rs +++ b/src/test/auxiliary/svh-a-macro.rs @@ -15,12 +15,14 @@ #![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 () {} diff --git a/src/test/auxiliary/svh-a-no-change.rs b/src/test/auxiliary/svh-a-no-change.rs index 12833daf604..04f1062c16f 100644 --- a/src/test/auxiliary/svh-a-no-change.rs +++ b/src/test/auxiliary/svh-a-no-change.rs @@ -15,12 +15,14 @@ #![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 () {} diff --git a/src/test/auxiliary/svh-a-redundant-cfg.rs b/src/test/auxiliary/svh-a-redundant-cfg.rs index 690ddc670f5..1e82b74f1ef 100644 --- a/src/test/auxiliary/svh-a-redundant-cfg.rs +++ b/src/test/auxiliary/svh-a-redundant-cfg.rs @@ -15,12 +15,14 @@ #![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 () {} diff --git a/src/test/auxiliary/svh-a-whitespace.rs b/src/test/auxiliary/svh-a-whitespace.rs index 216e8e997f2..3c3dac9cdab 100644 --- a/src/test/auxiliary/svh-a-whitespace.rs +++ b/src/test/auxiliary/svh-a-whitespace.rs @@ -15,12 +15,14 @@ #![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 () {} diff --git a/src/test/auxiliary/trait_bounds_on_structs_and_enums_xc.rs b/src/test/auxiliary/trait_bounds_on_structs_and_enums_xc.rs index 1695e474de9..a7c469fccaa 100644 --- a/src/test/auxiliary/trait_bounds_on_structs_and_enums_xc.rs +++ b/src/test/auxiliary/trait_bounds_on_structs_and_enums_xc.rs @@ -8,7 +8,9 @@ // 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 { pub x: T, diff --git a/src/test/auxiliary/trait_impl_conflict.rs b/src/test/auxiliary/trait_impl_conflict.rs index 990bc216049..0982efbdbf4 100644 --- a/src/test/auxiliary/trait_impl_conflict.rs +++ b/src/test/auxiliary/trait_impl_conflict.rs @@ -8,7 +8,7 @@ // 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 { diff --git a/src/test/auxiliary/use_from_trait_xc.rs b/src/test/auxiliary/use_from_trait_xc.rs index 22e0d3168ca..56fb40bc0a4 100644 --- a/src/test/auxiliary/use_from_trait_xc.rs +++ b/src/test/auxiliary/use_from_trait_xc.rs @@ -11,7 +11,7 @@ pub use self::sub::{Bar, Baz}; pub trait Trait { - fn foo(); + fn foo(&self); } struct Foo; diff --git a/src/test/bench/core-set.rs b/src/test/bench/core-set.rs index 1d440c4540c..994c9605fc3 100644 --- a/src/test/bench/core-set.rs +++ b/src/test/bench/core-set.rs @@ -16,9 +16,8 @@ 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; @@ -43,7 +42,7 @@ trait MutableSet { fn contains(&self, k: &T) -> bool; } -impl + Eq> MutableSet for HashSet { +impl MutableSet for HashSet { 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) } @@ -53,7 +52,7 @@ impl MutableSet for BTreeSet { fn remove(&mut self, k: &T) -> bool { self.remove(k) } fn contains(&self, k: &T) -> bool { self.contains(k) } } -impl MutableSet for BitvSet { +impl MutableSet 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) } @@ -222,7 +221,7 @@ fn main() { { 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); } } diff --git a/src/test/bench/shootout-fasta.rs b/src/test/bench/shootout-fasta.rs index fd559608011..2c640c4b092 100644 --- a/src/test/bench/shootout-fasta.rs +++ b/src/test/bench/shootout-fasta.rs @@ -132,7 +132,7 @@ fn run(writer: &mut W) -> std::old_io::IoResult<()> { ('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", diff --git a/src/test/bench/shootout-meteor.rs b/src/test/bench/shootout-meteor.rs index 73dce2910c9..a94fe0ccd95 100644 --- a/src/test/bench/shootout-meteor.rs +++ b/src/test/bench/shootout-meteor.rs @@ -202,7 +202,7 @@ fn filter_masks(masks: &mut Vec>>) { 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(); } @@ -270,7 +270,7 @@ fn handle_sol(raw_sol: &List, data: &mut Data) { // reverse order, i.e. the board rotated by half a turn. data.nb += 2; let sol1 = to_vec(raw_sol); - let sol2: Vec = sol1.iter().rev().map(|x| *x).collect(); + let sol2: Vec = sol1.iter().rev().cloned().collect(); if data.nb == 2 { data.min = sol1.clone(); diff --git a/src/test/compile-fail/ascii-only-character-escape.rs b/src/test/compile-fail/ascii-only-character-escape.rs deleted file mode 100644 index 1ba25a827a5..00000000000 --- a/src/test/compile-fail/ascii-only-character-escape.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -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 -} - diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs index 621f5ec9660..edd1b8255cc 100644 --- a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -16,8 +16,12 @@ #![feature(no_std)] #![no_std] +#[lang="phantom_fn"] +pub trait PhantomFn { } +impl PhantomFn for U { } + #[lang="sized"] -pub trait Sized { +pub trait Sized : PhantomFn { // Empty. } diff --git a/src/test/compile-fail/associated-types-coherence-failure.rs b/src/test/compile-fail/associated-types-coherence-failure.rs index 95a68dd6698..b7a16c68a34 100644 --- a/src/test/compile-fail/associated-types-coherence-failure.rs +++ b/src/test/compile-fail/associated-types-coherence-failure.rs @@ -11,9 +11,10 @@ // 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> { diff --git a/src/test/compile-fail/associated-types-eq-expr-path.rs b/src/test/compile-fail/associated-types-eq-expr-path.rs index 9baa7f1ad5a..c48f9972ebc 100644 --- a/src/test/compile-fail/associated-types-eq-expr-path.rs +++ b/src/test/compile-fail/associated-types-eq-expr-path.rs @@ -10,7 +10,7 @@ // Check that an associated type cannot be bound in an expression path. -trait Foo { +trait Foo : ::std::marker::MarkerTrait { type A; fn bar() -> isize; } diff --git a/src/test/compile-fail/associated-types-issue-17359.rs b/src/test/compile-fail/associated-types-issue-17359.rs index fa09ae793bf..625f4cdb8ef 100644 --- a/src/test/compile-fail/associated-types-issue-17359.rs +++ b/src/test/compile-fail/associated-types-issue-17359.rs @@ -11,7 +11,7 @@ // 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; } diff --git a/src/test/compile-fail/associated-types-multiple-types-one-trait.rs b/src/test/compile-fail/associated-types-multiple-types-one-trait.rs index 9436f825de8..5632f148da6 100644 --- a/src/test/compile-fail/associated-types-multiple-types-one-trait.rs +++ b/src/test/compile-fail/associated-types-multiple-types-one-trait.rs @@ -8,7 +8,7 @@ // 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; } diff --git a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs index a3f2850b294..2b84c38f80b 100644 --- a/src/test/compile-fail/associated-types-no-suitable-supertrait.rs +++ b/src/test/compile-fail/associated-types-no-suitable-supertrait.rs @@ -11,7 +11,7 @@ // Check that we get an error when you use `::Value` in // the trait definition but `Self` does not, in fact, implement `Get`. -trait Get { +trait Get : ::std::marker::MarkerTrait { type Value; } diff --git a/src/test/compile-fail/associated-types-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs index 51a37b517dd..b9a62ff4e41 100644 --- a/src/test/compile-fail/associated-types-path-2.rs +++ b/src/test/compile-fail/associated-types-path-2.rs @@ -12,6 +12,8 @@ pub trait Foo { type A; + + fn dummy(&self) { } } impl Foo for i32 { diff --git a/src/test/compile-fail/associated-types-unconstrained.rs b/src/test/compile-fail/associated-types-unconstrained.rs index aecbf217a5b..8832028f9ab 100644 --- a/src/test/compile-fail/associated-types-unconstrained.rs +++ b/src/test/compile-fail/associated-types-unconstrained.rs @@ -10,7 +10,7 @@ // Check that an associated type cannot be bound in an expression path. -trait Foo { +trait Foo : ::std::marker::MarkerTrait { type A; fn bar() -> isize; } diff --git a/src/test/compile-fail/attr-before-eof.rs b/src/test/compile-fail/attr-before-eof.rs deleted file mode 100644 index e34756229bd..00000000000 --- a/src/test/compile-fail/attr-before-eof.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#[derive(Debug)] //~ERROR expected item after attributes diff --git a/src/test/compile-fail/attr-before-ext.rs b/src/test/compile-fail/attr-before-ext.rs deleted file mode 100644 index 098c5aaec54..00000000000 --- a/src/test/compile-fail/attr-before-ext.rs +++ /dev/null @@ -1,14 +0,0 @@ -// 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 or the MIT license -// , 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"); -} diff --git a/src/test/compile-fail/attr-before-let.rs b/src/test/compile-fail/attr-before-let.rs deleted file mode 100644 index b4a90e35c40..00000000000 --- a/src/test/compile-fail/attr-before-let.rs +++ /dev/null @@ -1,14 +0,0 @@ -// 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 or the MIT license -// , 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; -} diff --git a/src/test/compile-fail/attr-before-stmt.rs b/src/test/compile-fail/attr-before-stmt.rs deleted file mode 100644 index ec837cd6de3..00000000000 --- a/src/test/compile-fail/attr-before-stmt.rs +++ /dev/null @@ -1,19 +0,0 @@ -// 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 or the MIT license -// , 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() { -} diff --git a/src/test/compile-fail/attr-dangling-in-fn.rs b/src/test/compile-fail/attr-dangling-in-fn.rs deleted file mode 100644 index 384622fb168..00000000000 --- a/src/test/compile-fail/attr-dangling-in-fn.rs +++ /dev/null @@ -1,18 +0,0 @@ -// 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 or the MIT license -// , 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() { -} diff --git a/src/test/compile-fail/attr-dangling-in-mod.rs b/src/test/compile-fail/attr-dangling-in-mod.rs deleted file mode 100644 index 59a922ebee1..00000000000 --- a/src/test/compile-fail/attr-dangling-in-mod.rs +++ /dev/null @@ -1,16 +0,0 @@ -// 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 or the MIT license -// , 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"] diff --git a/src/test/compile-fail/attr.rs b/src/test/compile-fail/attr.rs deleted file mode 100644 index 4bd61412731..00000000000 --- a/src/test/compile-fail/attr.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![feature(lang_items)] - -fn main() {} - -#![lang(foo)] //~ ERROR an inner attribute is not permitted in this context -fn foo() {} diff --git a/src/test/compile-fail/attrs-after-extern-mod.rs b/src/test/compile-fail/attrs-after-extern-mod.rs deleted file mode 100644 index df747618696..00000000000 --- a/src/test/compile-fail/attrs-after-extern-mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -// 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 or the MIT license -// , 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() {} diff --git a/src/test/compile-fail/bad-char-literals.rs b/src/test/compile-fail/bad-char-literals.rs deleted file mode 100644 index 2a358ae8307..00000000000 --- a/src/test/compile-fail/bad-char-literals.rs +++ /dev/null @@ -1,29 +0,0 @@ -// 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 or the MIT license -// , 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 - ' '; //~ ERROR: character constant must be escaped: \r - - // note that this is a literal tab character here - ' '; - //~^ ERROR: character constant must be escaped: \t -} diff --git a/src/test/compile-fail/bad-lit-suffixes.rs b/src/test/compile-fail/bad-lit-suffixes.rs deleted file mode 100644 index d10337e768c..00000000000 --- a/src/test/compile-fail/bad-lit-suffixes.rs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -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 -} diff --git a/src/test/compile-fail/bad-mid-path-type-params.rs b/src/test/compile-fail/bad-mid-path-type-params.rs index c91849ca53e..3e02a11c378 100644 --- a/src/test/compile-fail/bad-mid-path-type-params.rs +++ b/src/test/compile-fail/bad-mid-path-type-params.rs @@ -10,13 +10,6 @@ // ignore-tidy-linelength -#![feature(no_std)] -#![no_std] -#![feature(lang_items)] - -#[lang="sized"] -pub trait Sized {} - struct S { contents: T, } diff --git a/src/test/compile-fail/bad-sized.rs b/src/test/compile-fail/bad-sized.rs index 69be6414e4c..1944acbe1f3 100644 --- a/src/test/compile-fail/bad-sized.rs +++ b/src/test/compile-fail/bad-sized.rs @@ -12,7 +12,7 @@ use std::cell::RefCell; -trait Trait {} +trait Trait : ::std::marker::MarkerTrait {} pub fn main() { let x: Vec = Vec::new(); diff --git a/src/test/compile-fail/bad-value-ident-false.rs b/src/test/compile-fail/bad-value-ident-false.rs deleted file mode 100644 index ca10bdd9848..00000000000 --- a/src/test/compile-fail/bad-value-ident-false.rs +++ /dev/null @@ -1,12 +0,0 @@ -// 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 or the MIT license -// , 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() { } diff --git a/src/test/compile-fail/bad-value-ident-true.rs b/src/test/compile-fail/bad-value-ident-true.rs deleted file mode 100644 index 4508d5219a2..00000000000 --- a/src/test/compile-fail/bad-value-ident-true.rs +++ /dev/null @@ -1,12 +0,0 @@ -// 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 or the MIT license -// , 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() { } diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs index 27d97d18c94..d4decb71349 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs @@ -10,6 +10,7 @@ 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 @@ -19,9 +20,9 @@ trait MyTrait { fn get(&self) -> usize; } -trait Even { } +trait Even : MarkerTrait { } -trait Odd { } +trait Odd : MarkerTrait { } impl Even for isize { } diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs index 0f233b78c72..b1ee1762b6e 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs @@ -19,9 +19,9 @@ trait MyTrait { fn get(&self) -> usize; } -trait Even { } +trait Even : ::std::marker::MarkerTrait { } -trait Odd { } +trait Odd : ::std::marker::MarkerTrait { } impl MyTrait for T { //~ ERROR E0119 fn get(&self) -> usize { 0 } diff --git a/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs index c9dfb8201a9..a225f6cf473 100644 --- a/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs +++ b/src/test/compile-fail/coherence-conflicting-negative-trait-impl.rs @@ -10,18 +10,18 @@ #![feature(optin_builtin_traits)] -trait MyTrait {} +trait MyTrait : ::std::marker::MarkerTrait {} -struct TestType; +struct TestType(::std::marker::PhantomData); -unsafe impl Send for TestType {} +unsafe impl Send for TestType {} //~^ ERROR conflicting implementations for trait `core::marker::Send` //~^^ ERROR conflicting implementations for trait `core::marker::Send` impl !Send for TestType {} //~^ ERROR conflicting implementations for trait `core::marker::Send` -unsafe impl Send for TestType {} +unsafe impl Send for TestType {} //~^ ERROR error: conflicting implementations for trait `core::marker::Send` impl !Send for TestType {} diff --git a/src/test/compile-fail/coherence-subtyping.rs b/src/test/compile-fail/coherence-subtyping.rs new file mode 100644 index 00000000000..897cb083f84 --- /dev/null +++ b/src/test/compile-fail/coherence-subtyping.rs @@ -0,0 +1,50 @@ +// 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 or the MIT license +// , 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() { } diff --git a/src/test/compile-fail/cross-borrow-trait.rs b/src/test/compile-fail/cross-borrow-trait.rs index 86b7a8c8918..6bd21101a60 100644 --- a/src/test/compile-fail/cross-borrow-trait.rs +++ b/src/test/compile-fail/cross-borrow-trait.rs @@ -14,7 +14,7 @@ #![feature(box_syntax)] struct Foo; -trait Trait {} +trait Trait { fn foo(&self) {} } impl Trait for Foo {} pub fn main() { diff --git a/src/test/compile-fail/destructure-trait-ref.rs b/src/test/compile-fail/destructure-trait-ref.rs index f2e068cc4ff..4161cce2843 100644 --- a/src/test/compile-fail/destructure-trait-ref.rs +++ b/src/test/compile-fail/destructure-trait-ref.rs @@ -14,7 +14,7 @@ #![feature(box_patterns)] #![feature(box_syntax)] -trait T {} +trait T { fn foo(&self) {} } impl T for isize {} fn main() { diff --git a/src/test/compile-fail/doc-before-attr.rs b/src/test/compile-fail/doc-before-attr.rs deleted file mode 100644 index bb44a6a8abb..00000000000 --- a/src/test/compile-fail/doc-before-attr.rs +++ /dev/null @@ -1,12 +0,0 @@ -// 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 or the MIT license -// , 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 diff --git a/src/test/compile-fail/doc-before-eof.rs b/src/test/compile-fail/doc-before-eof.rs deleted file mode 100644 index e6dd4102462..00000000000 --- a/src/test/compile-fail/doc-before-eof.rs +++ /dev/null @@ -1,11 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -/// hi //~ERROR expected item after doc comment diff --git a/src/test/compile-fail/doc-before-extern-rbrace.rs b/src/test/compile-fail/doc-before-extern-rbrace.rs deleted file mode 100644 index 5afd1b2c6b8..00000000000 --- a/src/test/compile-fail/doc-before-extern-rbrace.rs +++ /dev/null @@ -1,14 +0,0 @@ -// 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 or the MIT license -// , 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 diff --git a/src/test/compile-fail/doc-before-macro.rs b/src/test/compile-fail/doc-before-macro.rs deleted file mode 100644 index 8dc6c546500..00000000000 --- a/src/test/compile-fail/doc-before-macro.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/doc-before-rbrace.rs b/src/test/compile-fail/doc-before-rbrace.rs deleted file mode 100644 index 6d05064277d..00000000000 --- a/src/test/compile-fail/doc-before-rbrace.rs +++ /dev/null @@ -1,14 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/doc-before-semi.rs b/src/test/compile-fail/doc-before-semi.rs deleted file mode 100644 index 8b0300edce0..00000000000 --- a/src/test/compile-fail/doc-before-semi.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs index 2b96c5ebe12..ddc92901771 100644 --- a/src/test/compile-fail/dst-bad-coerce1.rs +++ b/src/test/compile-fail/dst-bad-coerce1.rs @@ -15,7 +15,7 @@ struct Fat { } struct Foo; -trait Bar {} +trait Bar { fn bar(&self) {} } pub fn main() { // With a vec of isize. diff --git a/src/test/compile-fail/dst-bad-coerce2.rs b/src/test/compile-fail/dst-bad-coerce2.rs index 160197368d6..aa687266acb 100644 --- a/src/test/compile-fail/dst-bad-coerce2.rs +++ b/src/test/compile-fail/dst-bad-coerce2.rs @@ -15,7 +15,7 @@ struct Fat { } struct Foo; -trait Bar {} +trait Bar : ::std::marker::MarkerTrait {} impl Bar for Foo {} pub fn main() { diff --git a/src/test/compile-fail/dst-bad-coerce3.rs b/src/test/compile-fail/dst-bad-coerce3.rs index 347a2d2ecbe..7bad3bd69d3 100644 --- a/src/test/compile-fail/dst-bad-coerce3.rs +++ b/src/test/compile-fail/dst-bad-coerce3.rs @@ -15,7 +15,7 @@ struct Fat { } struct Foo; -trait Bar {} +trait Bar { fn bar(&self) {} } impl Bar for Foo {} fn baz<'a>() { diff --git a/src/test/compile-fail/dst-bad-coercions.rs b/src/test/compile-fail/dst-bad-coercions.rs index b30eada162b..8ec1034bc4d 100644 --- a/src/test/compile-fail/dst-bad-coercions.rs +++ b/src/test/compile-fail/dst-bad-coercions.rs @@ -10,8 +10,10 @@ // 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 { diff --git a/src/test/compile-fail/dst-object-from-unsized-type.rs b/src/test/compile-fail/dst-object-from-unsized-type.rs index 87ff4291f50..b4fd45845f7 100644 --- a/src/test/compile-fail/dst-object-from-unsized-type.rs +++ b/src/test/compile-fail/dst-object-from-unsized-type.rs @@ -10,7 +10,7 @@ // Test that we cannot create objects from unsized types. -trait Foo {} +trait Foo { fn foo(&self) {} } impl Foo for str {} fn test1(t: &T) { diff --git a/src/test/compile-fail/exclusive-drop-and-copy.rs b/src/test/compile-fail/exclusive-drop-and-copy.rs index 17453bc677f..f47f14d5879 100644 --- a/src/test/compile-fail/exclusive-drop-and-copy.rs +++ b/src/test/compile-fail/exclusive-drop-and-copy.rs @@ -20,7 +20,7 @@ fn drop(&mut self) {} } #[derive(Copy)] //~ ERROR the trait `Copy` may not be implemented -struct Bar; +struct Bar(::std::marker::PhantomData); #[unsafe_destructor] impl Drop for Bar { diff --git a/src/test/compile-fail/extern-crate-as-no-string-help.rs b/src/test/compile-fail/extern-crate-as-no-string-help.rs deleted file mode 100644 index 5cc52f6f6db..00000000000 --- a/src/test/compile-fail/extern-crate-as-no-string-help.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// 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? diff --git a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs index 02f09749d61..9fea5e609d1 100644 --- a/src/test/compile-fail/generic-impl-less-params-with-defaults.rs +++ b/src/test/compile-fail/generic-impl-less-params-with-defaults.rs @@ -8,10 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo; +use std::marker; + +struct Foo( + marker::PhantomData<(A,B,C)>); impl Foo { - fn new() -> Foo {Foo} + fn new() -> Foo {Foo(marker::PhantomData)} } fn main() { diff --git a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs index d88da2625c1..73c19aa012d 100644 --- a/src/test/compile-fail/generic-impl-more-params-with-defaults.rs +++ b/src/test/compile-fail/generic-impl-more-params-with-defaults.rs @@ -8,12 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker; + struct Heap; -struct Vec; +struct Vec( + marker::PhantomData<(T,A)>); impl Vec { - fn new() -> Vec {Vec} + fn new() -> Vec {Vec(marker::PhantomData)} } fn main() { diff --git a/src/test/compile-fail/generic-lifetime-trait-impl.rs b/src/test/compile-fail/generic-lifetime-trait-impl.rs index fc54002820e..9b9f09f4777 100644 --- a/src/test/compile-fail/generic-lifetime-trait-impl.rs +++ b/src/test/compile-fail/generic-lifetime-trait-impl.rs @@ -16,9 +16,12 @@ // // 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; } diff --git a/src/test/compile-fail/generic-non-trailing-defaults.rs b/src/test/compile-fail/generic-non-trailing-defaults.rs deleted file mode 100644 index 0cfb05b9332..00000000000 --- a/src/test/compile-fail/generic-non-trailing-defaults.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Heap; - -struct Vec; //~ ERROR type parameters with a default must be trailing - -struct Foo, C>; //~ ERROR type parameters with a default must be trailing - -fn main() {} diff --git a/src/test/compile-fail/generic-type-less-params-with-defaults.rs b/src/test/compile-fail/generic-type-less-params-with-defaults.rs index f25d8f99b8d..37737fda474 100644 --- a/src/test/compile-fail/generic-type-less-params-with-defaults.rs +++ b/src/test/compile-fail/generic-type-less-params-with-defaults.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker; + struct Heap; -struct Vec; +struct Vec( + marker::PhantomData<(T,A)>); fn main() { let _: Vec; //~ ERROR wrong number of type arguments: expected at least 1, found 0 diff --git a/src/test/compile-fail/generic-type-more-params-with-defaults.rs b/src/test/compile-fail/generic-type-more-params-with-defaults.rs index 19d303488ac..ad7e4f190c5 100644 --- a/src/test/compile-fail/generic-type-more-params-with-defaults.rs +++ b/src/test/compile-fail/generic-type-more-params-with-defaults.rs @@ -8,9 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker; + struct Heap; -struct Vec; +struct Vec( + marker::PhantomData<(T,A)>); fn main() { let _: Vec; diff --git a/src/test/compile-fail/generic-type-params-name-repr.rs b/src/test/compile-fail/generic-type-params-name-repr.rs index 3e34344d78b..a452cd35f94 100644 --- a/src/test/compile-fail/generic-type-params-name-repr.rs +++ b/src/test/compile-fail/generic-type-params-name-repr.rs @@ -8,13 +8,15 @@ // 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; +struct Foo(marker::PhantomData<(T,U,V)>); -struct Hash; -struct HashMap>; +struct Hash(marker::PhantomData); +struct HashMap>(marker::PhantomData<(K,V,H)>); fn main() { // Ensure that the printed type doesn't include the default type params... diff --git a/src/test/compile-fail/int-literal-too-large-span.rs b/src/test/compile-fail/int-literal-too-large-span.rs deleted file mode 100644 index 8a496c934b9..00000000000 --- a/src/test/compile-fail/int-literal-too-large-span.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// issue #17123 - -fn main() { - 100000000000000000000000000000000 //~ ERROR int literal is too large - - ; // the span shouldn't point to this. -} diff --git a/src/test/compile-fail/issue-10412.rs b/src/test/compile-fail/issue-10412.rs deleted file mode 100644 index 8a99633b4fc..00000000000 --- a/src/test/compile-fail/issue-10412.rs +++ /dev/null @@ -1,32 +0,0 @@ -// 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 or the MIT license -// , 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 ; //~ ERROR no longer a special lifetime - fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR no longer a special lifetime -} - -impl<'self> Serializable for &'self str { //~ ERROR no longer a special lifetime - //~^ ERROR no longer a special lifetime - fn serialize(val : &'self str) -> Vec { //~ 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); -} diff --git a/src/test/compile-fail/issue-11515.rs b/src/test/compile-fail/issue-11515.rs index f0089b0ae5b..4ff574e939d 100644 --- a/src/test/compile-fail/issue-11515.rs +++ b/src/test/compile-fail/issue-11515.rs @@ -10,7 +10,7 @@ #![feature(box_syntax)] -struct Test<'s> { +struct Test { func: Box } diff --git a/src/test/compile-fail/issue-12560-1.rs b/src/test/compile-fail/issue-12560-1.rs deleted file mode 100644 index ea2043e6703..00000000000 --- a/src/test/compile-fail/issue-12560-1.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// 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 }) -} diff --git a/src/test/compile-fail/issue-13853-2.rs b/src/test/compile-fail/issue-13853-2.rs index ea0d880f4a1..dc697e4784f 100644 --- a/src/test/compile-fail/issue-13853-2.rs +++ b/src/test/compile-fail/issue-13853-2.rs @@ -8,7 +8,9 @@ // 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); } diff --git a/src/test/compile-fail/issue-13853-3.rs b/src/test/compile-fail/issue-13853-3.rs index f10c47b594e..7ca158c3e32 100644 --- a/src/test/compile-fail/issue-13853-3.rs +++ b/src/test/compile-fail/issue-13853-3.rs @@ -10,6 +10,8 @@ #![crate_type = "lib"] +use std::marker::PhantomData; + enum NodeContents<'a> { Children(Vec>), } @@ -22,11 +24,12 @@ fn drop( &mut self ) { 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 } } } diff --git a/src/test/compile-fail/issue-13853.rs b/src/test/compile-fail/issue-13853.rs index 251da2c6b3e..cd3f337c4ab 100644 --- a/src/test/compile-fail/issue-13853.rs +++ b/src/test/compile-fail/issue-13853.rs @@ -8,7 +8,9 @@ // 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(); } diff --git a/src/test/compile-fail/issue-14182.rs b/src/test/compile-fail/issue-14182.rs deleted file mode 100644 index 364951a4fea..00000000000 --- a/src/test/compile-fail/issue-14182.rs +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// 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 - }; -} diff --git a/src/test/compile-fail/issue-14285.rs b/src/test/compile-fail/issue-14285.rs index cbf4412a81d..3a5df9e805b 100644 --- a/src/test/compile-fail/issue-14285.rs +++ b/src/test/compile-fail/issue-14285.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo {} +trait Foo { + fn dummy(&self) { } +} struct A; diff --git a/src/test/compile-fail/issue-14853.rs b/src/test/compile-fail/issue-14853.rs index 51deb99a4f2..0b846651acf 100644 --- a/src/test/compile-fail/issue-14853.rs +++ b/src/test/compile-fail/issue-14853.rs @@ -9,8 +9,9 @@ // except according to those terms. use std::fmt::Debug; +use std::marker::MarkerTrait; -trait Str {} +trait Str : MarkerTrait {} trait Something { fn yay(_: Option, thing: &[T]); diff --git a/src/test/compile-fail/issue-16747.rs b/src/test/compile-fail/issue-16747.rs index 814b885e3aa..a213234b89b 100644 --- a/src/test/compile-fail/issue-16747.rs +++ b/src/test/compile-fail/issue-16747.rs @@ -8,7 +8,9 @@ // 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; } diff --git a/src/test/compile-fail/issue-17383.rs b/src/test/compile-fail/issue-17383.rs deleted file mode 100644 index c71e0ecd494..00000000000 --- a/src/test/compile-fail/issue-17383.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum X { - A = - b'a' //~ ERROR discriminator values can only be used with a c-like enum - , - B(isize) -} - -fn main() {} diff --git a/src/test/compile-fail/issue-17431-4.rs b/src/test/compile-fail/issue-17431-4.rs index 1e27f025564..22aaa796ad0 100644 --- a/src/test/compile-fail/issue-17431-4.rs +++ b/src/test/compile-fail/issue-17431-4.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo { foo: Option>> } +use std::marker; + +struct Foo { foo: Option>>, marker: marker::PhantomData } //~^ ERROR illegal recursive struct type; wrap the inner value in a box to make it representable impl Foo { fn bar(&self) {} } diff --git a/src/test/compile-fail/issue-17431-5.rs b/src/test/compile-fail/issue-17431-5.rs index d22d79ecaa5..cc9cc2e3c03 100644 --- a/src/test/compile-fail/issue-17431-5.rs +++ b/src/test/compile-fail/issue-17431-5.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker; + struct Foo { foo: Bar } -struct Bar { x: Bar } +struct Bar { x: Bar , marker: marker::PhantomData } //~^ ERROR illegal recursive struct type; wrap the inner value in a box to make it representable impl Foo { fn foo(&self) {} } diff --git a/src/test/compile-fail/issue-17551.rs b/src/test/compile-fail/issue-17551.rs index e037ba92b4a..5781cb74117 100644 --- a/src/test/compile-fail/issue-17551.rs +++ b/src/test/compile-fail/issue-17551.rs @@ -10,9 +10,11 @@ #![feature(unboxed_closures)] -struct B; +use std::marker; + +struct B(marker::PhantomData); 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; } diff --git a/src/test/compile-fail/issue-17718-const-mut.rs b/src/test/compile-fail/issue-17718-const-mut.rs deleted file mode 100644 index 5177ebbc188..00000000000 --- a/src/test/compile-fail/issue-17718-const-mut.rs +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -const -mut //~ ERROR: const globals cannot be mutable -//~^ HELP did you mean to declare a static? -FOO: usize = 3; - -fn main() { -} - diff --git a/src/test/compile-fail/issue-17904-2.rs b/src/test/compile-fail/issue-17904-2.rs new file mode 100644 index 00000000000..a33ec23a16a --- /dev/null +++ b/src/test/compile-fail/issue-17904-2.rs @@ -0,0 +1,16 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// 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 where T: Copy; //~ ERROR parameter `T` is never used + +fn main() {} diff --git a/src/test/compile-fail/issue-1802-2.rs b/src/test/compile-fail/issue-1802-2.rs deleted file mode 100644 index f6da2fc82c3..00000000000 --- a/src/test/compile-fail/issue-1802-2.rs +++ /dev/null @@ -1,14 +0,0 @@ -// 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 or the MIT license -// , 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); -} diff --git a/src/test/compile-fail/issue-18107.rs b/src/test/compile-fail/issue-18107.rs index 91689988f58..d5fb22bdebd 100644 --- a/src/test/compile-fail/issue-18107.rs +++ b/src/test/compile-fail/issue-18107.rs @@ -8,9 +8,9 @@ // 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 diff --git a/src/test/compile-fail/issue-18611.rs b/src/test/compile-fail/issue-18611.rs index a662e9ca98e..e81a576fa63 100644 --- a/src/test/compile-fail/issue-18611.rs +++ b/src/test/compile-fail/issue-18611.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker::MarkerTrait; + fn add_state(op: ::State) { //~^ ERROR the trait `HasState` is not implemented for the type `isize` } -trait HasState { +trait HasState : MarkerTrait { type State; } diff --git a/src/test/compile-fail/issue-18783.rs b/src/test/compile-fail/issue-18783.rs index 5ddf06add9d..13908bda9d8 100644 --- a/src/test/compile-fail/issue-18783.rs +++ b/src/test/compile-fail/issue-18783.rs @@ -26,6 +26,7 @@ fn ufcs() { 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> { diff --git a/src/test/compile-fail/issue-18819.rs b/src/test/compile-fail/issue-18819.rs index 3a9de741043..951d78410b8 100644 --- a/src/test/compile-fail/issue-18819.rs +++ b/src/test/compile-fail/issue-18819.rs @@ -8,7 +8,9 @@ // 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; } diff --git a/src/test/compile-fail/issue-19660.rs b/src/test/compile-fail/issue-19660.rs index 14601e67a77..77aba7335bd 100644 --- a/src/test/compile-fail/issue-19660.rs +++ b/src/test/compile-fail/issue-19660.rs @@ -13,8 +13,12 @@ #![feature(lang_items, start, no_std)] #![no_std] +#[lang="phantom_fn"] +trait PhantomFn { } +impl PhantomFn for U { } + #[lang = "sized"] -trait Sized {} +trait Sized : PhantomFn {} #[start] fn main(_: int, _: *const *const u8) -> int { diff --git a/src/test/compile-fail/issue-2063.rs b/src/test/compile-fail/issue-2063.rs index 00607f85034..aed395d17ea 100644 --- a/src/test/compile-fail/issue-2063.rs +++ b/src/test/compile-fail/issue-2063.rs @@ -12,10 +12,11 @@ // cause compiler to loop. Note that no instances // of such a type could ever be constructed. +use std::marker::MarkerTrait; struct t(Box); //~ ERROR this type cannot be instantiated -trait to_str_2 { +trait to_str_2 : MarkerTrait { fn my_to_string() -> String; } diff --git a/src/test/compile-fail/issue-20831-debruijn.rs b/src/test/compile-fail/issue-20831-debruijn.rs index aaf45f27398..5b623ac377b 100644 --- a/src/test/compile-fail/issue-20831-debruijn.rs +++ b/src/test/compile-fail/issue-20831-debruijn.rs @@ -13,10 +13,11 @@ // 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; } diff --git a/src/test/compile-fail/issue-21160.rs b/src/test/compile-fail/issue-21160.rs index 45b7fbbd0b4..557bf518a3c 100644 --- a/src/test/compile-fail/issue-21160.rs +++ b/src/test/compile-fail/issue-21160.rs @@ -16,6 +16,6 @@ fn hash(&self, _: T) {} #[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() {} diff --git a/src/test/compile-fail/issue-2611-4.rs b/src/test/compile-fail/issue-2611-4.rs index 31796e5e20c..24cc0099b89 100644 --- a/src/test/compile-fail/issue-2611-4.rs +++ b/src/test/compile-fail/issue-2611-4.rs @@ -12,7 +12,7 @@ // than the trait method it's implementing trait A { - fn b(x: C) -> C; + fn b(&self, x: C) -> C; } struct E { @@ -20,7 +20,7 @@ struct E { } impl A for E { - fn b(_x: F) -> F { panic!() } + fn b(&self, _x: F) -> F { panic!() } //~^ ERROR `F : core::marker::Sync` appears on the impl method } diff --git a/src/test/compile-fail/issue-3008-3.rs b/src/test/compile-fail/issue-3008-3.rs index a338a01690d..af6cee1f107 100644 --- a/src/test/compile-fail/issue-3008-3.rs +++ b/src/test/compile-fail/issue-3008-3.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker; + enum E1 { V1(E2), } -enum E2 { V2(E2), } +enum E2 { V2(E2, marker::PhantomData), } //~^ ERROR illegal recursive enum type; wrap the inner value in a box to make it representable impl E1 { fn foo(&self) {} } diff --git a/src/test/compile-fail/issue-4972.rs b/src/test/compile-fail/issue-4972.rs index 9a398796d2a..f384dba7c9e 100644 --- a/src/test/compile-fail/issue-4972.rs +++ b/src/test/compile-fail/issue-4972.rs @@ -11,7 +11,9 @@ #![feature(box_patterns)] #![feature(box_syntax)] -trait MyTrait { } +trait MyTrait { + fn dummy(&self) {} +} pub enum TraitWrapper { A(Box), diff --git a/src/test/compile-fail/issue-5035-2.rs b/src/test/compile-fail/issue-5035-2.rs index 9e324cdd61e..d316b44794a 100644 --- a/src/test/compile-fail/issue-5035-2.rs +++ b/src/test/compile-fail/issue-5035-2.rs @@ -8,7 +8,9 @@ // 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 diff --git a/src/test/compile-fail/issue-5543.rs b/src/test/compile-fail/issue-5543.rs index cf98f1572e5..4d721ad7666 100644 --- a/src/test/compile-fail/issue-5543.rs +++ b/src/test/compile-fail/issue-5543.rs @@ -10,7 +10,7 @@ #![feature(box_syntax)] -trait Foo {} +trait Foo { fn foo(&self) {} } impl Foo for u8 {} fn main() { diff --git a/src/test/compile-fail/issue-5544-a.rs b/src/test/compile-fail/issue-5544-a.rs deleted file mode 100644 index 95a4f36d171..00000000000 --- a/src/test/compile-fail/issue-5544-a.rs +++ /dev/null @@ -1,14 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/issue-5544-b.rs b/src/test/compile-fail/issue-5544-b.rs deleted file mode 100644 index afff5984b46..00000000000 --- a/src/test/compile-fail/issue-5544-b.rs +++ /dev/null @@ -1,14 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/issue-5883.rs b/src/test/compile-fail/issue-5883.rs index 9ff957b6e6d..b0db9906195 100644 --- a/src/test/compile-fail/issue-5883.rs +++ b/src/test/compile-fail/issue-5883.rs @@ -8,7 +8,9 @@ // 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 @@ -20,6 +22,6 @@ fn new_struct(r: A+'static) Struct { r: r } } -trait Curve {} +trait Curve : MarkerTrait {} enum E {X(Curve+'static)} fn main() {} diff --git a/src/test/compile-fail/issue-6458.rs b/src/test/compile-fail/issue-6458.rs index efa3100360b..0bf9a3c2d48 100644 --- a/src/test/compile-fail/issue-6458.rs +++ b/src/test/compile-fail/issue-6458.rs @@ -8,13 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub struct TypeWithState; +use std::marker; + +pub struct TypeWithState(marker::PhantomData); pub struct MyState; pub fn foo(_: TypeWithState) {} pub fn bar() { - foo(TypeWithState); //~ ERROR type annotations required + foo(TypeWithState(marker::PhantomData)); //~ ERROR type annotations required } fn main() { diff --git a/src/test/compile-fail/issue-7575.rs b/src/test/compile-fail/issue-7575.rs index 9e6000c050a..b6643f43952 100644 --- a/src/test/compile-fail/issue-7575.rs +++ b/src/test/compile-fail/issue-7575.rs @@ -10,12 +10,14 @@ // 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 } @@ -24,7 +26,7 @@ trait OtherTrait { // 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 } @@ -52,7 +54,7 @@ fn fff(i: isize) -> isize { //~ NOTE candidate } } -trait ManyImplTrait { +trait ManyImplTrait : MarkerTrait { fn is_str() -> bool { //~ NOTE candidate false } diff --git a/src/test/compile-fail/issue-8537.rs b/src/test/compile-fail/issue-8537.rs deleted file mode 100644 index 52cf420a9ff..00000000000 --- a/src/test/compile-fail/issue-8537.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -pub extern - "invalid-ab_isize" //~ ERROR illegal ABI -fn foo() {} - -fn main() {} diff --git a/src/test/compile-fail/issue-8727.rs b/src/test/compile-fail/issue-8727.rs index d1a86d334cb..72da6dcaa6c 100644 --- a/src/test/compile-fail/issue-8727.rs +++ b/src/test/compile-fail/issue-8727.rs @@ -13,16 +13,12 @@ // Verify the compiler fails with an error on infinite function // recursions. -struct Data(Box>); - -fn generic( _ : Vec<(Data,T)> ) { - let rec : Vec<(Data,(bool,T))> = Vec::new(); - generic( rec ); +fn generic() { + generic::>(); } fn main () { // Use generic at least once to trigger instantiation. - let input : Vec<(Data,())> = Vec::new(); - generic(input); + generic::(); } diff --git a/src/test/compile-fail/keyword-as-as-identifier.rs b/src/test/compile-fail/keyword-as-as-identifier.rs deleted file mode 100644 index f307b12f66e..00000000000 --- a/src/test/compile-fail/keyword-as-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-break-as-identifier.rs b/src/test/compile-fail/keyword-break-as-identifier.rs deleted file mode 100644 index 1e2725eb2fe..00000000000 --- a/src/test/compile-fail/keyword-break-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-else-as-identifier.rs b/src/test/compile-fail/keyword-else-as-identifier.rs deleted file mode 100644 index 101fd938dcb..00000000000 --- a/src/test/compile-fail/keyword-else-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-enum-as-identifier.rs b/src/test/compile-fail/keyword-enum-as-identifier.rs deleted file mode 100644 index ed504cc7b7f..00000000000 --- a/src/test/compile-fail/keyword-enum-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-extern-as-identifier.rs b/src/test/compile-fail/keyword-extern-as-identifier.rs deleted file mode 100644 index 3260506b3e1..00000000000 --- a/src/test/compile-fail/keyword-extern-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-fn-as-identifier.rs b/src/test/compile-fail/keyword-fn-as-identifier.rs deleted file mode 100644 index 8c98da229c8..00000000000 --- a/src/test/compile-fail/keyword-fn-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-for-as-identifier.rs b/src/test/compile-fail/keyword-for-as-identifier.rs deleted file mode 100644 index 196a3390676..00000000000 --- a/src/test/compile-fail/keyword-for-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-if-as-identifier.rs b/src/test/compile-fail/keyword-if-as-identifier.rs deleted file mode 100644 index 05f82ec790c..00000000000 --- a/src/test/compile-fail/keyword-if-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-impl-as-identifier.rs b/src/test/compile-fail/keyword-impl-as-identifier.rs deleted file mode 100644 index 1dd21800345..00000000000 --- a/src/test/compile-fail/keyword-impl-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-let-as-identifier.rs b/src/test/compile-fail/keyword-let-as-identifier.rs deleted file mode 100644 index 0069a26a40b..00000000000 --- a/src/test/compile-fail/keyword-let-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-loop-as-identifier.rs b/src/test/compile-fail/keyword-loop-as-identifier.rs deleted file mode 100644 index 6e469e8c0b4..00000000000 --- a/src/test/compile-fail/keyword-loop-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-match-as-identifier.rs b/src/test/compile-fail/keyword-match-as-identifier.rs deleted file mode 100644 index 9155ebc71fa..00000000000 --- a/src/test/compile-fail/keyword-match-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-mod-as-identifier.rs b/src/test/compile-fail/keyword-mod-as-identifier.rs deleted file mode 100644 index 02f57e937dd..00000000000 --- a/src/test/compile-fail/keyword-mod-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-pub-as-identifier.rs b/src/test/compile-fail/keyword-pub-as-identifier.rs deleted file mode 100644 index aa679741c1c..00000000000 --- a/src/test/compile-fail/keyword-pub-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-return-as-identifier.rs b/src/test/compile-fail/keyword-return-as-identifier.rs deleted file mode 100644 index c5676445917..00000000000 --- a/src/test/compile-fail/keyword-return-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-self-as-identifier.rs b/src/test/compile-fail/keyword-self-as-identifier.rs deleted file mode 100644 index 8bb52142287..00000000000 --- a/src/test/compile-fail/keyword-self-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-static-as-identifier.rs b/src/test/compile-fail/keyword-static-as-identifier.rs deleted file mode 100644 index 7268c4f387e..00000000000 --- a/src/test/compile-fail/keyword-static-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-struct-as-identifier.rs b/src/test/compile-fail/keyword-struct-as-identifier.rs deleted file mode 100644 index bd42eac0ecb..00000000000 --- a/src/test/compile-fail/keyword-struct-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-super-as-identifier.rs b/src/test/compile-fail/keyword-super-as-identifier.rs deleted file mode 100644 index 0378c326a89..00000000000 --- a/src/test/compile-fail/keyword-super-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-super.rs b/src/test/compile-fail/keyword-super.rs deleted file mode 100644 index 0c94f76f1f6..00000000000 --- a/src/test/compile-fail/keyword-super.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - let super: isize; //~ ERROR expected identifier, found keyword `super` -} diff --git a/src/test/compile-fail/keyword-trait-as-identifier.rs b/src/test/compile-fail/keyword-trait-as-identifier.rs deleted file mode 100644 index 95c0d174c33..00000000000 --- a/src/test/compile-fail/keyword-trait-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-type-as-identifier.rs b/src/test/compile-fail/keyword-type-as-identifier.rs deleted file mode 100644 index 0aaa2a63c7c..00000000000 --- a/src/test/compile-fail/keyword-type-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-unsafe-as-identifier.rs b/src/test/compile-fail/keyword-unsafe-as-identifier.rs deleted file mode 100644 index 1b631eb877d..00000000000 --- a/src/test/compile-fail/keyword-unsafe-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-use-as-identifier.rs b/src/test/compile-fail/keyword-use-as-identifier.rs deleted file mode 100644 index e82afd54442..00000000000 --- a/src/test/compile-fail/keyword-use-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword-while-as-identifier.rs b/src/test/compile-fail/keyword-while-as-identifier.rs deleted file mode 100644 index 95cea65c610..00000000000 --- a/src/test/compile-fail/keyword-while-as-identifier.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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 -} diff --git a/src/test/compile-fail/keyword.rs b/src/test/compile-fail/keyword.rs deleted file mode 100644 index 64eac47e69b..00000000000 --- a/src/test/compile-fail/keyword.rs +++ /dev/null @@ -1,13 +0,0 @@ -// 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 or the MIT license -// , 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` -} diff --git a/src/test/compile-fail/keywords-followed-by-double-colon.rs b/src/test/compile-fail/keywords-followed-by-double-colon.rs deleted file mode 100644 index f69b041597e..00000000000 --- a/src/test/compile-fail/keywords-followed-by-double-colon.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn main() { - struct::foo(); //~ ERROR expected identifier - mut::baz(); //~ ERROR expected identifier -} - diff --git a/src/test/compile-fail/kindck-copy.rs b/src/test/compile-fail/kindck-copy.rs index 56f83d93008..74e372e41eb 100644 --- a/src/test/compile-fail/kindck-copy.rs +++ b/src/test/compile-fail/kindck-copy.rs @@ -10,12 +10,12 @@ // Test which of the builtin types are considered POD. - +use std::marker::MarkerTrait; use std::rc::Rc; fn assert_copy() { } -trait Dummy { } +trait Dummy : MarkerTrait { } #[derive(Copy)] struct MyStruct { diff --git a/src/test/compile-fail/kindck-impl-type-params-2.rs b/src/test/compile-fail/kindck-impl-type-params-2.rs index 2731be7308a..b575144f637 100644 --- a/src/test/compile-fail/kindck-impl-type-params-2.rs +++ b/src/test/compile-fail/kindck-impl-type-params-2.rs @@ -10,7 +10,9 @@ #![feature(box_syntax)] -trait Foo { +use std::marker::MarkerTrait; + +trait Foo : MarkerTrait { } impl Foo for T { diff --git a/src/test/compile-fail/kindck-impl-type-params.rs b/src/test/compile-fail/kindck-impl-type-params.rs index d5276efa8be..dffc8fa2abd 100644 --- a/src/test/compile-fail/kindck-impl-type-params.rs +++ b/src/test/compile-fail/kindck-impl-type-params.rs @@ -13,40 +13,44 @@ #![feature(box_syntax)] -struct S; +use std::marker; -trait Gettable {} +struct S(marker::PhantomData); + +trait Gettable { + fn get(&self) -> T { panic!() } +} impl Gettable for S {} fn f(val: T) { - let t: S = S; + let t: S = S(marker::PhantomData); let a = &t as &Gettable; //~^ ERROR the trait `core::marker::Send` is not implemented //~^^ ERROR the trait `core::marker::Copy` is not implemented } fn g(val: T) { - let t: S = S; + let t: S = S(marker::PhantomData); let a: &Gettable = &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> = box S; + let t: Box> = box S(marker::PhantomData); let a = t as Box>; //~^ ERROR the trait `core::marker::Copy` is not implemented } fn foo3<'a>() { - let t: Box> = box S; + let t: Box> = box S(marker::PhantomData); let a: Box> = t; //~^ ERROR the trait `core::marker::Copy` is not implemented } diff --git a/src/test/compile-fail/kindck-inherited-copy-bound.rs b/src/test/compile-fail/kindck-inherited-copy-bound.rs index e146cac21a3..0072b1228af 100644 --- a/src/test/compile-fail/kindck-inherited-copy-bound.rs +++ b/src/test/compile-fail/kindck-inherited-copy-bound.rs @@ -15,6 +15,7 @@ use std::any::Any; trait Foo : Copy { + fn foo(&self) {} } impl Foo for T { diff --git a/src/test/compile-fail/kindck-send-object.rs b/src/test/compile-fail/kindck-send-object.rs index 570f7ad7fe3..0c68401bb2b 100644 --- a/src/test/compile-fail/kindck-send-object.rs +++ b/src/test/compile-fail/kindck-send-object.rs @@ -12,8 +12,10 @@ // 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() { } -trait Dummy { } +trait Dummy : MarkerTrait { } trait Message : Send { } // careful with object types, who knows what they close over... diff --git a/src/test/compile-fail/kindck-send-object1.rs b/src/test/compile-fail/kindck-send-object1.rs index 48d5215b708..f86eac8b16b 100644 --- a/src/test/compile-fail/kindck-send-object1.rs +++ b/src/test/compile-fail/kindck-send-object1.rs @@ -12,8 +12,10 @@ // 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() { } -trait Dummy { } +trait Dummy : MarkerTrait { } // careful with object types, who knows what they close over... fn test51<'a>() { diff --git a/src/test/compile-fail/kindck-send-object2.rs b/src/test/compile-fail/kindck-send-object2.rs index d3d166e2a69..08516e67318 100644 --- a/src/test/compile-fail/kindck-send-object2.rs +++ b/src/test/compile-fail/kindck-send-object2.rs @@ -10,8 +10,10 @@ // Continue kindck-send-object1.rs. +use std::marker::MarkerTrait; + fn assert_send() { } -trait Dummy { } +trait Dummy : MarkerTrait { } fn test50() { assert_send::<&'static Dummy>(); //~ ERROR the trait `core::marker::Sync` is not implemented diff --git a/src/test/compile-fail/lex-bad-numeric-literals.rs b/src/test/compile-fail/lex-bad-numeric-literals.rs deleted file mode 100644 index 9a490be6a01..00000000000 --- a/src/test/compile-fail/lex-bad-numeric-literals.rs +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -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 -} diff --git a/src/test/compile-fail/lex-bare-cr-string-literal-doc-comment.rs b/src/test/compile-fail/lex-bare-cr-string-literal-doc-comment.rs deleted file mode 100644 index c1e5121d6dd..00000000000 --- a/src/test/compile-fail/lex-bare-cr-string-literal-doc-comment.rs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// ignore-tidy-cr - -/// doc comment with bare CR: ' ' -pub fn foo() {} -//~^^ ERROR: bare CR not allowed in doc-comment - -/** block doc comment with bare CR: ' ' */ -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 bar"; //~ ERROR: bare CR not allowed in string - - // the following string literal has a bare CR in it - let _s = r"bar foo"; //~ ERROR: bare CR not allowed in raw string - - // the following string literal has a bare CR in it - let _s = "foo\ bar"; //~ ERROR: unknown character escape: \r -} diff --git a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-3.rs b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-3.rs index 04c5b223cb8..66d8927ee51 100644 --- a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-3.rs +++ b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param-3.rs @@ -10,7 +10,9 @@ // 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) diff --git a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs index c60e321219b..a85776a938b 100644 --- a/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs +++ b/src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs @@ -10,7 +10,9 @@ // 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 diff --git a/src/test/compile-fail/lifetime-no-keyword.rs b/src/test/compile-fail/lifetime-no-keyword.rs deleted file mode 100644 index 8ffbcd90df8..00000000000 --- a/src/test/compile-fail/lifetime-no-keyword.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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() { } diff --git a/src/test/compile-fail/lifetime-obsoleted-self.rs b/src/test/compile-fail/lifetime-obsoleted-self.rs deleted file mode 100644 index 766922f2f88..00000000000 --- a/src/test/compile-fail/lifetime-obsoleted-self.rs +++ /dev/null @@ -1,13 +0,0 @@ -// 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 or the MIT license -// , 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() { } diff --git a/src/test/compile-fail/lint-missing-doc.rs b/src/test/compile-fail/lint-missing-doc.rs index 3b96fd64fa2..73a58741bbb 100644 --- a/src/test/compile-fail/lint-missing-doc.rs +++ b/src/test/compile-fail/lint-missing-doc.rs @@ -47,20 +47,26 @@ fn foo3() {} /// 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() {} diff --git a/src/test/compile-fail/lint-non-camel-case-types.rs b/src/test/compile-fail/lint-non-camel-case-types.rs index 70d6b240985..9f58d5791cb 100644 --- a/src/test/compile-fail/lint-non-camel-case-types.rs +++ b/src/test/compile-fail/lint-non-camel-case-types.rs @@ -30,6 +30,7 @@ enum Foo5 { } trait foo6 { //~ ERROR trait `foo6` should have a camel case name such as `Foo6` + fn dummy(&self) { } } fn f(_: ty) {} //~ ERROR type parameter `ty` should have a camel case name such as `Ty` diff --git a/src/test/compile-fail/lint-stability.rs b/src/test/compile-fail/lint-stability.rs index f9cdfa4f7d6..88f2cbdea6d 100644 --- a/src/test/compile-fail/lint-stability.rs +++ b/src/test/compile-fail/lint-stability.rs @@ -341,7 +341,9 @@ fn fn_in_body() {} #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] - pub trait DeprecatedTrait {} + pub trait DeprecatedTrait { + fn dummy(&self) { } + } struct S; diff --git a/src/test/compile-fail/lint-visible-private-types.rs b/src/test/compile-fail/lint-visible-private-types.rs index 8cf375f80fb..918b4ee209c 100644 --- a/src/test/compile-fail/lint-visible-private-types.rs +++ b/src/test/compile-fail/lint-visible-private-types.rs @@ -12,8 +12,10 @@ #![allow(dead_code)] #![crate_type="lib"] -struct Private; -pub struct Public; +use std::marker; + +struct Private(marker::PhantomData); +pub struct Public(marker::PhantomData); impl Private> { pub fn a(&self) -> Private { panic!() } @@ -103,7 +105,7 @@ impl PrivTrait for (Private,) { fn bar(&self) -> Private { panic!() } } -pub trait ParamTrait { +pub trait ParamTrait : marker::MarkerTrait { fn foo() -> T; } diff --git a/src/test/compile-fail/liveness-use-after-send.rs b/src/test/compile-fail/liveness-use-after-send.rs index a49339ecd7f..03d8d62e0b4 100644 --- a/src/test/compile-fail/liveness-use-after-send.rs +++ b/src/test/compile-fail/liveness-use-after-send.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker; + fn send(ch: _chan, data: T) { println!("{:?}", ch); println!("{:?}", data); @@ -15,7 +17,7 @@ fn send(ch: _chan, data: T) { } #[derive(Debug)] -struct _chan(isize); +struct _chan(isize, marker::PhantomData); // Tests that "log(debug, message);" is flagged as using // message after the send deinitializes it diff --git a/src/test/compile-fail/macros-no-semicolon-items.rs b/src/test/compile-fail/macros-no-semicolon-items.rs deleted file mode 100644 index 314292085df..00000000000 --- a/src/test/compile-fail/macros-no-semicolon-items.rs +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -macro_rules! foo() //~ ERROR semicolon - -fn main() { -} diff --git a/src/test/compile-fail/map-types.rs b/src/test/compile-fail/map-types.rs index ba2205f5868..6e8719eeace 100644 --- a/src/test/compile-fail/map-types.rs +++ b/src/test/compile-fail/map-types.rs @@ -14,7 +14,10 @@ use std::collections::HashMap; -trait Map {} +trait Map +{ + fn get(&self, k: K) -> V { panic!() } +} impl Map for HashMap {} diff --git a/src/test/compile-fail/method-ambig-one-trait-coerce.rs b/src/test/compile-fail/method-ambig-one-trait-coerce.rs deleted file mode 100644 index cb5da4bb547..00000000000 --- a/src/test/compile-fail/method-ambig-one-trait-coerce.rs +++ /dev/null @@ -1,50 +0,0 @@ -// 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 or the MIT license -// , 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 { - fn foo(self) -> isize {1} -} - -impl foo for Box { - fn foo(self) -> isize {2} -} - -fn test1(x: Box) { - // 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) { - // Not ambiguous because it is a precise match: - x.foo(); -} - -fn test3(x: Box) { - // Not ambiguous because it is a precise match: - x.foo(); -} - -fn main() { } diff --git a/src/test/compile-fail/mod_file_disambig.rs b/src/test/compile-fail/mod_file_disambig.rs new file mode 100644 index 00000000000..48bd00a3ee0 --- /dev/null +++ b/src/test/compile-fail/mod_file_disambig.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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); +} diff --git a/src/test/compile-fail/mod_file_not_owning.rs b/src/test/compile-fail/mod_file_not_owning.rs new file mode 100644 index 00000000000..adbcedd91f2 --- /dev/null +++ b/src/test/compile-fail/mod_file_not_owning.rs @@ -0,0 +1,15 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// error-pattern: cannot declare a new module at this location + +mod mod_file_not_owning_aux1; + +fn main() {} diff --git a/src/test/compile-fail/no-binary-float-literal.rs b/src/test/compile-fail/no-binary-float-literal.rs deleted file mode 100644 index 2e207f90d36..00000000000 --- a/src/test/compile-fail/no-binary-float-literal.rs +++ /dev/null @@ -1,17 +0,0 @@ -// 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 or the MIT license -// , 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; -} diff --git a/src/test/compile-fail/no-hex-float-literal.rs b/src/test/compile-fail/no-hex-float-literal.rs deleted file mode 100644 index 4abb6093b24..00000000000 --- a/src/test/compile-fail/no-hex-float-literal.rs +++ /dev/null @@ -1,17 +0,0 @@ -// 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 or the MIT license -// , 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; -} diff --git a/src/test/compile-fail/no-unsafe-self.rs b/src/test/compile-fail/no-unsafe-self.rs deleted file mode 100644 index 0bf73bbdfe3..00000000000 --- a/src/test/compile-fail/no-unsafe-self.rs +++ /dev/null @@ -1,22 +0,0 @@ -// 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 or the MIT license -// , 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() { } diff --git a/src/test/compile-fail/non-str-meta.rs b/src/test/compile-fail/non-str-meta.rs deleted file mode 100644 index 752f72f0b08..00000000000 --- a/src/test/compile-fail/non-str-meta.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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() { } diff --git a/src/test/compile-fail/object-does-not-impl-trait.rs b/src/test/compile-fail/object-does-not-impl-trait.rs index cfaf149a49c..607ab13d122 100644 --- a/src/test/compile-fail/object-does-not-impl-trait.rs +++ b/src/test/compile-fail/object-does-not-impl-trait.rs @@ -11,8 +11,9 @@ // Test that an object type `Box` is not considered to implement the // trait `Foo`. Issue #5087. +use std::marker::MarkerTrait; -trait Foo {} +trait Foo : MarkerTrait {} fn take_foo(f: F) {} fn take_object(f: Box) { take_foo(f); } //~^ ERROR the trait `Foo` is not implemented diff --git a/src/test/compile-fail/object-lifetime-default-mybox.rs b/src/test/compile-fail/object-lifetime-default-mybox.rs index c107c8d131d..23ddea4499a 100644 --- a/src/test/compile-fail/object-lifetime-default-mybox.rs +++ b/src/test/compile-fail/object-lifetime-default-mybox.rs @@ -37,7 +37,6 @@ fn load1<'a,'b>(a: &'a MyBox, a //~^ ERROR cannot infer //~| ERROR mismatched types - //~| ERROR mismatched types } fn main() { diff --git a/src/test/compile-fail/object-safety-issue-22040.rs b/src/test/compile-fail/object-safety-issue-22040.rs new file mode 100644 index 00000000000..edf32131b68 --- /dev/null +++ b/src/test/compile-fail/object-safety-issue-22040.rs @@ -0,0 +1,50 @@ +// 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 or the MIT license +// , 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>, +} + +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 = Box::new(SExpr::new()); //~ ERROR trait `Expr` is not object-safe + let b: Box = Box::new(SExpr::new()); //~ ERROR trait `Expr` is not object-safe + + assert_eq!(a , b); +} diff --git a/src/test/compile-fail/object-safety-no-static.rs b/src/test/compile-fail/object-safety-no-static.rs index 6a010d49692..aae829ec7b5 100644 --- a/src/test/compile-fail/object-safety-no-static.rs +++ b/src/test/compile-fail/object-safety-no-static.rs @@ -11,7 +11,7 @@ // Check that we correctly prevent users from making trait objects // from traits with static methods. -trait Foo { +trait Foo : ::std::marker::MarkerTrait { fn foo(); } diff --git a/src/test/compile-fail/object-safety-phantom-fn.rs b/src/test/compile-fail/object-safety-phantom-fn.rs new file mode 100644 index 00000000000..1c95ee43d27 --- /dev/null +++ b/src/test/compile-fail/object-safety-phantom-fn.rs @@ -0,0 +1,34 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// 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 { +} + +trait Bar : PhantomFn<(Self, T)> { +} + +fn make_bar>(t: &T) -> &Bar { + t +} + +fn make_baz(t: &T) -> &Baz { + t +} + +#[rustc_error] +fn main() { //~ ERROR compilation successful +} diff --git a/src/test/compile-fail/object-safety-supertrait-mentions-Self.rs b/src/test/compile-fail/object-safety-supertrait-mentions-Self.rs new file mode 100644 index 00000000000..d3f9dc73020 --- /dev/null +++ b/src/test/compile-fail/object-safety-supertrait-mentions-Self.rs @@ -0,0 +1,32 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// 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 { + fn bar(&self, x: &T); +} + +trait Baz : Bar { +} + +fn make_bar>(t: &T) -> &Bar { + t +} + +fn make_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() { +} diff --git a/src/test/compile-fail/obsolete-for-sized.rs b/src/test/compile-fail/obsolete-for-sized.rs deleted file mode 100644 index 1b86d08a50d..00000000000 --- a/src/test/compile-fail/obsolete-for-sized.rs +++ /dev/null @@ -1,17 +0,0 @@ -// 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 or the MIT license -// , 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() { } diff --git a/src/test/compile-fail/obsolete-proc.rs b/src/test/compile-fail/obsolete-proc.rs deleted file mode 100644 index 5208cdb6ad2..00000000000 --- a/src/test/compile-fail/obsolete-proc.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// 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() { } diff --git a/src/test/compile-fail/on-unimplemented-bad-anno.rs b/src/test/compile-fail/on-unimplemented-bad-anno.rs index dda534cc489..7538b1c85e5 100644 --- a/src/test/compile-fail/on-unimplemented-bad-anno.rs +++ b/src/test/compile-fail/on-unimplemented-bad-anno.rs @@ -13,8 +13,12 @@ #![allow(unused)] +use std::marker; + #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"] -trait Foo{} +trait Foo + : 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 { @@ -23,15 +27,21 @@ trait MyFromIterator { } #[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 {} +trait BadAnnotation2 + : 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 {} +trait BadAnnotation3 + : marker::PhantomFn<(Self,A,B)> +{} pub fn main() { } diff --git a/src/test/compile-fail/on-unimplemented.rs b/src/test/compile-fail/on-unimplemented.rs index 7b406afcf1f..2447d086422 100644 --- a/src/test/compile-fail/on-unimplemented.rs +++ b/src/test/compile-fail/on-unimplemented.rs @@ -11,8 +11,12 @@ #![feature(on_unimplemented)] +use std::marker; + #[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"] -trait Foo{} +trait Foo + : marker::PhantomFn<(Self,Bar,Baz,Quux)> +{} fn foobar>() -> T { diff --git a/src/test/compile-fail/orphan-check-diagnostics.rs b/src/test/compile-fail/orphan-check-diagnostics.rs index ff5c101b917..8201565c331 100644 --- a/src/test/compile-fail/orphan-check-diagnostics.rs +++ b/src/test/compile-fail/orphan-check-diagnostics.rs @@ -15,7 +15,7 @@ use orphan_check_diagnostics::RemoteTrait; -trait LocalTrait {} +trait LocalTrait { fn dummy(&self) { } } impl RemoteTrait for T where T: LocalTrait {} //~^ ERROR type parameter `T` must be used as the type parameter for some local type diff --git a/src/test/compile-fail/priv-in-bad-locations.rs b/src/test/compile-fail/priv-in-bad-locations.rs index db649ed0cc6..43d112b8aa0 100644 --- a/src/test/compile-fail/priv-in-bad-locations.rs +++ b/src/test/compile-fail/priv-in-bad-locations.rs @@ -14,7 +14,7 @@ } trait A { - fn foo() {} + fn foo(&self) {} } struct B; @@ -22,7 +22,7 @@ fn foo() {} 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() {} diff --git a/src/test/compile-fail/privacy-ns2.rs b/src/test/compile-fail/privacy-ns2.rs index 7fe0574ab7d..67bb566ea68 100644 --- a/src/test/compile-fail/privacy-ns2.rs +++ b/src/test/compile-fail/privacy-ns2.rs @@ -17,7 +17,9 @@ // public type, private value pub mod foo1 { - pub trait Bar { + use std::marker::MarkerTrait; + + pub trait Bar : MarkerTrait { } pub struct Baz; @@ -39,7 +41,7 @@ fn test_list1() { // private type, public value pub mod foo2 { - trait Bar { + trait Bar : ::std::marker::MarkerTrait { } pub struct Baz; @@ -60,7 +62,7 @@ fn test_list2() { // neither public pub mod foo3 { - trait Bar { + trait Bar : ::std::marker::MarkerTrait { } pub struct Baz; diff --git a/src/test/compile-fail/privacy1.rs b/src/test/compile-fail/privacy1.rs index 7ebbcc2809a..1ae79adbad7 100644 --- a/src/test/compile-fail/privacy1.rs +++ b/src/test/compile-fail/privacy1.rs @@ -11,11 +11,15 @@ #![feature(lang_items, start, no_std)] #![no_std] // makes debugging this test *a lot* easier (during resolve) +#[lang="phantom_fn"] +pub trait PhantomFn { } +impl PhantomFn for U { } + #[lang="sized"] -pub trait Sized {} +pub trait Sized : PhantomFn {} #[lang="copy"] -pub trait Copy {} +pub trait Copy : PhantomFn {} mod bar { // shouldn't bring in too much diff --git a/src/test/compile-fail/privacy4.rs b/src/test/compile-fail/privacy4.rs index bcb46663aa8..adce93af079 100644 --- a/src/test/compile-fail/privacy4.rs +++ b/src/test/compile-fail/privacy4.rs @@ -11,8 +11,12 @@ #![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 { } +impl PhantomFn for U { } + +#[lang = "sized"] pub trait Sized : PhantomFn {} +#[lang="copy"] pub trait Copy : PhantomFn {} // Test to make sure that private items imported through globs remain private // when they're used. diff --git a/src/test/compile-fail/qquote-1.rs b/src/test/compile-fail/qquote-1.rs deleted file mode 100644 index deae9a83866..00000000000 --- a/src/test/compile-fail/qquote-1.rs +++ /dev/null @@ -1,68 +0,0 @@ -// 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 or the MIT license -// , 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(expr: T, f: |pprust::ps, T|, expect: str) { - panic!(); -} diff --git a/src/test/compile-fail/qquote-2.rs b/src/test/compile-fail/qquote-2.rs deleted file mode 100644 index 978287a681e..00000000000 --- a/src/test/compile-fail/qquote-2.rs +++ /dev/null @@ -1,61 +0,0 @@ -// 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 or the MIT license -// , 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(expr: T, f: |pprust::ps, T|, expect: str) { - panic!(); -} diff --git a/src/test/compile-fail/region-object-lifetime-in-coercion.rs b/src/test/compile-fail/region-object-lifetime-in-coercion.rs index 20cc624ab19..2da414befd8 100644 --- a/src/test/compile-fail/region-object-lifetime-in-coercion.rs +++ b/src/test/compile-fail/region-object-lifetime-in-coercion.rs @@ -13,7 +13,7 @@ #![feature(box_syntax)] -trait Foo {} +trait Foo : ::std::marker::MarkerTrait {} impl<'a> Foo for &'a [u8] {} fn a(v: &[u8]) -> Box { diff --git a/src/test/compile-fail/regions-assoc-type-in-supertrait-outlives-container.rs b/src/test/compile-fail/regions-assoc-type-in-supertrait-outlives-container.rs index fa26c9c54c8..6aa0cc003ce 100644 --- a/src/test/compile-fail/regions-assoc-type-in-supertrait-outlives-container.rs +++ b/src/test/compile-fail/regions-assoc-type-in-supertrait-outlives-container.rs @@ -15,15 +15,12 @@ #![allow(dead_code)] -use std::mem::transmute; -use std::ops::Deref; +use std::marker::PhantomFn; /////////////////////////////////////////////////////////////////////////// -pub trait TheTrait { +pub trait TheTrait: PhantomFn { type TheAssocType; - - fn dummy(&self) { } } pub trait TheSubTrait : TheTrait { diff --git a/src/test/compile-fail/regions-assoc-type-outlives-container-hrtb.rs b/src/test/compile-fail/regions-assoc-type-outlives-container-hrtb.rs index 7d955065ff4..9736910d7b5 100644 --- a/src/test/compile-fail/regions-assoc-type-outlives-container-hrtb.rs +++ b/src/test/compile-fail/regions-assoc-type-outlives-container-hrtb.rs @@ -14,12 +14,12 @@ #![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> { diff --git a/src/test/compile-fail/regions-assoc-type-outlives-container-wc.rs b/src/test/compile-fail/regions-assoc-type-outlives-container-wc.rs index 6ee65fbdf91..da7546ce21c 100644 --- a/src/test/compile-fail/regions-assoc-type-outlives-container-wc.rs +++ b/src/test/compile-fail/regions-assoc-type-outlives-container-wc.rs @@ -15,15 +15,12 @@ #![allow(dead_code)] -use std::mem::transmute; -use std::ops::Deref; +use std::marker::PhantomFn; /////////////////////////////////////////////////////////////////////////// -pub trait TheTrait { +pub trait TheTrait: PhantomFn { type TheAssocType; - - fn dummy(&self) { } } pub struct TheType<'b> { diff --git a/src/test/compile-fail/regions-assoc-type-outlives-container.rs b/src/test/compile-fail/regions-assoc-type-outlives-container.rs index 49a0726fa3b..e1e72e6f56e 100644 --- a/src/test/compile-fail/regions-assoc-type-outlives-container.rs +++ b/src/test/compile-fail/regions-assoc-type-outlives-container.rs @@ -13,16 +13,14 @@ // 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 { type TheAssocType; - - fn dummy(&self) { } } pub struct TheType<'b> { diff --git a/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs b/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs index f833361e3b5..f921eccef1f 100644 --- a/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs +++ b/src/test/compile-fail/regions-assoc-type-region-bound-in-trait-not-met.rs @@ -11,7 +11,10 @@ // 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. diff --git a/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs b/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs index 0871d8b01f6..1cf83b8ac58 100644 --- a/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs +++ b/src/test/compile-fail/regions-assoc-type-static-bound-in-trait-not-met.rs @@ -11,7 +11,10 @@ // 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 diff --git a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs b/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs index a3c38dff6b0..278ccd3c119 100644 --- a/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs +++ b/src/test/compile-fail/regions-bound-missing-bound-in-impl.rs @@ -21,10 +21,9 @@ pub trait Foo<'a, 't> { 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 @@ -51,7 +50,7 @@ fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) { 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() { } diff --git a/src/test/compile-fail/regions-bounded-method-type-parameters-trait-bound.rs b/src/test/compile-fail/regions-bounded-method-type-parameters-trait-bound.rs index 74c2c6e584b..f13d8a60894 100644 --- a/src/test/compile-fail/regions-bounded-method-type-parameters-trait-bound.rs +++ b/src/test/compile-fail/regions-bounded-method-type-parameters-trait-bound.rs @@ -8,16 +8,10 @@ // 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 } diff --git a/src/test/compile-fail/regions-close-associated-type-into-object.rs b/src/test/compile-fail/regions-close-associated-type-into-object.rs index 8a03f36972d..979c1e997d0 100644 --- a/src/test/compile-fail/regions-close-associated-type-into-object.rs +++ b/src/test/compile-fail/regions-close-associated-type-into-object.rs @@ -10,7 +10,9 @@ #![feature(box_syntax)] -trait X {} +use std::marker::MarkerTrait; + +trait X : MarkerTrait {} trait Iter { type Item: X; diff --git a/src/test/compile-fail/regions-close-object-into-object-1.rs b/src/test/compile-fail/regions-close-object-into-object-1.rs index 7a0e3cf4611..7bbce7dad53 100644 --- a/src/test/compile-fail/regions-close-object-into-object-1.rs +++ b/src/test/compile-fail/regions-close-object-into-object-1.rs @@ -11,13 +11,16 @@ #![feature(box_syntax)] #![allow(warnings)] -trait A {} +use std::marker::PhantomFn; + +trait A : PhantomFn<(Self,T)> { } struct B<'a, T>(&'a (A+'a)); -trait X {} +trait X : ::std::marker::MarkerTrait {} + impl<'a, T> X for B<'a, T> {} -fn f<'a, T, U>(v: Box+'static>) -> Box { +fn f<'a, T:'static, U>(v: Box+'static>) -> Box { box B(&*v) as Box //~ ERROR `*v` does not live long enough } diff --git a/src/test/compile-fail/regions-close-object-into-object-2.rs b/src/test/compile-fail/regions-close-object-into-object-2.rs index 7861fb95fef..6de49020a6f 100644 --- a/src/test/compile-fail/regions-close-object-into-object-2.rs +++ b/src/test/compile-fail/regions-close-object-into-object-2.rs @@ -10,10 +10,12 @@ #![feature(box_syntax)] -trait A {} +use std::marker::PhantomFn; + +trait A : PhantomFn<(Self,T)> { } struct B<'a, T>(&'a (A+'a)); -trait X {} +trait X : PhantomFn {} impl<'a, T> X for B<'a, T> {} fn g<'a, T: 'static>(v: Box+'a>) -> Box { diff --git a/src/test/compile-fail/regions-close-object-into-object-3.rs b/src/test/compile-fail/regions-close-object-into-object-3.rs index 31354de2a27..e22d0c7d0a4 100644 --- a/src/test/compile-fail/regions-close-object-into-object-3.rs +++ b/src/test/compile-fail/regions-close-object-into-object-3.rs @@ -11,10 +11,12 @@ #![feature(box_syntax)] #![allow(warnings)] -trait A {} +use std::marker::PhantomFn; + +trait A : PhantomFn<(Self,T)> {} struct B<'a, T>(&'a (A+'a)); -trait X {} +trait X : PhantomFn {} impl<'a, T> X for B<'a, T> {} fn h<'a, T, U>(v: Box+'static>) -> Box { diff --git a/src/test/compile-fail/regions-close-object-into-object-4.rs b/src/test/compile-fail/regions-close-object-into-object-4.rs index c60975f97e1..147a575d38c 100644 --- a/src/test/compile-fail/regions-close-object-into-object-4.rs +++ b/src/test/compile-fail/regions-close-object-into-object-4.rs @@ -10,10 +10,12 @@ #![feature(box_syntax)] -trait A {} +use std::marker::PhantomFn; + +trait A : PhantomFn<(Self,T)> {} struct B<'a, T>(&'a (A+'a)); -trait X {} +trait X : PhantomFn {} impl<'a, T> X for B<'a, T> {} fn i<'a, T, U>(v: Box+'a>) -> Box { diff --git a/src/test/compile-fail/regions-close-object-into-object-5.rs b/src/test/compile-fail/regions-close-object-into-object-5.rs new file mode 100644 index 00000000000..bdc52eca2cb --- /dev/null +++ b/src/test/compile-fail/regions-close-object-into-object-5.rs @@ -0,0 +1,30 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_syntax)] +#![allow(warnings)] + +trait A +{ + fn get(&self) -> T { panic!() } +} + +struct B<'a, T>(&'a (A+'a)); + +trait X { fn foo(&self) {} } + +impl<'a, T> X for B<'a, T> {} + +fn f<'a, T, U>(v: Box+'static>) -> Box { + box B(&*v) as Box //~ ERROR the parameter type `T` may not live long enough +} + +fn main() {} + diff --git a/src/test/compile-fail/regions-close-over-borrowed-ref-in-obj.rs b/src/test/compile-fail/regions-close-over-borrowed-ref-in-obj.rs index 25b8137d29c..2341d2397c9 100644 --- a/src/test/compile-fail/regions-close-over-borrowed-ref-in-obj.rs +++ b/src/test/compile-fail/regions-close-over-borrowed-ref-in-obj.rs @@ -10,7 +10,9 @@ #![feature(box_syntax)] -trait Foo { } +use std::marker::MarkerTrait; + +trait Foo : MarkerTrait { } impl<'a> Foo for &'a isize { } diff --git a/src/test/compile-fail/regions-close-param-into-object.rs b/src/test/compile-fail/regions-close-param-into-object.rs index 74b36958c92..655ac6f66c9 100644 --- a/src/test/compile-fail/regions-close-param-into-object.rs +++ b/src/test/compile-fail/regions-close-param-into-object.rs @@ -10,7 +10,7 @@ #![feature(box_syntax)] -trait X {} +trait X { fn foo(&self) {} } fn p1(v: T) -> Box where T : X diff --git a/src/test/compile-fail/regions-fn-bound.rs b/src/test/compile-fail/regions-fn-bound.rs deleted file mode 100644 index c2b52b79f6c..00000000000 --- a/src/test/compile-fail/regions-fn-bound.rs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn of() -> |T| { panic!(); } -fn subtype(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::(of::()) 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() {} diff --git a/src/test/compile-fail/regions-infer-contravariance-due-to-decl.rs b/src/test/compile-fail/regions-infer-contravariance-due-to-decl.rs index 6c5e90a54de..b7ef19d1e3b 100644 --- a/src/test/compile-fail/regions-infer-contravariance-due-to-decl.rs +++ b/src/test/compile-fail/regions-infer-contravariance-due-to-decl.rs @@ -20,7 +20,7 @@ // 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>, diff --git a/src/test/compile-fail/regions-infer-covariance-due-to-decl.rs b/src/test/compile-fail/regions-infer-covariance-due-to-decl.rs index d8e31fa1374..0d3d9dacbd6 100644 --- a/src/test/compile-fail/regions-infer-covariance-due-to-decl.rs +++ b/src/test/compile-fail/regions-infer-covariance-due-to-decl.rs @@ -17,7 +17,7 @@ use std::marker; struct Covariant<'a> { - marker: marker::CovariantLifetime<'a> + marker: marker::PhantomData } fn use_<'short,'long>(c: Covariant<'long>, diff --git a/src/test/compile-fail/regions-infer-invariance-due-to-decl.rs b/src/test/compile-fail/regions-infer-invariance-due-to-decl.rs index e88c96de9e4..8c191fbd5bb 100644 --- a/src/test/compile-fail/regions-infer-invariance-due-to-decl.rs +++ b/src/test/compile-fail/regions-infer-invariance-due-to-decl.rs @@ -11,7 +11,7 @@ use std::marker; struct invariant<'a> { - marker: marker::InvariantLifetime<'a> + marker: marker::PhantomData<*mut &'a()> } fn to_same_lifetime<'r>(b_isize: invariant<'r>) { diff --git a/src/test/compile-fail/require-parens-for-chained-comparison.rs b/src/test/compile-fail/require-parens-for-chained-comparison.rs deleted file mode 100644 index f2705f58331..00000000000 --- a/src/test/compile-fail/require-parens-for-chained-comparison.rs +++ /dev/null @@ -1,23 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn f() {} - -fn main() { - false == false == false; - //~^ ERROR: chained comparison operators require parentheses - - false == 0 < 2; - //~^ ERROR: chained comparison operators require parentheses - - f(); - //~^ ERROR: chained comparison operators require parentheses - //~^^ HELP: use `::<...>` instead of `<...>` -} diff --git a/src/test/compile-fail/required-lang-item.rs b/src/test/compile-fail/required-lang-item.rs index 7d252604883..1b749faf1b8 100644 --- a/src/test/compile-fail/required-lang-item.rs +++ b/src/test/compile-fail/required-lang-item.rs @@ -11,7 +11,11 @@ #![feature(lang_items, no_std)] #![no_std] -#[lang="sized"] pub trait Sized {} +#[lang="phantom_fn"] +pub trait PhantomFn { } +impl PhantomFn for U { } + +#[lang="sized"] pub trait Sized : PhantomFn {} // error-pattern:requires `start` lang_item diff --git a/src/test/compile-fail/shadowed-type-parameter.rs b/src/test/compile-fail/shadowed-type-parameter.rs index 1a3d7821159..1f72db1e894 100644 --- a/src/test/compile-fail/shadowed-type-parameter.rs +++ b/src/test/compile-fail/shadowed-type-parameter.rs @@ -12,19 +12,21 @@ #![feature(box_syntax)] -struct Foo; +struct Foo(T); impl Foo { fn shadow_in_method(&self) {} //~^ ERROR type parameter `T` shadows another type parameter fn not_shadow_in_item(&self) { - struct Bar; // not a shadow, separate item + struct Bar(T,U); // not a shadow, separate item fn foo() {} // same } } trait Bar { + fn dummy(&self) -> T; + fn shadow_in_required(&self); //~^ ERROR type parameter `T` shadows another type parameter diff --git a/src/test/compile-fail/slice-1.rs b/src/test/compile-fail/slice-1.rs index 23ad5b09950..3b992e3bcc3 100644 --- a/src/test/compile-fail/slice-1.rs +++ b/src/test/compile-fail/slice-1.rs @@ -9,14 +9,12 @@ // 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 } diff --git a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs index 1203d622348..3c1c3796a24 100644 --- a/src/test/compile-fail/slightly-nice-generic-literal-messages.rs +++ b/src/test/compile-fail/slightly-nice-generic-literal-messages.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo(T); +use std::marker; + +struct Foo(T, marker::PhantomData); fn main() { - match Foo(1.1) { + match Foo(1.1, marker::PhantomData) { 1 => {} //~^ ERROR mismatched types //~| expected `Foo<_, _>` diff --git a/src/test/compile-fail/staticness-mismatch.rs b/src/test/compile-fail/staticness-mismatch.rs index bf4e46cace3..2dfc9b79ee2 100644 --- a/src/test/compile-fail/staticness-mismatch.rs +++ b/src/test/compile-fail/staticness-mismatch.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - trait foo { + fn dummy(&self) { } fn bar(); } diff --git a/src/test/compile-fail/struct-no-fields-2.rs b/src/test/compile-fail/struct-no-fields-2.rs deleted file mode 100644 index 4f973f81b16..00000000000 --- a/src/test/compile-fail/struct-no-fields-2.rs +++ /dev/null @@ -1,18 +0,0 @@ -// 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 or the MIT license -// , 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() {} diff --git a/src/test/compile-fail/struct-no-fields-3.rs b/src/test/compile-fail/struct-no-fields-3.rs deleted file mode 100644 index e594683feed..00000000000 --- a/src/test/compile-fail/struct-no-fields-3.rs +++ /dev/null @@ -1,18 +0,0 @@ -// 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 or the MIT license -// , 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() {} diff --git a/src/test/compile-fail/struct-no-fields-4.rs b/src/test/compile-fail/struct-no-fields-4.rs deleted file mode 100644 index 60a0a85d0ab..00000000000 --- a/src/test/compile-fail/struct-no-fields-4.rs +++ /dev/null @@ -1,18 +0,0 @@ -// 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 or the MIT license -// , 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() {} diff --git a/src/test/compile-fail/struct-no-fields-5.rs b/src/test/compile-fail/struct-no-fields-5.rs deleted file mode 100644 index 940fa9c7f27..00000000000 --- a/src/test/compile-fail/struct-no-fields-5.rs +++ /dev/null @@ -1,18 +0,0 @@ -// 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 or the MIT license -// , 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() {} diff --git a/src/test/compile-fail/struct-variant-no-fields.rs b/src/test/compile-fail/struct-variant-no-fields.rs deleted file mode 100644 index 41dbbeefc0a..00000000000 --- a/src/test/compile-fail/struct-variant-no-fields.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum Foo { - Bar {} //~ ERROR unit-like struct variant should be written without braces, as `Bar,` -} diff --git a/src/test/compile-fail/struct-variant-no-pub.rs b/src/test/compile-fail/struct-variant-no-pub.rs deleted file mode 100644 index e62b39ad5aa..00000000000 --- a/src/test/compile-fail/struct-variant-no-pub.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -enum Foo { - Bar { - pub a: isize //~ ERROR: `pub` is not allowed here - } -} - -fn main() {} diff --git a/src/test/compile-fail/syntax-trait-polarity.rs b/src/test/compile-fail/syntax-trait-polarity.rs deleted file mode 100644 index 1ab79f5c80e..00000000000 --- a/src/test/compile-fail/syntax-trait-polarity.rs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -#![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; - -impl !TestType2 {} -//~^ ERROR inherent implementation can't be negated - -unsafe impl !Send for TestType2 {} -impl !TestTrait for TestType2 {} - -fn main() {} diff --git a/src/test/compile-fail/tag-variant-disr-non-nullary.rs b/src/test/compile-fail/tag-variant-disr-non-nullary.rs deleted file mode 100644 index 207bbe9a446..00000000000 --- a/src/test/compile-fail/tag-variant-disr-non-nullary.rs +++ /dev/null @@ -1,20 +0,0 @@ -// 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 or the MIT license -// , 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), -} diff --git a/src/test/compile-fail/trailing-carriage-return-in-string.rs b/src/test/compile-fail/trailing-carriage-return-in-string.rs deleted file mode 100644 index 81098333261..00000000000 --- a/src/test/compile-fail/trailing-carriage-return-in-string.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// ignore-tidy-cr -// Issue #11669 - -fn main() { - // \r\n - let ok = "This is \ - a test"; - // \r only - let bad = "This is \ a test"; - //~^ ERROR unknown character escape: \r - //~^^ HELP this is an isolated carriage return - -} diff --git a/src/test/compile-fail/trailing-plus-in-bounds.rs b/src/test/compile-fail/trailing-plus-in-bounds.rs deleted file mode 100644 index e8f9ed4d2cf..00000000000 --- a/src/test/compile-fail/trailing-plus-in-bounds.rs +++ /dev/null @@ -1,18 +0,0 @@ -// 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 or the MIT license -// , 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 = box 3 as Box; - //~^ ERROR at least one type parameter bound must be specified - //~^^ ERROR at least one type parameter bound must be specified -} - diff --git a/src/test/compile-fail/trait-as-struct-constructor.rs b/src/test/compile-fail/trait-as-struct-constructor.rs index a1fcab002e1..fff14414094 100644 --- a/src/test/compile-fail/trait-as-struct-constructor.rs +++ b/src/test/compile-fail/trait-as-struct-constructor.rs @@ -8,7 +8,7 @@ // 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 }; diff --git a/src/test/compile-fail/trait-bounds-cant-coerce.rs b/src/test/compile-fail/trait-bounds-cant-coerce.rs index 79174552ae0..3129dceffbb 100644 --- a/src/test/compile-fail/trait-bounds-cant-coerce.rs +++ b/src/test/compile-fail/trait-bounds-cant-coerce.rs @@ -10,6 +10,7 @@ trait Foo { + fn dummy(&self) { } } fn a(_x: Box) { diff --git a/src/test/compile-fail/trait-bounds-impl-comparison-1.rs b/src/test/compile-fail/trait-bounds-impl-comparison-1.rs index 477bd4f5be9..34e06cc9365 100644 --- a/src/test/compile-fail/trait-bounds-impl-comparison-1.rs +++ b/src/test/compile-fail/trait-bounds-impl-comparison-1.rs @@ -11,7 +11,10 @@ // Make sure rustc checks the type parameter bounds in implementations of traits, // see #2687 -trait A {} +use std::marker; + +trait A : marker::PhantomFn { +} trait B: A {} @@ -62,15 +65,16 @@ fn test_error8_fn(&self) {} //~^ ERROR the requirement `T : C` appears on the impl } - -trait Getter { } +trait Getter { + fn get(&self) -> T { loop { } } +} trait Trait { - fn method>(); + fn method>(&self); } impl Trait for usize { - fn method>() {} + fn method>(&self) {} //~^ G : Getter` appears on the impl method but not on the corresponding trait method } diff --git a/src/test/compile-fail/trait-bounds-impl-comparison-2.rs b/src/test/compile-fail/trait-bounds-impl-comparison-2.rs index 8ad19116e7b..284c4fac953 100644 --- a/src/test/compile-fail/trait-bounds-impl-comparison-2.rs +++ b/src/test/compile-fail/trait-bounds-impl-comparison-2.rs @@ -14,7 +14,9 @@ trait Iterator { fn next(&mut self) -> Option; } -trait IteratorUtil { +trait IteratorUtil + : ::std::marker::PhantomFn<(),A> +{ fn zip>(self, other: U) -> ZipIterator; } diff --git a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs index 434d803d718..448b186f6a5 100644 --- a/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs +++ b/src/test/compile-fail/trait-bounds-not-on-bare-trait.rs @@ -9,6 +9,7 @@ // except according to those terms. trait Foo { + fn dummy(&self) { } } // This should emit the less confusing error, not the more confusing one. diff --git a/src/test/compile-fail/trait-bounds-not-on-impl.rs b/src/test/compile-fail/trait-bounds-not-on-impl.rs deleted file mode 100644 index a034352c4a6..00000000000 --- a/src/test/compile-fail/trait-bounds-not-on-impl.rs +++ /dev/null @@ -1,19 +0,0 @@ -// 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 or the MIT license -// , 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() { } diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums-locals.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums-locals.rs index 118dfeb37c2..df44e847c50 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums-locals.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums-locals.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Trait {} +trait Trait { + fn dummy(&self) { } +} struct Foo { x: T, diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums-static.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums-static.rs index d5369817e9a..18871d0d386 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums-static.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums-static.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Trait {} +trait Trait { + fn dummy(&self) { } +} struct Foo { x: T, diff --git a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs index 490ee0e8ad6..8dfdb2f205d 100644 --- a/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs +++ b/src/test/compile-fail/trait-bounds-on-structs-and-enums.rs @@ -8,7 +8,9 @@ // 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 { x: T, @@ -51,15 +53,15 @@ enum MoreBadness { EvenMoreBadness(Bar), } -trait PolyTrait { - fn whatever() {} +trait PolyTrait +{ + fn whatever(&self, t: T) {} } struct Struct; impl PolyTrait> for Struct { //~^ ERROR not implemented - fn whatever() {} } fn main() { diff --git a/src/test/compile-fail/trait-bounds-sugar.rs b/src/test/compile-fail/trait-bounds-sugar.rs index 3d264e681a3..e4058a0943a 100644 --- a/src/test/compile-fail/trait-bounds-sugar.rs +++ b/src/test/compile-fail/trait-bounds-sugar.rs @@ -10,8 +10,9 @@ // Tests for "default" bounds inferred for traits with no bounds list. +use std::marker::MarkerTrait; -trait Foo {} +trait Foo : MarkerTrait {} fn a(_x: Box) { } diff --git a/src/test/compile-fail/trait-impl-1.rs b/src/test/compile-fail/trait-impl-1.rs index dadcbd5bce7..2f4793b4d88 100644 --- a/src/test/compile-fail/trait-impl-1.rs +++ b/src/test/compile-fail/trait-impl-1.rs @@ -12,7 +12,9 @@ // 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) {} diff --git a/src/test/compile-fail/trait-object-safety.rs b/src/test/compile-fail/trait-object-safety.rs index 761bcd4968a..d45d13556e1 100644 --- a/src/test/compile-fail/trait-object-safety.rs +++ b/src/test/compile-fail/trait-object-safety.rs @@ -12,6 +12,7 @@ trait Tr { fn foo(); + fn bar(&self) { } } struct St; diff --git a/src/test/compile-fail/trait-static-method-generic-inference.rs b/src/test/compile-fail/trait-static-method-generic-inference.rs index 651f663fc99..0e357d9d4d5 100644 --- a/src/test/compile-fail/trait-static-method-generic-inference.rs +++ b/src/test/compile-fail/trait-static-method-generic-inference.rs @@ -16,6 +16,7 @@ mod base { pub trait HasNew { fn new() -> T; + fn dummy(&self) { } } pub struct Foo { diff --git a/src/test/compile-fail/type-parameter-defaults-referencing-Self-ppaux.rs b/src/test/compile-fail/type-parameter-defaults-referencing-Self-ppaux.rs new file mode 100644 index 00000000000..8ff514e04e3 --- /dev/null +++ b/src/test/compile-fail/type-parameter-defaults-referencing-Self-ppaux.rs @@ -0,0 +1,26 @@ +// 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 or the MIT license +// , 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 { 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; + //~^ ERROR as `MyAdd` +} diff --git a/src/test/compile-fail/type-parameter-defaults-referencing-Self.rs b/src/test/compile-fail/type-parameter-defaults-referencing-Self.rs new file mode 100644 index 00000000000..9982d485024 --- /dev/null +++ b/src/test/compile-fail/type-parameter-defaults-referencing-Self.rs @@ -0,0 +1,23 @@ +// 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 or the MIT license +// , 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 { + fn method(&self); +} + +fn foo(x: &Foo) { } +//~^ ERROR the type parameter `T` must be explicitly specified + +fn main() { } diff --git a/src/test/compile-fail/type-parameters-in-field-exprs.rs b/src/test/compile-fail/type-parameters-in-field-exprs.rs deleted file mode 100644 index 54ddb3e19fa..00000000000 --- a/src/test/compile-fail/type-parameters-in-field-exprs.rs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -struct Foo { - x: isize, - y: isize, -} - -fn main() { - let f = Foo { - x: 1, - y: 2, - }; - f.x::; - //~^ ERROR field expressions may not have type parameters -} - diff --git a/src/test/compile-fail/typeck-negative-impls-builtin.rs b/src/test/compile-fail/typeck-negative-impls-builtin.rs index 9da79b11cf0..557fb2f4f88 100644 --- a/src/test/compile-fail/typeck-negative-impls-builtin.rs +++ b/src/test/compile-fail/typeck-negative-impls-builtin.rs @@ -12,7 +12,9 @@ struct TestType; -trait TestTrait {} +trait TestTrait { + fn dummy(&self) { } +} impl !TestTrait for TestType {} //~^ ERROR negative impls are currently allowed just for `Send` and `Sync` diff --git a/src/test/compile-fail/typeck_type_placeholder_mismatch.rs b/src/test/compile-fail/typeck_type_placeholder_mismatch.rs index a34be63ba6b..1daea8f915b 100644 --- a/src/test/compile-fail/typeck_type_placeholder_mismatch.rs +++ b/src/test/compile-fail/typeck_type_placeholder_mismatch.rs @@ -11,14 +11,16 @@ // This test checks that genuine type errors with partial // type hints are understandable. -struct Foo; -struct Bar; +use std::marker::PhantomData; + +struct Foo(PhantomData); +struct Bar(PhantomData); pub fn main() { } fn test1() { - let x: Foo<_> = Bar::; + let x: Foo<_> = Bar::(PhantomData); //~^ ERROR mismatched types //~| expected `Foo<_>` //~| found `Bar` @@ -28,7 +30,7 @@ fn test1() { } fn test2() { - let x: Foo<_> = Bar::; + let x: Foo<_> = Bar::(PhantomData); //~^ ERROR mismatched types //~| expected `Foo<_>` //~| found `Bar` diff --git a/src/test/compile-fail/ufcs-qpath-missing-params.rs b/src/test/compile-fail/ufcs-qpath-missing-params.rs index 5fa66eb98e1..f4e18265fd9 100644 --- a/src/test/compile-fail/ufcs-qpath-missing-params.rs +++ b/src/test/compile-fail/ufcs-qpath-missing-params.rs @@ -12,6 +12,5 @@ fn main() { ::into_cow("foo".to_string()); - //~^ ERROR wrong number of type arguments: expected 2, found 0 + //~^ ERROR wrong number of type arguments: expected 1, found 0 } - diff --git a/src/test/compile-fail/unboxed-closure-feature-gate.rs b/src/test/compile-fail/unboxed-closure-feature-gate.rs index 3536244f011..74a6f869f63 100644 --- a/src/test/compile-fail/unboxed-closure-feature-gate.rs +++ b/src/test/compile-fail/unboxed-closure-feature-gate.rs @@ -11,8 +11,12 @@ // Check that parenthetical notation is feature-gated except with the // `Fn` traits. +use std::marker; + trait Foo { type Output; + + fn dummy(&self, a: A) { } } fn main() { diff --git a/src/test/compile-fail/unboxed-closure-sugar-default.rs b/src/test/compile-fail/unboxed-closure-sugar-default.rs index 870377bc1ad..831db98941c 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-default.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-default.rs @@ -19,7 +19,7 @@ trait Foo { fn dummy(&self, t: T, v: V); } -trait Eq { } +trait Eq { fn same_types(&self, x: &X) -> bool { true } } impl Eq for X { } fn eq() where A : Eq { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs index dc5576aee65..6d315c1b7a9 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-equiv.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-equiv.rs @@ -16,12 +16,14 @@ #![feature(unboxed_closures)] #![allow(dead_code)] +use std::marker::PhantomFn; + trait Foo { type Output; fn dummy(&self, t: T, u: Self::Output); } -trait Eq { } +trait Eq : PhantomFn<(Self,X)> { } impl Eq for X { } fn eq>() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs index d2f781bba11..bd3530e6e30 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-lifetime-elision.rs @@ -16,12 +16,14 @@ #![feature(unboxed_closures)] #![allow(dead_code)] +use std::marker; + trait Foo { type Output; fn dummy(&self, t: T); } -trait Eq { } +trait Eq : marker::PhantomFn<(Self, X)> { } impl Eq for X { } fn eq>() { } diff --git a/src/test/compile-fail/unboxed-closure-sugar-region.rs b/src/test/compile-fail/unboxed-closure-sugar-region.rs index 75688e44e80..057b496bd43 100644 --- a/src/test/compile-fail/unboxed-closure-sugar-region.rs +++ b/src/test/compile-fail/unboxed-closure-sugar-region.rs @@ -22,7 +22,7 @@ trait Foo<'a,T> { fn dummy(&'a self) -> &'a (T,Self::Output); } -trait Eq { } +trait Eq { fn is_of_eq_type(&self, x: &X) -> bool { true } } impl Eq for X { } fn eq>() { } diff --git a/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs b/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs index 215b2c6798e..713b64b1349 100644 --- a/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs +++ b/src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs @@ -10,7 +10,7 @@ #![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 @@ -18,12 +18,12 @@ struct YCombinator { func: F, - marker: CovariantType<(A,R)>, + marker: PhantomData<(A,R)>, } impl YCombinator { fn new(f: F) -> YCombinator { - YCombinator { func: f, marker: CovariantType } + YCombinator { func: f, marker: PhantomData } } } diff --git a/src/test/compile-fail/unnecessary-private.rs b/src/test/compile-fail/unnecessary-private.rs index e3707292f24..964db6e9a45 100644 --- a/src/test/compile-fail/unnecessary-private.rs +++ b/src/test/compile-fail/unnecessary-private.rs @@ -13,10 +13,10 @@ fn main() { 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 { diff --git a/src/test/compile-fail/unsized-inherent-impl-self-type.rs b/src/test/compile-fail/unsized-inherent-impl-self-type.rs index 8740346a217..a03c76b12dd 100644 --- a/src/test/compile-fail/unsized-inherent-impl-self-type.rs +++ b/src/test/compile-fail/unsized-inherent-impl-self-type.rs @@ -12,7 +12,7 @@ // impl - struct -struct S5; +struct S5(Y); impl S5 { //~ ERROR not implemented } diff --git a/src/test/compile-fail/unsized-trait-impl-self-type.rs b/src/test/compile-fail/unsized-trait-impl-self-type.rs index 3dd55b0ba7d..08df1d9b7b8 100644 --- a/src/test/compile-fail/unsized-trait-impl-self-type.rs +++ b/src/test/compile-fail/unsized-trait-impl-self-type.rs @@ -12,9 +12,10 @@ // impl - struct trait T3 { + fn foo(&self, z: &Z); } -struct S5; +struct S5(Y); impl T3 for S5 { //~ ERROR not implemented } diff --git a/src/test/compile-fail/unsized-trait-impl-trait-arg.rs b/src/test/compile-fail/unsized-trait-impl-trait-arg.rs index ac8043d6852..4723dfeaeb9 100644 --- a/src/test/compile-fail/unsized-trait-impl-trait-arg.rs +++ b/src/test/compile-fail/unsized-trait-impl-trait-arg.rs @@ -12,8 +12,9 @@ // impl - unbounded trait T2 { + fn foo(&self, z: Z); } -struct S4; +struct S4(Box); impl T2 for S4 { //~^ ERROR `core::marker::Sized` is not implemented for the type `X` } diff --git a/src/test/compile-fail/unsized2.rs b/src/test/compile-fail/unsized2.rs deleted file mode 100644 index b2eb2064aeb..00000000000 --- a/src/test/compile-fail/unsized2.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// Test syntax checks for `type` keyword. - -fn f() {} - -pub fn main() { - f(); - //~^ ERROR expected identifier, found keyword `type` - //~^^ ERROR: chained comparison - //~^^^ HELP: use `::< -} diff --git a/src/test/compile-fail/unsized3.rs b/src/test/compile-fail/unsized3.rs index 4fc76c99c60..de1cbab82b2 100644 --- a/src/test/compile-fail/unsized3.rs +++ b/src/test/compile-fail/unsized3.rs @@ -10,6 +10,7 @@ // Test sized-ness checking in substitution within fn bodies.. +use std::marker; // Unbounded. fn f1(x: &X) { @@ -20,7 +21,9 @@ fn f2(x: &X) { } // Bounded. -trait T {} +trait T { + fn foo(&self) { } +} fn f3(x: &X) { f4::(x); //~^ ERROR the trait `core::marker::Sized` is not implemented diff --git a/src/test/compile-fail/unsized6.rs b/src/test/compile-fail/unsized6.rs index 217d1f44d84..f31a6ffdc0d 100644 --- a/src/test/compile-fail/unsized6.rs +++ b/src/test/compile-fail/unsized6.rs @@ -10,8 +10,9 @@ // Test `?Sized` local variables. +use std::marker; -trait T {} +trait T : marker::MarkerTrait { } fn f1(x: &X) { let _: X; // <-- this is OK, no bindings created, no initializer. diff --git a/src/test/compile-fail/unsized7.rs b/src/test/compile-fail/unsized7.rs index 6fc547c0b8e..6ea3d0720ee 100644 --- a/src/test/compile-fail/unsized7.rs +++ b/src/test/compile-fail/unsized7.rs @@ -10,13 +10,17 @@ // 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 { + fn dummy(&self) -> Z; } -struct S3; + +struct S3(Box); impl T1 for S3 { //~^ ERROR `core::marker::Sized` is not implemented for the type `X` } diff --git a/src/test/compile-fail/unused-attr.rs b/src/test/compile-fail/unused-attr.rs index 2d4bc0c857a..af242b96a84 100644 --- a/src/test/compile-fail/unused-attr.rs +++ b/src/test/compile-fail/unused-attr.rs @@ -52,9 +52,9 @@ struct Foo { #[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() {} diff --git a/src/test/compile-fail/useless-priv.rs b/src/test/compile-fail/useless-priv.rs index d8531f4543d..b1120e54434 100644 --- a/src/test/compile-fail/useless-priv.rs +++ b/src/test/compile-fail/useless-priv.rs @@ -12,12 +12,14 @@ struct A { pub i: isize } 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() {} diff --git a/src/test/compile-fail/useless-priv2.rs b/src/test/compile-fail/useless-priv2.rs index 7125a66b294..a404d09248f 100644 --- a/src/test/compile-fail/useless-priv2.rs +++ b/src/test/compile-fail/useless-priv2.rs @@ -9,8 +9,10 @@ // 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() {} diff --git a/src/test/compile-fail/variance-contravariant-arg-object.rs b/src/test/compile-fail/variance-contravariant-arg-object.rs new file mode 100644 index 00000000000..3330e1d0d51 --- /dev/null +++ b/src/test/compile-fail/variance-contravariant-arg-object.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +trait Get : 'static { + fn get(&self, t: T); +} + +fn get_min_from_max<'min, 'max>(v: Box>) + -> Box> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +fn get_max_from_min<'min, 'max, G>(v: Box>) + -> Box> + where 'max : 'min +{ + v +} + +fn main() { } diff --git a/src/test/compile-fail/variance-contravariant-arg-trait-match.rs b/src/test/compile-fail/variance-contravariant-arg-trait-match.rs new file mode 100644 index 00000000000..caaad4014ad --- /dev/null +++ b/src/test/compile-fail/variance-contravariant-arg-trait-match.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , 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, t: T); +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, G : Get<&'max i32> +{ + impls_get::() //~ ERROR mismatched types +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, G : Get<&'min i32> +{ + impls_get::() +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/src/test/compile-fail/variance-contravariant-self-trait-match.rs b/src/test/compile-fail/variance-contravariant-self-trait-match.rs new file mode 100644 index 00000000000..013511ed517 --- /dev/null +++ b/src/test/compile-fail/variance-contravariant-self-trait-match.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , 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() where G : Get { } + +fn main() { } diff --git a/src/test/compile-fail/variance-covariant-arg-object.rs b/src/test/compile-fail/variance-covariant-arg-object.rs new file mode 100644 index 00000000000..828c987c082 --- /dev/null +++ b/src/test/compile-fail/variance-covariant-arg-object.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +trait Get : 'static { + fn get(&self) -> T; +} + +fn get_min_from_max<'min, 'max>(v: Box>) + -> Box> + where 'max : 'min +{ + v +} + +fn get_max_from_min<'min, 'max, G>(v: Box>) + -> Box> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +fn main() { } diff --git a/src/test/compile-fail/variance-covariant-arg-trait-match.rs b/src/test/compile-fail/variance-covariant-arg-trait-match.rs new file mode 100644 index 00000000000..17761b9c0b1 --- /dev/null +++ b/src/test/compile-fail/variance-covariant-arg-trait-match.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , 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) -> T; +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, G : Get<&'max i32> +{ + impls_get::() +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, G : Get<&'min i32> +{ + impls_get::() //~ ERROR mismatched types +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/src/test/compile-fail/variance-covariant-self-trait-match.rs b/src/test/compile-fail/variance-covariant-self-trait-match.rs new file mode 100644 index 00000000000..4e94a3eeb46 --- /dev/null +++ b/src/test/compile-fail/variance-covariant-self-trait-match.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , 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() where G : Get { } + +fn main() { } diff --git a/src/test/compile-fail/variance-deprecated-markers.rs b/src/test/compile-fail/variance-deprecated-markers.rs new file mode 100644 index 00000000000..8f9d24cb132 --- /dev/null +++ b/src/test/compile-fail/variance-deprecated-markers.rs @@ -0,0 +1,35 @@ +// 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 or the MIT license +// , 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(marker::CovariantType); //~ ERROR types=[[+];[];[]] + +#[rustc_variance] +struct B(marker::ContravariantType); //~ ERROR types=[[-];[];[]] + +#[rustc_variance] +struct C(marker::InvariantType); //~ 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() { } diff --git a/src/test/compile-fail/variance-invariant-arg-object.rs b/src/test/compile-fail/variance-invariant-arg-object.rs new file mode 100644 index 00000000000..9edb510b826 --- /dev/null +++ b/src/test/compile-fail/variance-invariant-arg-object.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +trait Get : 'static { + fn get(&self, t: T) -> T; +} + +fn get_min_from_max<'min, 'max>(v: Box>) + -> Box> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +fn get_max_from_min<'min, 'max, G>(v: Box>) + -> Box> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +fn main() { } diff --git a/src/test/compile-fail/variance-invariant-arg-trait-match.rs b/src/test/compile-fail/variance-invariant-arg-trait-match.rs new file mode 100644 index 00000000000..45fed0b083d --- /dev/null +++ b/src/test/compile-fail/variance-invariant-arg-trait-match.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , 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, t: T) -> T; +} + +fn get_min_from_max<'min, 'max, G>() + where 'max : 'min, G : Get<&'max i32> +{ + impls_get::() //~ ERROR mismatched types +} + +fn get_max_from_min<'min, 'max, G>() + where 'max : 'min, G : Get<&'min i32> +{ + impls_get::() //~ ERROR mismatched types +} + +fn impls_get() where G : Get { } + +fn main() { } diff --git a/src/test/compile-fail/variance-invariant-self-trait-match.rs b/src/test/compile-fail/variance-invariant-self-trait-match.rs new file mode 100644 index 00000000000..b46cd302ae5 --- /dev/null +++ b/src/test/compile-fail/variance-invariant-self-trait-match.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , 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() where G : Get { } + +fn main() { } diff --git a/src/test/compile-fail/variance-issue-20533.rs b/src/test/compile-fail/variance-issue-20533.rs new file mode 100644 index 00000000000..0254f56bd1a --- /dev/null +++ b/src/test/compile-fail/variance-issue-20533.rs @@ -0,0 +1,54 @@ +// 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 or the MIT license +// , 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); + +fn bar<'a, T>(_x: &'a T) -> Wrap> { + 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); + } +} + diff --git a/src/test/compile-fail/variance-regions-direct.rs b/src/test/compile-fail/variance-regions-direct.rs index d70305d1106..da4d6c75227 100644 --- a/src/test/compile-fail/variance-regions-direct.rs +++ b/src/test/compile-fail/variance-regions-direct.rs @@ -60,6 +60,7 @@ #[rustc_variance] struct Test7<'a> { //~ ERROR regions=[[*];[];[]] + //~^ ERROR parameter `'a` is never used x: isize } diff --git a/src/test/compile-fail/variance-regions-indirect.rs b/src/test/compile-fail/variance-regions-indirect.rs index 4bb329d6304..9beb90d0b24 100644 --- a/src/test/compile-fail/variance-regions-indirect.rs +++ b/src/test/compile-fail/variance-regions-indirect.rs @@ -16,6 +16,7 @@ #[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), @@ -23,16 +24,19 @@ #[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> } diff --git a/src/test/compile-fail/variance-regions-unused-direct.rs b/src/test/compile-fail/variance-regions-unused-direct.rs new file mode 100644 index 00000000000..396e7765206 --- /dev/null +++ b/src/test/compile-fail/variance-regions-unused-direct.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , 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() {} diff --git a/src/test/compile-fail/variance-regions-unused-indirect.rs b/src/test/compile-fail/variance-regions-unused-indirect.rs new file mode 100644 index 00000000000..2d234ed7b57 --- /dev/null +++ b/src/test/compile-fail/variance-regions-unused-indirect.rs @@ -0,0 +1,21 @@ +// 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 or the MIT license +// , 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() {} diff --git a/src/test/compile-fail/variance-trait-bounds.rs b/src/test/compile-fail/variance-trait-bounds.rs new file mode 100644 index 00000000000..88b50058b65 --- /dev/null +++ b/src/test/compile-fail/variance-trait-bounds.rs @@ -0,0 +1,65 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![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 { //~ ERROR types=[[+];[-];[]] + fn get(&self) -> T; +} + +#[rustc_variance] +trait Setter { //~ ERROR types=[[-];[-];[]] + fn get(&self, T); +} + +#[rustc_variance] +struct TestStruct> { //~ ERROR types=[[+, +];[];[]] + t: T, u: U +} + +#[rustc_variance] +enum TestEnum> {//~ ERROR types=[[*, +];[];[]] + //~^ ERROR parameter `U` is never used + Foo(T) +} + +#[rustc_variance] +trait TestTrait> { //~ ERROR types=[[-, +];[-];[]] + fn getter(&self, u: U) -> T; +} + +#[rustc_variance] +trait TestTrait2 : Getter { //~ ERROR types=[[+];[-];[]] +} + +#[rustc_variance] +trait TestTrait3 { //~ ERROR types=[[-];[-];[]] + fn getter>(&self); +} + +#[rustc_variance] +struct TestContraStruct> { //~ ERROR types=[[*, +];[];[]] + //~^ ERROR parameter `U` is never used + t: T +} + +#[rustc_variance] +struct TestBox+Setter> { //~ ERROR types=[[*, +];[];[]] + //~^ ERROR parameter `U` is never used + t: T +} + +pub fn main() { } diff --git a/src/test/compile-fail/variance-trait-object-bound.rs b/src/test/compile-fail/variance-trait-object-bound.rs index 965b9430a5e..f0ca1edd563 100644 --- a/src/test/compile-fail/variance-trait-object-bound.rs +++ b/src/test/compile-fail/variance-trait-object-bound.rs @@ -18,7 +18,7 @@ use std::mem; -trait T { fn foo(); } +trait T { fn foo(&self); } #[rustc_variance] struct TOption<'a> { //~ ERROR regions=[[-];[];[]] diff --git a/src/test/compile-fail/variance-types-bounds.rs b/src/test/compile-fail/variance-types-bounds.rs new file mode 100644 index 00000000000..d53e4cd7610 --- /dev/null +++ b/src/test/compile-fail/variance-types-bounds.rs @@ -0,0 +1,76 @@ +// 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 or the MIT license +// , 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 { //~ ERROR types=[[+, +];[];[]] + x: A, + y: B, +} + +#[rustc_variance] +struct TestMut { //~ ERROR types=[[+, o];[];[]] + x: A, + y: &'static mut B, +} + +#[rustc_variance] +struct TestIndirect { //~ ERROR types=[[+, o];[];[]] + m: TestMut +} + +#[rustc_variance] +struct TestIndirect2 { //~ ERROR types=[[o, o];[];[]] + n: TestMut, + m: TestMut +} + +#[rustc_variance] +trait Getter { //~ ERROR types=[[+];[-];[]] + fn get(&self) -> A; +} + +#[rustc_variance] +trait Setter { //~ ERROR types=[[-];[o];[]] + fn set(&mut self, a: A); +} + +#[rustc_variance] +trait GetterSetter { //~ ERROR types=[[o];[o];[]] + fn get(&self) -> A; + fn set(&mut self, a: A); +} + +#[rustc_variance] +trait GetterInTypeBound { //~ 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`. 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>(&self); +} + +#[rustc_variance] +trait SetterInTypeBound { //~ ERROR types=[[+];[-];[]] + fn do_it>(&self); +} + +#[rustc_variance] +struct TestObject { //~ ERROR types=[[-, +];[];[]] + n: Box+Send>, + m: Box+Send>, +} + +fn main() {} diff --git a/src/test/compile-fail/variance-types.rs b/src/test/compile-fail/variance-types.rs new file mode 100644 index 00000000000..e407ebe345a --- /dev/null +++ b/src/test/compile-fail/variance-types.rs @@ -0,0 +1,52 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![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 { //~ ERROR types=[[o];[];[]] + t: Cell +} + +#[rustc_variance] +struct InvariantIndirect { //~ ERROR types=[[o];[];[]] + t: InvariantCell +} + +#[rustc_variance] +struct Covariant { //~ ERROR types=[[+];[];[]] + t: A, u: fn() -> A +} + +#[rustc_variance] +struct Contravariant { //~ ERROR types=[[-];[];[]] + t: fn(A) +} + +#[rustc_variance] +enum Enum { //~ ERROR types=[[+, -, o];[];[]] + Foo(Covariant), + Bar(Contravariant), + Zed(Covariant,Contravariant) +} + +pub fn main() { } diff --git a/src/test/compile-fail/variance-unused-region-param.rs b/src/test/compile-fail/variance-unused-region-param.rs new file mode 100644 index 00000000000..5f504226370 --- /dev/null +++ b/src/test/compile-fail/variance-unused-region-param.rs @@ -0,0 +1,17 @@ +// 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 or the MIT license +// , 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() {} diff --git a/src/test/compile-fail/variance-unused-type-param.rs b/src/test/compile-fail/variance-unused-type-param.rs new file mode 100644 index 00000000000..2e867ec3c93 --- /dev/null +++ b/src/test/compile-fail/variance-unused-type-param.rs @@ -0,0 +1,36 @@ +// 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 or the MIT license +// , 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 { x: u32 } +//~^ ERROR parameter `A` is never used +//~| HELP PhantomData + +enum SomeEnum { Nothing } +//~^ ERROR parameter `A` is never used +//~| HELP PhantomData + +trait SomeTrait { fn foo(&self); } +//~^ ERROR parameter `A` is never used +//~| HELP PhantomFn + +// Here T might *appear* used, but in fact it isn't. +enum ListCell { +//~^ ERROR parameter `T` is never used +//~| HELP PhantomData + Cons(Box>), + Nil +} + +fn main() {} diff --git a/src/test/compile-fail/variance-use-contravariant-struct-1.rs b/src/test/compile-fail/variance-use-contravariant-struct-1.rs new file mode 100644 index 00000000000..d2fd2978750 --- /dev/null +++ b/src/test/compile-fail/variance-use-contravariant-struct-1.rs @@ -0,0 +1,26 @@ +// 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 or the MIT license +// , 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(fn(T)); + +fn foo<'min,'max>(v: SomeStruct<&'max ()>) + -> SomeStruct<&'min ()> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +#[rustc_error] +fn main() { } diff --git a/src/test/compile-fail/variance-use-contravariant-struct-2.rs b/src/test/compile-fail/variance-use-contravariant-struct-2.rs new file mode 100644 index 00000000000..b38fd0e9ffc --- /dev/null +++ b/src/test/compile-fail/variance-use-contravariant-struct-2.rs @@ -0,0 +1,27 @@ +// 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 or the MIT license +// , 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(fn(T)); + +fn bar<'min,'max>(v: SomeStruct<&'min ()>) + -> SomeStruct<&'max ()> + where 'max : 'min +{ + v +} + +#[rustc_error] +fn main() { } //~ ERROR compilation successful diff --git a/src/test/compile-fail/variance-use-covariant-struct-1.rs b/src/test/compile-fail/variance-use-covariant-struct-1.rs new file mode 100644 index 00000000000..2631cfc05e8 --- /dev/null +++ b/src/test/compile-fail/variance-use-covariant-struct-1.rs @@ -0,0 +1,23 @@ +// 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 or the MIT license +// , 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); + +fn foo<'min,'max>(v: SomeStruct<&'min ()>) + -> SomeStruct<&'max ()> + where 'max : 'min +{ + v //~ ERROR mismatched types +} + +fn main() { } diff --git a/src/test/compile-fail/variance-use-covariant-struct-2.rs b/src/test/compile-fail/variance-use-covariant-struct-2.rs new file mode 100644 index 00000000000..d8e1a5f5f1c --- /dev/null +++ b/src/test/compile-fail/variance-use-covariant-struct-2.rs @@ -0,0 +1,26 @@ +// 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 or the MIT license +// , 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); + +fn foo<'min,'max>(v: SomeStruct<&'max ()>) + -> SomeStruct<&'min ()> + where 'max : 'min +{ + v +} + +#[rustc_error] fn main() { } //~ ERROR compilation successful diff --git a/src/test/compile-fail/variance-use-invariant-struct-1.rs b/src/test/compile-fail/variance-use-invariant-struct-1.rs new file mode 100644 index 00000000000..c89436b2094 --- /dev/null +++ b/src/test/compile-fail/variance-use-invariant-struct-1.rs @@ -0,0 +1,33 @@ +// 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 or the MIT license +// , 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(*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() { } diff --git a/src/test/compile-fail/virtual-structs.rs b/src/test/compile-fail/virtual-structs.rs deleted file mode 100644 index 3b3c7d5a30f..00000000000 --- a/src/test/compile-fail/virtual-structs.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// 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() {} diff --git a/src/test/compile-fail/visible-private-types-generics.rs b/src/test/compile-fail/visible-private-types-generics.rs index 7ff18f8e088..1f2205b5c71 100644 --- a/src/test/compile-fail/visible-private-types-generics.rs +++ b/src/test/compile-fail/visible-private-types-generics.rs @@ -8,7 +8,9 @@ // 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 diff --git a/src/test/compile-fail/visible-private-types-supertrait.rs b/src/test/compile-fail/visible-private-types-supertrait.rs index dc6d446154a..9d9eae4a075 100644 --- a/src/test/compile-fail/visible-private-types-supertrait.rs +++ b/src/test/compile-fail/visible-private-types-supertrait.rs @@ -8,7 +8,9 @@ // 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 diff --git a/src/test/compile-fail/where-clause-method-substituion.rs b/src/test/compile-fail/where-clause-method-substituion.rs index a5108f005dc..bf614e6eb51 100644 --- a/src/test/compile-fail/where-clause-method-substituion.rs +++ b/src/test/compile-fail/where-clause-method-substituion.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo {} +trait Foo { + fn dummy(&self, t: T) { } +} trait Bar { fn method(&self) where A: Foo; diff --git a/src/test/compile-fail/where-clauses-no-bounds-or-predicates.rs b/src/test/compile-fail/where-clauses-no-bounds-or-predicates.rs deleted file mode 100644 index b96c7c2de6b..00000000000 --- a/src/test/compile-fail/where-clauses-no-bounds-or-predicates.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -fn equal1(_: &T, _: &T) -> bool where { -//~^ ERROR a `where` clause must have at least one predicate in it - true -} - -fn equal2(_: &T, _: &T) -> bool where T: { -//~^ ERROR each predicate in a `where` clause must have at least one bound - true -} - -fn main() { -} - diff --git a/src/test/compile-fail/where-clauses-not-parameter.rs b/src/test/compile-fail/where-clauses-not-parameter.rs index 313ae273c07..7968cc37090 100644 --- a/src/test/compile-fail/where-clauses-not-parameter.rs +++ b/src/test/compile-fail/where-clauses-not-parameter.rs @@ -21,7 +21,7 @@ fn test2() -> bool where Option : Eq {} #[derive(PartialEq)] //~^ ERROR cannot bound type `isize`, where clause bounds -enum Foo where isize : Eq { MkFoo } +enum Foo where isize : Eq { MkFoo(T) } //~^ ERROR cannot bound type `isize`, where clause bounds fn test3() -> bool where Option> : Eq {} @@ -31,7 +31,7 @@ fn test4() -> bool where Option> : Eq {} trait Baz 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 } diff --git a/src/test/debuginfo/type-names.rs b/src/test/debuginfo/type-names.rs index a592484f1a4..bf26fc23d3c 100644 --- a/src/test/debuginfo/type-names.rs +++ b/src/test/debuginfo/type-names.rs @@ -177,10 +177,11 @@ #![omit_gdb_pretty_printer_section] use self::Enum1::{Variant1_1, Variant1_2}; +use std::marker::PhantomData; use std::ptr; struct Struct1; -struct GenericStruct; +struct GenericStruct(PhantomData<(T1,T2)>); enum Enum1 { Variant1_1, @@ -207,8 +208,8 @@ pub enum Enum3 { } } -trait Trait1 { } -trait Trait2 { } +trait Trait1 { fn dummy(&self) { } } +trait Trait2 { fn dummy(&self, _: T1, _:T2) { } } impl Trait1 for isize {} impl Trait2 for isize {} @@ -240,8 +241,10 @@ fn main() { // Structs let simple_struct = Struct1; - let generic_struct1: GenericStruct = GenericStruct; - let generic_struct2: GenericStruct usize> = GenericStruct; + let generic_struct1: GenericStruct = + GenericStruct(PhantomData); + let generic_struct2: GenericStruct usize> = + GenericStruct(PhantomData); let mod_struct = Mod1::Struct2; // Enums @@ -262,10 +265,10 @@ fn main() { // References let ref1 = (&Struct1, 0i32); - let ref2 = (&GenericStruct::, 0i32); + let ref2 = (&GenericStruct::(PhantomData), 0i32); let mut mut_struct1 = Struct1; - let mut mut_generic_struct = GenericStruct::; + let mut mut_generic_struct = GenericStruct::(PhantomData); let mut_ref1 = (&mut mut_struct1, 0i32); let mut_ref2 = (&mut mut_generic_struct, 0i32); diff --git a/src/test/parse-fail/ascii-only-character-escape.rs b/src/test/parse-fail/ascii-only-character-escape.rs new file mode 100644 index 00000000000..1ba25a827a5 --- /dev/null +++ b/src/test/parse-fail/ascii-only-character-escape.rs @@ -0,0 +1,17 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +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 +} + diff --git a/src/test/parse-fail/attr-before-eof.rs b/src/test/parse-fail/attr-before-eof.rs new file mode 100644 index 00000000000..e34756229bd --- /dev/null +++ b/src/test/parse-fail/attr-before-eof.rs @@ -0,0 +1,11 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#[derive(Debug)] //~ERROR expected item after attributes diff --git a/src/test/parse-fail/attr-before-ext.rs b/src/test/parse-fail/attr-before-ext.rs new file mode 100644 index 00000000000..098c5aaec54 --- /dev/null +++ b/src/test/parse-fail/attr-before-ext.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , 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"); +} diff --git a/src/test/parse-fail/attr-before-let.rs b/src/test/parse-fail/attr-before-let.rs new file mode 100644 index 00000000000..b4a90e35c40 --- /dev/null +++ b/src/test/parse-fail/attr-before-let.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , 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; +} diff --git a/src/test/parse-fail/attr-before-stmt.rs b/src/test/parse-fail/attr-before-stmt.rs new file mode 100644 index 00000000000..ec837cd6de3 --- /dev/null +++ b/src/test/parse-fail/attr-before-stmt.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , 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() { +} diff --git a/src/test/parse-fail/attr-dangling-in-fn.rs b/src/test/parse-fail/attr-dangling-in-fn.rs new file mode 100644 index 00000000000..384622fb168 --- /dev/null +++ b/src/test/parse-fail/attr-dangling-in-fn.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , 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() { +} diff --git a/src/test/parse-fail/attr-dangling-in-mod.rs b/src/test/parse-fail/attr-dangling-in-mod.rs new file mode 100644 index 00000000000..59a922ebee1 --- /dev/null +++ b/src/test/parse-fail/attr-dangling-in-mod.rs @@ -0,0 +1,16 @@ +// 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 or the MIT license +// , 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"] diff --git a/src/test/parse-fail/attr.rs b/src/test/parse-fail/attr.rs new file mode 100644 index 00000000000..4bd61412731 --- /dev/null +++ b/src/test/parse-fail/attr.rs @@ -0,0 +1,16 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(lang_items)] + +fn main() {} + +#![lang(foo)] //~ ERROR an inner attribute is not permitted in this context +fn foo() {} diff --git a/src/test/parse-fail/attrs-after-extern-mod.rs b/src/test/parse-fail/attrs-after-extern-mod.rs new file mode 100644 index 00000000000..df747618696 --- /dev/null +++ b/src/test/parse-fail/attrs-after-extern-mod.rs @@ -0,0 +1,23 @@ +// 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 or the MIT license +// , 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() {} diff --git a/src/test/parse-fail/bad-char-literals.rs b/src/test/parse-fail/bad-char-literals.rs new file mode 100644 index 00000000000..2a358ae8307 --- /dev/null +++ b/src/test/parse-fail/bad-char-literals.rs @@ -0,0 +1,29 @@ +// 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 or the MIT license +// , 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 + ' '; //~ ERROR: character constant must be escaped: \r + + // note that this is a literal tab character here + ' '; + //~^ ERROR: character constant must be escaped: \t +} diff --git a/src/test/parse-fail/bad-lit-suffixes.rs b/src/test/parse-fail/bad-lit-suffixes.rs new file mode 100644 index 00000000000..d10337e768c --- /dev/null +++ b/src/test/parse-fail/bad-lit-suffixes.rs @@ -0,0 +1,41 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + + +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 +} diff --git a/src/test/parse-fail/bad-value-ident-false.rs b/src/test/parse-fail/bad-value-ident-false.rs new file mode 100644 index 00000000000..ca10bdd9848 --- /dev/null +++ b/src/test/parse-fail/bad-value-ident-false.rs @@ -0,0 +1,12 @@ +// 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 or the MIT license +// , 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() { } diff --git a/src/test/parse-fail/bad-value-ident-true.rs b/src/test/parse-fail/bad-value-ident-true.rs new file mode 100644 index 00000000000..4508d5219a2 --- /dev/null +++ b/src/test/parse-fail/bad-value-ident-true.rs @@ -0,0 +1,12 @@ +// 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 or the MIT license +// , 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() { } diff --git a/src/test/parse-fail/doc-before-attr.rs b/src/test/parse-fail/doc-before-attr.rs new file mode 100644 index 00000000000..bb44a6a8abb --- /dev/null +++ b/src/test/parse-fail/doc-before-attr.rs @@ -0,0 +1,12 @@ +// 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 or the MIT license +// , 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 diff --git a/src/test/parse-fail/doc-before-eof.rs b/src/test/parse-fail/doc-before-eof.rs new file mode 100644 index 00000000000..e6dd4102462 --- /dev/null +++ b/src/test/parse-fail/doc-before-eof.rs @@ -0,0 +1,11 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// hi //~ERROR expected item after doc comment diff --git a/src/test/parse-fail/doc-before-extern-rbrace.rs b/src/test/parse-fail/doc-before-extern-rbrace.rs new file mode 100644 index 00000000000..5afd1b2c6b8 --- /dev/null +++ b/src/test/parse-fail/doc-before-extern-rbrace.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , 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 diff --git a/src/test/parse-fail/doc-before-macro.rs b/src/test/parse-fail/doc-before-macro.rs new file mode 100644 index 00000000000..8dc6c546500 --- /dev/null +++ b/src/test/parse-fail/doc-before-macro.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/doc-before-rbrace.rs b/src/test/parse-fail/doc-before-rbrace.rs new file mode 100644 index 00000000000..6d05064277d --- /dev/null +++ b/src/test/parse-fail/doc-before-rbrace.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/doc-before-semi.rs b/src/test/parse-fail/doc-before-semi.rs new file mode 100644 index 00000000000..8b0300edce0 --- /dev/null +++ b/src/test/parse-fail/doc-before-semi.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/extern-crate-as-no-string-help.rs b/src/test/parse-fail/extern-crate-as-no-string-help.rs new file mode 100644 index 00000000000..5cc52f6f6db --- /dev/null +++ b/src/test/parse-fail/extern-crate-as-no-string-help.rs @@ -0,0 +1,15 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// 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? diff --git a/src/test/parse-fail/generic-non-trailing-defaults.rs b/src/test/parse-fail/generic-non-trailing-defaults.rs new file mode 100644 index 00000000000..0cfb05b9332 --- /dev/null +++ b/src/test/parse-fail/generic-non-trailing-defaults.rs @@ -0,0 +1,17 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Heap; + +struct Vec; //~ ERROR type parameters with a default must be trailing + +struct Foo, C>; //~ ERROR type parameters with a default must be trailing + +fn main() {} diff --git a/src/test/parse-fail/int-literal-too-large-span.rs b/src/test/parse-fail/int-literal-too-large-span.rs new file mode 100644 index 00000000000..8a496c934b9 --- /dev/null +++ b/src/test/parse-fail/int-literal-too-large-span.rs @@ -0,0 +1,17 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// issue #17123 + +fn main() { + 100000000000000000000000000000000 //~ ERROR int literal is too large + + ; // the span shouldn't point to this. +} diff --git a/src/test/parse-fail/issue-10412.rs b/src/test/parse-fail/issue-10412.rs new file mode 100644 index 00000000000..8a99633b4fc --- /dev/null +++ b/src/test/parse-fail/issue-10412.rs @@ -0,0 +1,32 @@ +// 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 or the MIT license +// , 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 ; //~ ERROR no longer a special lifetime + fn deserialize(repr : &[u8]) -> &'self T; //~ ERROR no longer a special lifetime +} + +impl<'self> Serializable for &'self str { //~ ERROR no longer a special lifetime + //~^ ERROR no longer a special lifetime + fn serialize(val : &'self str) -> Vec { //~ 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); +} diff --git a/src/test/parse-fail/issue-12560-1.rs b/src/test/parse-fail/issue-12560-1.rs new file mode 100644 index 00000000000..ea2043e6703 --- /dev/null +++ b/src/test/parse-fail/issue-12560-1.rs @@ -0,0 +1,23 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// 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 }) +} diff --git a/src/test/parse-fail/issue-14182.rs b/src/test/parse-fail/issue-14182.rs new file mode 100644 index 00000000000..364951a4fea --- /dev/null +++ b/src/test/parse-fail/issue-14182.rs @@ -0,0 +1,27 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// 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 + }; +} diff --git a/src/test/parse-fail/issue-17383.rs b/src/test/parse-fail/issue-17383.rs new file mode 100644 index 00000000000..c71e0ecd494 --- /dev/null +++ b/src/test/parse-fail/issue-17383.rs @@ -0,0 +1,18 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum X { + A = + b'a' //~ ERROR discriminator values can only be used with a c-like enum + , + B(isize) +} + +fn main() {} diff --git a/src/test/parse-fail/issue-17718-const-mut.rs b/src/test/parse-fail/issue-17718-const-mut.rs new file mode 100644 index 00000000000..5177ebbc188 --- /dev/null +++ b/src/test/parse-fail/issue-17718-const-mut.rs @@ -0,0 +1,18 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +const +mut //~ ERROR: const globals cannot be mutable +//~^ HELP did you mean to declare a static? +FOO: usize = 3; + +fn main() { +} + diff --git a/src/test/parse-fail/issue-1802-2.rs b/src/test/parse-fail/issue-1802-2.rs new file mode 100644 index 00000000000..f6da2fc82c3 --- /dev/null +++ b/src/test/parse-fail/issue-1802-2.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , 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); +} diff --git a/src/test/parse-fail/issue-5544-a.rs b/src/test/parse-fail/issue-5544-a.rs new file mode 100644 index 00000000000..95a4f36d171 --- /dev/null +++ b/src/test/parse-fail/issue-5544-a.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/issue-5544-b.rs b/src/test/parse-fail/issue-5544-b.rs new file mode 100644 index 00000000000..afff5984b46 --- /dev/null +++ b/src/test/parse-fail/issue-5544-b.rs @@ -0,0 +1,14 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/issue-8537.rs b/src/test/parse-fail/issue-8537.rs new file mode 100644 index 00000000000..52cf420a9ff --- /dev/null +++ b/src/test/parse-fail/issue-8537.rs @@ -0,0 +1,15 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +pub extern + "invalid-ab_isize" //~ ERROR illegal ABI +fn foo() {} + +fn main() {} diff --git a/src/test/parse-fail/keyword-as-as-identifier.rs b/src/test/parse-fail/keyword-as-as-identifier.rs new file mode 100644 index 00000000000..f307b12f66e --- /dev/null +++ b/src/test/parse-fail/keyword-as-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-break-as-identifier.rs b/src/test/parse-fail/keyword-break-as-identifier.rs new file mode 100644 index 00000000000..1e2725eb2fe --- /dev/null +++ b/src/test/parse-fail/keyword-break-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-else-as-identifier.rs b/src/test/parse-fail/keyword-else-as-identifier.rs new file mode 100644 index 00000000000..101fd938dcb --- /dev/null +++ b/src/test/parse-fail/keyword-else-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-enum-as-identifier.rs b/src/test/parse-fail/keyword-enum-as-identifier.rs new file mode 100644 index 00000000000..ed504cc7b7f --- /dev/null +++ b/src/test/parse-fail/keyword-enum-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-extern-as-identifier.rs b/src/test/parse-fail/keyword-extern-as-identifier.rs new file mode 100644 index 00000000000..3260506b3e1 --- /dev/null +++ b/src/test/parse-fail/keyword-extern-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-fn-as-identifier.rs b/src/test/parse-fail/keyword-fn-as-identifier.rs new file mode 100644 index 00000000000..8c98da229c8 --- /dev/null +++ b/src/test/parse-fail/keyword-fn-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-for-as-identifier.rs b/src/test/parse-fail/keyword-for-as-identifier.rs new file mode 100644 index 00000000000..196a3390676 --- /dev/null +++ b/src/test/parse-fail/keyword-for-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-if-as-identifier.rs b/src/test/parse-fail/keyword-if-as-identifier.rs new file mode 100644 index 00000000000..05f82ec790c --- /dev/null +++ b/src/test/parse-fail/keyword-if-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-impl-as-identifier.rs b/src/test/parse-fail/keyword-impl-as-identifier.rs new file mode 100644 index 00000000000..1dd21800345 --- /dev/null +++ b/src/test/parse-fail/keyword-impl-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-let-as-identifier.rs b/src/test/parse-fail/keyword-let-as-identifier.rs new file mode 100644 index 00000000000..0069a26a40b --- /dev/null +++ b/src/test/parse-fail/keyword-let-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-loop-as-identifier.rs b/src/test/parse-fail/keyword-loop-as-identifier.rs new file mode 100644 index 00000000000..6e469e8c0b4 --- /dev/null +++ b/src/test/parse-fail/keyword-loop-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-match-as-identifier.rs b/src/test/parse-fail/keyword-match-as-identifier.rs new file mode 100644 index 00000000000..9155ebc71fa --- /dev/null +++ b/src/test/parse-fail/keyword-match-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-mod-as-identifier.rs b/src/test/parse-fail/keyword-mod-as-identifier.rs new file mode 100644 index 00000000000..02f57e937dd --- /dev/null +++ b/src/test/parse-fail/keyword-mod-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-pub-as-identifier.rs b/src/test/parse-fail/keyword-pub-as-identifier.rs new file mode 100644 index 00000000000..aa679741c1c --- /dev/null +++ b/src/test/parse-fail/keyword-pub-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-return-as-identifier.rs b/src/test/parse-fail/keyword-return-as-identifier.rs new file mode 100644 index 00000000000..c5676445917 --- /dev/null +++ b/src/test/parse-fail/keyword-return-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-self-as-identifier.rs b/src/test/parse-fail/keyword-self-as-identifier.rs new file mode 100644 index 00000000000..8bb52142287 --- /dev/null +++ b/src/test/parse-fail/keyword-self-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-static-as-identifier.rs b/src/test/parse-fail/keyword-static-as-identifier.rs new file mode 100644 index 00000000000..7268c4f387e --- /dev/null +++ b/src/test/parse-fail/keyword-static-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-struct-as-identifier.rs b/src/test/parse-fail/keyword-struct-as-identifier.rs new file mode 100644 index 00000000000..bd42eac0ecb --- /dev/null +++ b/src/test/parse-fail/keyword-struct-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-super-as-identifier.rs b/src/test/parse-fail/keyword-super-as-identifier.rs new file mode 100644 index 00000000000..0378c326a89 --- /dev/null +++ b/src/test/parse-fail/keyword-super-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-super.rs b/src/test/parse-fail/keyword-super.rs new file mode 100644 index 00000000000..0c94f76f1f6 --- /dev/null +++ b/src/test/parse-fail/keyword-super.rs @@ -0,0 +1,13 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let super: isize; //~ ERROR expected identifier, found keyword `super` +} diff --git a/src/test/parse-fail/keyword-trait-as-identifier.rs b/src/test/parse-fail/keyword-trait-as-identifier.rs new file mode 100644 index 00000000000..95c0d174c33 --- /dev/null +++ b/src/test/parse-fail/keyword-trait-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-type-as-identifier.rs b/src/test/parse-fail/keyword-type-as-identifier.rs new file mode 100644 index 00000000000..0aaa2a63c7c --- /dev/null +++ b/src/test/parse-fail/keyword-type-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-unsafe-as-identifier.rs b/src/test/parse-fail/keyword-unsafe-as-identifier.rs new file mode 100644 index 00000000000..1b631eb877d --- /dev/null +++ b/src/test/parse-fail/keyword-unsafe-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-use-as-identifier.rs b/src/test/parse-fail/keyword-use-as-identifier.rs new file mode 100644 index 00000000000..e82afd54442 --- /dev/null +++ b/src/test/parse-fail/keyword-use-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword-while-as-identifier.rs b/src/test/parse-fail/keyword-while-as-identifier.rs new file mode 100644 index 00000000000..95cea65c610 --- /dev/null +++ b/src/test/parse-fail/keyword-while-as-identifier.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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 +} diff --git a/src/test/parse-fail/keyword.rs b/src/test/parse-fail/keyword.rs new file mode 100644 index 00000000000..64eac47e69b --- /dev/null +++ b/src/test/parse-fail/keyword.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , 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` +} diff --git a/src/test/parse-fail/keywords-followed-by-double-colon.rs b/src/test/parse-fail/keywords-followed-by-double-colon.rs new file mode 100644 index 00000000000..f69b041597e --- /dev/null +++ b/src/test/parse-fail/keywords-followed-by-double-colon.rs @@ -0,0 +1,15 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + struct::foo(); //~ ERROR expected identifier + mut::baz(); //~ ERROR expected identifier +} + diff --git a/src/test/parse-fail/lex-bad-numeric-literals.rs b/src/test/parse-fail/lex-bad-numeric-literals.rs new file mode 100644 index 00000000000..9a490be6a01 --- /dev/null +++ b/src/test/parse-fail/lex-bad-numeric-literals.rs @@ -0,0 +1,35 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +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 +} diff --git a/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs b/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs new file mode 100644 index 00000000000..c1e5121d6dd --- /dev/null +++ b/src/test/parse-fail/lex-bare-cr-string-literal-doc-comment.rs @@ -0,0 +1,30 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-cr + +/// doc comment with bare CR: ' ' +pub fn foo() {} +//~^^ ERROR: bare CR not allowed in doc-comment + +/** block doc comment with bare CR: ' ' */ +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 bar"; //~ ERROR: bare CR not allowed in string + + // the following string literal has a bare CR in it + let _s = r"bar foo"; //~ ERROR: bare CR not allowed in raw string + + // the following string literal has a bare CR in it + let _s = "foo\ bar"; //~ ERROR: unknown character escape: \r +} diff --git a/src/test/parse-fail/lifetime-no-keyword.rs b/src/test/parse-fail/lifetime-no-keyword.rs new file mode 100644 index 00000000000..8ffbcd90df8 --- /dev/null +++ b/src/test/parse-fail/lifetime-no-keyword.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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() { } diff --git a/src/test/parse-fail/lifetime-obsoleted-self.rs b/src/test/parse-fail/lifetime-obsoleted-self.rs new file mode 100644 index 00000000000..766922f2f88 --- /dev/null +++ b/src/test/parse-fail/lifetime-obsoleted-self.rs @@ -0,0 +1,13 @@ +// 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 or the MIT license +// , 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() { } diff --git a/src/test/parse-fail/macros-no-semicolon-items.rs b/src/test/parse-fail/macros-no-semicolon-items.rs new file mode 100644 index 00000000000..314292085df --- /dev/null +++ b/src/test/parse-fail/macros-no-semicolon-items.rs @@ -0,0 +1,14 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! foo() //~ ERROR semicolon + +fn main() { +} diff --git a/src/test/parse-fail/mod_file_disambig.rs b/src/test/parse-fail/mod_file_disambig.rs deleted file mode 100644 index 48bd00a3ee0..00000000000 --- a/src/test/parse-fail/mod_file_disambig.rs +++ /dev/null @@ -1,15 +0,0 @@ -// 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 or the MIT license -// , 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); -} diff --git a/src/test/parse-fail/mod_file_not_owning.rs b/src/test/parse-fail/mod_file_not_owning.rs deleted file mode 100644 index adbcedd91f2..00000000000 --- a/src/test/parse-fail/mod_file_not_owning.rs +++ /dev/null @@ -1,15 +0,0 @@ -// Copyright 2014 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// error-pattern: cannot declare a new module at this location - -mod mod_file_not_owning_aux1; - -fn main() {} diff --git a/src/test/parse-fail/no-binary-float-literal.rs b/src/test/parse-fail/no-binary-float-literal.rs new file mode 100644 index 00000000000..2e207f90d36 --- /dev/null +++ b/src/test/parse-fail/no-binary-float-literal.rs @@ -0,0 +1,17 @@ +// 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 or the MIT license +// , 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; +} diff --git a/src/test/parse-fail/no-hex-float-literal.rs b/src/test/parse-fail/no-hex-float-literal.rs new file mode 100644 index 00000000000..4abb6093b24 --- /dev/null +++ b/src/test/parse-fail/no-hex-float-literal.rs @@ -0,0 +1,17 @@ +// 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 or the MIT license +// , 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; +} diff --git a/src/test/parse-fail/no-unsafe-self.rs b/src/test/parse-fail/no-unsafe-self.rs new file mode 100644 index 00000000000..0bf73bbdfe3 --- /dev/null +++ b/src/test/parse-fail/no-unsafe-self.rs @@ -0,0 +1,22 @@ +// 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 or the MIT license +// , 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() { } diff --git a/src/test/parse-fail/non-str-meta.rs b/src/test/parse-fail/non-str-meta.rs new file mode 100644 index 00000000000..752f72f0b08 --- /dev/null +++ b/src/test/parse-fail/non-str-meta.rs @@ -0,0 +1,15 @@ +// 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 or the MIT license +// , 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() { } diff --git a/src/test/parse-fail/obsolete-for-sized.rs b/src/test/parse-fail/obsolete-for-sized.rs new file mode 100644 index 00000000000..1b86d08a50d --- /dev/null +++ b/src/test/parse-fail/obsolete-for-sized.rs @@ -0,0 +1,17 @@ +// 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 or the MIT license +// , 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() { } diff --git a/src/test/parse-fail/obsolete-proc.rs b/src/test/parse-fail/obsolete-proc.rs new file mode 100644 index 00000000000..5208cdb6ad2 --- /dev/null +++ b/src/test/parse-fail/obsolete-proc.rs @@ -0,0 +1,17 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// 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() { } diff --git a/src/test/parse-fail/qquote-1.rs b/src/test/parse-fail/qquote-1.rs new file mode 100644 index 00000000000..deae9a83866 --- /dev/null +++ b/src/test/parse-fail/qquote-1.rs @@ -0,0 +1,68 @@ +// 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 or the MIT license +// , 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(expr: T, f: |pprust::ps, T|, expect: str) { + panic!(); +} diff --git a/src/test/parse-fail/qquote-2.rs b/src/test/parse-fail/qquote-2.rs new file mode 100644 index 00000000000..978287a681e --- /dev/null +++ b/src/test/parse-fail/qquote-2.rs @@ -0,0 +1,61 @@ +// 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 or the MIT license +// , 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(expr: T, f: |pprust::ps, T|, expect: str) { + panic!(); +} diff --git a/src/test/parse-fail/regions-fn-bound.rs b/src/test/parse-fail/regions-fn-bound.rs new file mode 100644 index 00000000000..c2b52b79f6c --- /dev/null +++ b/src/test/parse-fail/regions-fn-bound.rs @@ -0,0 +1,46 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn of() -> |T| { panic!(); } +fn subtype(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::(of::()) 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() {} diff --git a/src/test/parse-fail/require-parens-for-chained-comparison.rs b/src/test/parse-fail/require-parens-for-chained-comparison.rs new file mode 100644 index 00000000000..f2705f58331 --- /dev/null +++ b/src/test/parse-fail/require-parens-for-chained-comparison.rs @@ -0,0 +1,23 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn f() {} + +fn main() { + false == false == false; + //~^ ERROR: chained comparison operators require parentheses + + false == 0 < 2; + //~^ ERROR: chained comparison operators require parentheses + + f(); + //~^ ERROR: chained comparison operators require parentheses + //~^^ HELP: use `::<...>` instead of `<...>` +} diff --git a/src/test/parse-fail/struct-no-fields-2.rs b/src/test/parse-fail/struct-no-fields-2.rs new file mode 100644 index 00000000000..4f973f81b16 --- /dev/null +++ b/src/test/parse-fail/struct-no-fields-2.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , 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() {} diff --git a/src/test/parse-fail/struct-no-fields-3.rs b/src/test/parse-fail/struct-no-fields-3.rs new file mode 100644 index 00000000000..e594683feed --- /dev/null +++ b/src/test/parse-fail/struct-no-fields-3.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , 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() {} diff --git a/src/test/parse-fail/struct-no-fields-4.rs b/src/test/parse-fail/struct-no-fields-4.rs new file mode 100644 index 00000000000..60a0a85d0ab --- /dev/null +++ b/src/test/parse-fail/struct-no-fields-4.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , 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() {} diff --git a/src/test/parse-fail/struct-no-fields-5.rs b/src/test/parse-fail/struct-no-fields-5.rs new file mode 100644 index 00000000000..940fa9c7f27 --- /dev/null +++ b/src/test/parse-fail/struct-no-fields-5.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , 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() {} diff --git a/src/test/parse-fail/struct-variant-no-fields.rs b/src/test/parse-fail/struct-variant-no-fields.rs new file mode 100644 index 00000000000..41dbbeefc0a --- /dev/null +++ b/src/test/parse-fail/struct-variant-no-fields.rs @@ -0,0 +1,13 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Foo { + Bar {} //~ ERROR unit-like struct variant should be written without braces, as `Bar,` +} diff --git a/src/test/parse-fail/struct-variant-no-pub.rs b/src/test/parse-fail/struct-variant-no-pub.rs new file mode 100644 index 00000000000..e62b39ad5aa --- /dev/null +++ b/src/test/parse-fail/struct-variant-no-pub.rs @@ -0,0 +1,17 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +enum Foo { + Bar { + pub a: isize //~ ERROR: `pub` is not allowed here + } +} + +fn main() {} diff --git a/src/test/parse-fail/syntax-trait-polarity.rs b/src/test/parse-fail/syntax-trait-polarity.rs new file mode 100644 index 00000000000..1ab79f5c80e --- /dev/null +++ b/src/test/parse-fail/syntax-trait-polarity.rs @@ -0,0 +1,33 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![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; + +impl !TestType2 {} +//~^ ERROR inherent implementation can't be negated + +unsafe impl !Send for TestType2 {} +impl !TestTrait for TestType2 {} + +fn main() {} diff --git a/src/test/parse-fail/tag-variant-disr-non-nullary.rs b/src/test/parse-fail/tag-variant-disr-non-nullary.rs new file mode 100644 index 00000000000..207bbe9a446 --- /dev/null +++ b/src/test/parse-fail/tag-variant-disr-non-nullary.rs @@ -0,0 +1,20 @@ +// 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 or the MIT license +// , 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), +} diff --git a/src/test/parse-fail/trailing-carriage-return-in-string.rs b/src/test/parse-fail/trailing-carriage-return-in-string.rs new file mode 100644 index 00000000000..81098333261 --- /dev/null +++ b/src/test/parse-fail/trailing-carriage-return-in-string.rs @@ -0,0 +1,23 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// ignore-tidy-cr +// Issue #11669 + +fn main() { + // \r\n + let ok = "This is \ + a test"; + // \r only + let bad = "This is \ a test"; + //~^ ERROR unknown character escape: \r + //~^^ HELP this is an isolated carriage return + +} diff --git a/src/test/parse-fail/trailing-plus-in-bounds.rs b/src/test/parse-fail/trailing-plus-in-bounds.rs new file mode 100644 index 00000000000..e8f9ed4d2cf --- /dev/null +++ b/src/test/parse-fail/trailing-plus-in-bounds.rs @@ -0,0 +1,18 @@ +// 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 or the MIT license +// , 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 = box 3 as Box; + //~^ ERROR at least one type parameter bound must be specified + //~^^ ERROR at least one type parameter bound must be specified +} + diff --git a/src/test/parse-fail/trait-bounds-not-on-impl.rs b/src/test/parse-fail/trait-bounds-not-on-impl.rs new file mode 100644 index 00000000000..a034352c4a6 --- /dev/null +++ b/src/test/parse-fail/trait-bounds-not-on-impl.rs @@ -0,0 +1,19 @@ +// 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 or the MIT license +// , 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() { } diff --git a/src/test/parse-fail/type-parameters-in-field-exprs.rs b/src/test/parse-fail/type-parameters-in-field-exprs.rs new file mode 100644 index 00000000000..54ddb3e19fa --- /dev/null +++ b/src/test/parse-fail/type-parameters-in-field-exprs.rs @@ -0,0 +1,24 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Foo { + x: isize, + y: isize, +} + +fn main() { + let f = Foo { + x: 1, + y: 2, + }; + f.x::; + //~^ ERROR field expressions may not have type parameters +} + diff --git a/src/test/parse-fail/unsized2.rs b/src/test/parse-fail/unsized2.rs new file mode 100644 index 00000000000..b2eb2064aeb --- /dev/null +++ b/src/test/parse-fail/unsized2.rs @@ -0,0 +1,20 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Test syntax checks for `type` keyword. + +fn f() {} + +pub fn main() { + f(); + //~^ ERROR expected identifier, found keyword `type` + //~^^ ERROR: chained comparison + //~^^^ HELP: use `::< +} diff --git a/src/test/parse-fail/virtual-structs.rs b/src/test/parse-fail/virtual-structs.rs new file mode 100644 index 00000000000..3b3c7d5a30f --- /dev/null +++ b/src/test/parse-fail/virtual-structs.rs @@ -0,0 +1,20 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// 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() {} diff --git a/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs b/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs new file mode 100644 index 00000000000..b96c7c2de6b --- /dev/null +++ b/src/test/parse-fail/where-clauses-no-bounds-or-predicates.rs @@ -0,0 +1,23 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn equal1(_: &T, _: &T) -> bool where { +//~^ ERROR a `where` clause must have at least one predicate in it + true +} + +fn equal2(_: &T, _: &T) -> bool where T: { +//~^ ERROR each predicate in a `where` clause must have at least one bound + true +} + +fn main() { +} + diff --git a/src/test/pretty/empty-impl.rs b/src/test/pretty/empty-impl.rs index f22f1b40952..f5205de5c1f 100644 --- a/src/test/pretty/empty-impl.rs +++ b/src/test/pretty/empty-impl.rs @@ -8,8 +8,8 @@ // 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 { } diff --git a/src/test/pretty/path-type-bounds.rs b/src/test/pretty/path-type-bounds.rs index e27a3365a41..9e1f2aa8bfe 100644 --- a/src/test/pretty/path-type-bounds.rs +++ b/src/test/pretty/path-type-bounds.rs @@ -11,7 +11,9 @@ // pp-exact -trait Tr { } +trait Tr { + fn dummy(&self) { } +} impl Tr for int { } fn foo<'a>(x: Box) -> Box { x } diff --git a/src/test/run-fail/bug-811.rs b/src/test/run-fail/bug-811.rs index e46564f8076..4ad81197286 100644 --- a/src/test/run-fail/bug-811.rs +++ b/src/test/run-fail/bug-811.rs @@ -9,6 +9,9 @@ // except according to those terms. // error-pattern:quux + +use std::marker::PhantomData; + fn test00_start(ch: chan_t, message: int) { send(ch, message); } type task_id = int; @@ -17,6 +20,7 @@ struct chan_t { task: task_id, port: port_id, + marker: PhantomData<*mut T>, } fn send(_ch: chan_t, _data: T) { panic!(); } diff --git a/src/test/run-make/rustdoc-json/foo.rs b/src/test/run-make/rustdoc-json/foo.rs index d57a7164cdb..3bd56c14193 100644 --- a/src/test/run-make/rustdoc-json/foo.rs +++ b/src/test/run-make/rustdoc-json/foo.rs @@ -21,5 +21,5 @@ pub fn baz() { } } /// *wow* - pub trait Doge { } + pub trait Doge { fn dummy(&self) { } } } diff --git a/src/test/run-make/rustdoc-negative-impl/foo.rs b/src/test/run-make/rustdoc-negative-impl/foo.rs index b5fcbf46c5c..6c56bcc9be6 100644 --- a/src/test/run-make/rustdoc-negative-impl/foo.rs +++ b/src/test/run-make/rustdoc-negative-impl/foo.rs @@ -13,7 +13,7 @@ // @matches foo/struct.Alpha.html '//pre' "pub struct Alpha" pub struct Alpha; // @matches foo/struct.Bravo.html '//pre' "pub struct Bravo" -pub struct Bravo; +pub struct Bravo(B); // @matches foo/struct.Alpha.html '//*[@class="impl"]//code' "impl !Send for Alpha" impl !Send for Alpha {} diff --git a/src/test/run-make/rustdoc-search-index/index.rs b/src/test/run-make/rustdoc-search-index/index.rs index dd68f2d6f1d..42469a21f22 100644 --- a/src/test/run-make/rustdoc-search-index/index.rs +++ b/src/test/run-make/rustdoc-search-index/index.rs @@ -21,6 +21,6 @@ fn priv_method() {} // @!has - priv_method } pub trait PrivateTrait { - fn trait_method() {} // @!has - priv_method + fn trait_method(&self) {} // @!has - priv_method } } diff --git a/src/test/run-make/rustdoc-smoke/foo.rs b/src/test/run-make/rustdoc-smoke/foo.rs index 0438c9aba35..f6b73021beb 100644 --- a/src/test/run-make/rustdoc-smoke/foo.rs +++ b/src/test/run-make/rustdoc-smoke/foo.rs @@ -26,7 +26,7 @@ pub fn baz() { } /// *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 } diff --git a/src/test/run-make/rustdoc-viewpath-self/foo.rs b/src/test/run-make/rustdoc-viewpath-self/foo.rs index da8f7393023..6fd47d84c30 100644 --- a/src/test/run-make/rustdoc-viewpath-self/foo.rs +++ b/src/test/run-make/rustdoc-viewpath-self/foo.rs @@ -9,7 +9,7 @@ // except according to those terms. pub mod io { - pub trait Reader { } + pub trait Reader { fn dummy(&self) { } } } pub enum Maybe { diff --git a/src/test/run-make/rustdoc-where/foo.rs b/src/test/run-make/rustdoc-where/foo.rs index 68fde60564e..91a7e1c9fd4 100644 --- a/src/test/run-make/rustdoc-where/foo.rs +++ b/src/test/run-make/rustdoc-where/foo.rs @@ -8,30 +8,33 @@ // 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 where A: MyTrait" -pub struct Alpha where A: MyTrait; +pub struct Alpha(A) where A: MyTrait; // @has foo/trait.Bravo.html '//pre' "pub trait Bravo where B: MyTrait" -pub trait Bravo where B: MyTrait {} +pub trait Bravo where B: MyTrait { fn get(&self, B: B); } // @has foo/fn.charlie.html '//pre' "pub fn charlie() where C: MyTrait" pub fn charlie() where C: MyTrait {} -pub struct Delta; +pub struct Delta(D); + // @has foo/struct.Delta.html '//*[@class="impl"]//code' \ // "impl Delta where D: MyTrait" impl Delta where D: MyTrait { pub fn delta() {} } -pub struct Echo; +pub struct Echo(E); + // @has foo/struct.Echo.html '//*[@class="impl"]//code' \ // "impl MyTrait for Echo where E: MyTrait" // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \ // "impl MyTrait for Echo where E: MyTrait" impl MyTrait for Echo where E: MyTrait {} -pub enum Foxtrot {} +pub enum Foxtrot { Foxtrot1(F) } + // @has foo/enum.Foxtrot.html '//*[@class="impl"]//code' \ // "impl MyTrait for Foxtrot where F: MyTrait" // @has foo/trait.MyTrait.html '//*[@id="implementors-list"]//code' \ diff --git a/src/test/run-make/save-analysis/foo.rs b/src/test/run-make/save-analysis/foo.rs index db70a245232..38381da3670 100644 --- a/src/test/run-make/save-analysis/foo.rs +++ b/src/test/run-make/save-analysis/foo.rs @@ -34,7 +34,7 @@ static uni: &'static str = "Les Miséééééééérables"; static yy: usize = 25; -static bob: Option> = None; +static bob: Option<&'static [isize]> = None; // buglink test - see issue #1337. @@ -99,6 +99,7 @@ struct some_fields { type SF = some_fields; trait SuperTrait { + fn dummy(&self) { } } trait SomeTrait: SuperTrait { diff --git a/src/test/run-make/simd-ffi/simd.rs b/src/test/run-make/simd-ffi/simd.rs index 834a2adf01f..f418d5d1fb7 100755 --- a/src/test/run-make/simd-ffi/simd.rs +++ b/src/test/run-make/simd-ffi/simd.rs @@ -70,10 +70,14 @@ pub fn bar(a: i32x4, b: i32x4) -> i32x4 { } #[lang = "sized"] -trait Sized {} +pub trait Sized : PhantomFn {} #[lang = "copy"] -trait Copy {} +pub trait Copy : PhantomFn {} + +#[lang="phantom_fn"] +pub trait PhantomFn { } +impl PhantomFn for U { } mod core { pub mod marker { diff --git a/src/test/run-make/symbols-are-reasonable/lib.rs b/src/test/run-make/symbols-are-reasonable/lib.rs index 1e0570c95ac..e1f36ecda53 100644 --- a/src/test/run-make/symbols-are-reasonable/lib.rs +++ b/src/test/run-make/symbols-are-reasonable/lib.rs @@ -11,7 +11,7 @@ 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() { diff --git a/src/test/run-make/target-specs/foo.rs b/src/test/run-make/target-specs/foo.rs index 365fc039a4e..acda8705b19 100644 --- a/src/test/run-make/target-specs/foo.rs +++ b/src/test/run-make/target-specs/foo.rs @@ -11,11 +11,15 @@ #![feature(lang_items, no_std)] #![no_std] +#[lang="phantom_fn"] +trait PhantomFn { } +impl PhantomFn for U { } + #[lang="copy"] -trait Copy { } +trait Copy : PhantomFn { } #[lang="sized"] -trait Sized { } +trait Sized : PhantomFn { } #[lang="start"] fn start(_main: *const u8, _argc: int, _argv: *const *const u8) -> int { 0 } diff --git a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs index 195055f12d1..aecec44f6fd 100644 --- a/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs +++ b/src/test/run-pass-valgrind/cleanup-auto-borrow-obj.rs @@ -25,7 +25,7 @@ fn drop(&mut self) { } -trait Trait {} +trait Trait { fn dummy(&self) { } } impl Trait for Foo {} pub fn main() { diff --git a/src/test/run-pass-valgrind/dst-dtor-1.rs b/src/test/run-pass-valgrind/dst-dtor-1.rs index 47e2a18a999..c49a684de94 100644 --- a/src/test/run-pass-valgrind/dst-dtor-1.rs +++ b/src/test/run-pass-valgrind/dst-dtor-1.rs @@ -19,7 +19,7 @@ fn drop(&mut self) { } } -trait Trait {} +trait Trait { fn dummy(&self) { } } impl Trait for Foo {} struct Fat { diff --git a/src/test/run-pass/associated-types-basic.rs b/src/test/run-pass/associated-types-basic.rs index 3314b613201..f5521f7da85 100644 --- a/src/test/run-pass/associated-types-basic.rs +++ b/src/test/run-pass/associated-types-basic.rs @@ -8,7 +8,9 @@ // 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; } diff --git a/src/test/run-pass/associated-types-conditional-dispatch.rs b/src/test/run-pass/associated-types-conditional-dispatch.rs index f21b7183d70..aa65b0ed10b 100644 --- a/src/test/run-pass/associated-types-conditional-dispatch.rs +++ b/src/test/run-pass/associated-types-conditional-dispatch.rs @@ -14,6 +14,7 @@ // `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 { @@ -41,7 +42,8 @@ fn eq(&self, other: &[B]) -> bool { } struct DerefWithHelper { - pub helper: H + pub helper: H, + pub marker: PhantomData, } trait Helper { @@ -63,7 +65,8 @@ fn deref(&self) -> &T { } pub fn check(x: T, y: T) -> bool { - let d: DerefWithHelper, T> = DerefWithHelper { helper: Some(x) }; + let d: DerefWithHelper, T> = DerefWithHelper { helper: Some(x), + marker: PhantomData }; d.eq(&y) } diff --git a/src/test/run-pass/associated-types-issue-20371.rs b/src/test/run-pass/associated-types-issue-20371.rs index d35b7331d4d..40ef7f3531c 100644 --- a/src/test/run-pass/associated-types-issue-20371.rs +++ b/src/test/run-pass/associated-types-issue-20371.rs @@ -11,6 +11,8 @@ // 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() {} diff --git a/src/test/run-pass/associated-types-issue-21212.rs b/src/test/run-pass/associated-types-issue-21212.rs index ced44250e4d..3c91577362a 100644 --- a/src/test/run-pass/associated-types-issue-21212.rs +++ b/src/test/run-pass/associated-types-issue-21212.rs @@ -20,7 +20,8 @@ fn parse(input: ::Input) { panic!() } } -impl

Parser for P { + +impl

Parser for P { type Input = (); } diff --git a/src/test/run-pass/associated-types-nested-projections.rs b/src/test/run-pass/associated-types-nested-projections.rs index e3227613159..2ee8ef0d3dd 100644 --- a/src/test/run-pass/associated-types-nested-projections.rs +++ b/src/test/run-pass/associated-types-nested-projections.rs @@ -10,11 +10,12 @@ // 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; diff --git a/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs b/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs index dd5814f875b..de96af83f59 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds-binding.rs @@ -13,7 +13,9 @@ #![allow(dead_code)] -pub trait Integral { +use std::marker::MarkerTrait; + +pub trait Integral : MarkerTrait { type Opposite; } @@ -27,6 +29,8 @@ impl Integral for u32 { pub trait FnLike { type R; + + fn dummy(&self, a: A) -> Self::R { loop { } } } fn foo() diff --git a/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs b/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs index 1d264655bc4..8617750ca53 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds-ufcs.rs @@ -11,15 +11,17 @@ // 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; +use std::marker::PhantomData; + +struct Splits<'a, T:'a, P>(PhantomData<(&'a T, P)>); +struct SplitsN(PhantomData); 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> + fn splitn2<'a, P>(&'a self, n: u32, pred: P) -> SplitsN> where P: FnMut(&Self::Item) -> bool; } @@ -30,7 +32,7 @@ fn split2

(&self, pred: P) -> Splits where P: FnMut(&T) -> bool { loop {} } - fn splitn2

(&self, n: uint, pred: P) -> SplitsN> where P: FnMut(&T) -> bool { + fn splitn2

(&self, n: u32, pred: P) -> SplitsN> where P: FnMut(&T) -> bool { SliceExt2::split2(self, pred); loop {} } diff --git a/src/test/run-pass/associated-types-normalize-in-bounds.rs b/src/test/run-pass/associated-types-normalize-in-bounds.rs index 742bab0578e..94cfcb83653 100644 --- a/src/test/run-pass/associated-types-normalize-in-bounds.rs +++ b/src/test/run-pass/associated-types-normalize-in-bounds.rs @@ -11,15 +11,17 @@ // 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; +use std::marker::PhantomData; + +struct Splits<'a, T, P>(PhantomData<(&'a(),T,P)>); +struct SplitsN(PhantomData); 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> + fn splitn2<'a, P>(&'a self, n: usize, pred: P) -> SplitsN> where P: FnMut(&Self::Item) -> bool; } @@ -30,7 +32,7 @@ fn split2

(&self, pred: P) -> Splits where P: FnMut(&T) -> bool { loop {} } - fn splitn2

(&self, n: uint, pred: P) -> SplitsN> where P: FnMut(&T) -> bool { + fn splitn2

(&self, n: usize, pred: P) -> SplitsN> where P: FnMut(&T) -> bool { self.split2(pred); loop {} } diff --git a/src/test/run-pass/associated-types-normalize-unifield-struct.rs b/src/test/run-pass/associated-types-normalize-unifield-struct.rs index 5aafe93067c..2288e19aae0 100644 --- a/src/test/run-pass/associated-types-normalize-unifield-struct.rs +++ b/src/test/run-pass/associated-types-normalize-unifield-struct.rs @@ -13,7 +13,10 @@ 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; } diff --git a/src/test/run-pass/associated-types-projection-from-known-type-in-impl.rs b/src/test/run-pass/associated-types-projection-from-known-type-in-impl.rs index 0a1a8589dec..c65d2db9b0c 100644 --- a/src/test/run-pass/associated-types-projection-from-known-type-in-impl.rs +++ b/src/test/run-pass/associated-types-projection-from-known-type-in-impl.rs @@ -13,6 +13,8 @@ trait Int { type T; + + fn dummy(&self) { } } trait NonZero diff --git a/src/test/run-pass/associated-types-projection-in-object-type.rs b/src/test/run-pass/associated-types-projection-in-object-type.rs index 44dd49b7297..a9c34a605ce 100644 --- a/src/test/run-pass/associated-types-projection-in-object-type.rs +++ b/src/test/run-pass/associated-types-projection-in-object-type.rs @@ -18,6 +18,8 @@ pub trait Subscriber { type Input; + + fn dummy(&self) { } } pub trait Publisher<'a> { diff --git a/src/test/run-pass/associated-types-projection-in-supertrait.rs b/src/test/run-pass/associated-types-projection-in-supertrait.rs index e6fec675b03..4d2358fae27 100644 --- a/src/test/run-pass/associated-types-projection-in-supertrait.rs +++ b/src/test/run-pass/associated-types-projection-in-supertrait.rs @@ -14,6 +14,8 @@ trait A { type TA; + + fn dummy(&self) { } } trait B diff --git a/src/test/run-pass/associated-types-projection-in-where-clause.rs b/src/test/run-pass/associated-types-projection-in-where-clause.rs index 10a459f3c36..3f3f4fbd1d6 100644 --- a/src/test/run-pass/associated-types-projection-in-where-clause.rs +++ b/src/test/run-pass/associated-types-projection-in-where-clause.rs @@ -13,6 +13,8 @@ trait Int { type T; + + fn dummy(&self) { } } trait NonZero diff --git a/src/test/run-pass/associated-types-ref-in-struct-literal.rs b/src/test/run-pass/associated-types-ref-in-struct-literal.rs index 022c8f4cd01..67fe11d8fed 100644 --- a/src/test/run-pass/associated-types-ref-in-struct-literal.rs +++ b/src/test/run-pass/associated-types-ref-in-struct-literal.rs @@ -12,6 +12,8 @@ pub trait Foo { type Bar; + + fn dummy(&self) { } } impl Foo for int { diff --git a/src/test/run-pass/associated-types-resolve-lifetime.rs b/src/test/run-pass/associated-types-resolve-lifetime.rs index e7a8061a346..a4b0b1a6e03 100644 --- a/src/test/run-pass/associated-types-resolve-lifetime.rs +++ b/src/test/run-pass/associated-types-resolve-lifetime.rs @@ -15,6 +15,8 @@ trait Get { trait Trait<'a> { type T: 'static; type U: Get<&'a int>; + + fn dummy(&'a self) { } } fn main() {} diff --git a/src/test/run-pass/associated-types-struct-field-named.rs b/src/test/run-pass/associated-types-struct-field-named.rs index 1ded34ff3ff..8667f6c8430 100644 --- a/src/test/run-pass/associated-types-struct-field-named.rs +++ b/src/test/run-pass/associated-types-struct-field-named.rs @@ -13,6 +13,8 @@ pub trait UnifyKey { type Value; + + fn dummy(&self) { } } pub struct Node { diff --git a/src/test/run-pass/associated-types-struct-field-numbered.rs b/src/test/run-pass/associated-types-struct-field-numbered.rs index 3669dec4fbd..9503f78a71b 100644 --- a/src/test/run-pass/associated-types-struct-field-numbered.rs +++ b/src/test/run-pass/associated-types-struct-field-numbered.rs @@ -13,6 +13,8 @@ pub trait UnifyKey { type Value; + + fn dummy(&self) { } } pub struct Node(K, K::Value); diff --git a/src/test/run-pass/associated-types-sugar-path.rs b/src/test/run-pass/associated-types-sugar-path.rs index 3b70e941ac5..c068065ac6a 100644 --- a/src/test/run-pass/associated-types-sugar-path.rs +++ b/src/test/run-pass/associated-types-sugar-path.rs @@ -31,8 +31,9 @@ pub fn bar(a: T, x: T::A) -> T::A { // Using a type via an impl. trait C { fn f(); + fn g(&self) { } } -struct B; +struct B(X); impl C for B { fn f() { let x: T::A = panic!(); diff --git a/src/test/run-pass/bitv-perf-test.rs b/src/test/run-pass/bitv-perf-test.rs index b6d428924e3..7bb9f042fe8 100644 --- a/src/test/run-pass/bitv-perf-test.rs +++ b/src/test/run-pass/bitv-perf-test.rs @@ -13,11 +13,11 @@ #![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); } diff --git a/src/test/run-pass/borrowck-trait-lifetime.rs b/src/test/run-pass/borrowck-trait-lifetime.rs index b39f03a93c9..a2b0fa56635 100644 --- a/src/test/run-pass/borrowck-trait-lifetime.rs +++ b/src/test/run-pass/borrowck-trait-lifetime.rs @@ -12,8 +12,11 @@ // 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 diff --git a/src/test/run-pass/bug-7295.rs b/src/test/run-pass/bug-7295.rs index ea711d78dd2..143ebfdabfa 100644 --- a/src/test/run-pass/bug-7295.rs +++ b/src/test/run-pass/bug-7295.rs @@ -9,10 +9,10 @@ // except according to those terms. pub trait Foo { - fn func1(&self, t: U); + fn func1(&self, t: U, w: T); - fn func2(&self, t: U) { - self.func1(t); + fn func2(&self, t: U, w: T) { + self.func1(t, w); } } diff --git a/src/test/run-pass/builtin-superkinds-in-metadata.rs b/src/test/run-pass/builtin-superkinds-in-metadata.rs index c115415bb9b..7eaed910124 100644 --- a/src/test/run-pass/builtin-superkinds-in-metadata.rs +++ b/src/test/run-pass/builtin-superkinds-in-metadata.rs @@ -16,6 +16,7 @@ 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); diff --git a/src/test/run-pass/builtin-superkinds-phantom-typaram.rs b/src/test/run-pass/builtin-superkinds-phantom-typaram.rs index 7e1b2821937..964c28dc945 100644 --- a/src/test/run-pass/builtin-superkinds-phantom-typaram.rs +++ b/src/test/run-pass/builtin-superkinds-phantom-typaram.rs @@ -12,10 +12,12 @@ // 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(()); +struct X { marker: marker::PhantomData } -impl Foo for X { } +impl Foo for X { } pub fn main() { } diff --git a/src/test/run-pass/c-stack-returning-int64.rs b/src/test/run-pass/c-stack-returning-int64.rs index 22c322b86c9..6246ee9c6c4 100644 --- a/src/test/run-pass/c-stack-returning-int64.rs +++ b/src/test/run-pass/c-stack-returning-int64.rs @@ -24,12 +24,12 @@ mod mlibc { } 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 } } diff --git a/src/test/run-pass/class-typarams.rs b/src/test/run-pass/class-typarams.rs index 68457095944..b56a749d33b 100644 --- a/src/test/run-pass/class-typarams.rs +++ b/src/test/run-pass/class-typarams.rs @@ -8,10 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use std::marker::PhantomData; + struct cat { meows : uint, - how_hungry : int, + m: PhantomData } impl cat { @@ -22,7 +24,8 @@ pub fn meow_count(&mut self) -> uint { self.meows } fn cat(in_x : uint, in_y : int) -> cat { cat { meows: in_x, - how_hungry: in_y + how_hungry: in_y, + m: PhantomData } } diff --git a/src/test/run-pass/const-polymorphic-paths.rs b/src/test/run-pass/const-polymorphic-paths.rs index f8f92a56adb..dce12030f79 100644 --- a/src/test/run-pass/const-polymorphic-paths.rs +++ b/src/test/run-pass/const-polymorphic-paths.rs @@ -11,7 +11,7 @@ #![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; @@ -63,8 +63,8 @@ macro_rules! tests { 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:: bool>, fn(uint, fn(uint) -> bool) -> Bitv, (5, odd); + BitVec::from_fn, fn(uint, fn(uint) -> bool) -> BitVec, (5, odd); + BitVec::from_fn:: bool>, fn(uint, fn(uint) -> bool) -> BitVec, (5, odd); // Inherent non-static method. Vec::map_in_place, fn(Vec, fn(u8) -> i8) -> Vec, (vec![b'f', b'o', b'o'], u8_as_i8); @@ -100,8 +100,8 @@ macro_rules! tests { Add::add, fn(i32, i32) -> i32, (5, 6); >::add, fn(i32, i32) -> i32, (5, 6); >::add, fn(i32, i32) -> i32, (5, 6); - >::into_cow, fn(String) -> Cow<'static, String, str>, + >::into_cow, fn(String) -> Cow<'static, str>, ("foo".to_string()); - >::into_cow, fn(String) -> Cow<'static, String, str>, + >::into_cow, fn(String) -> Cow<'static, str>, ("foo".to_string()); } diff --git a/src/test/run-pass/deriving-hash.rs b/src/test/run-pass/deriving-hash.rs index 02ab7e5db5b..5fe7c8bb94b 100644 --- a/src/test/run-pass/deriving-hash.rs +++ b/src/test/run-pass/deriving-hash.rs @@ -17,7 +17,7 @@ struct Person { phone: uint, } -fn hash>(t: &T) -> u64 { +fn hash(t: &T) -> u64 { std::hash::hash::(t) } diff --git a/src/test/run-pass/deriving-meta-multiple.rs b/src/test/run-pass/deriving-meta-multiple.rs index f45dce9da63..62ec2f8e590 100644 --- a/src/test/run-pass/deriving-meta-multiple.rs +++ b/src/test/run-pass/deriving-meta-multiple.rs @@ -20,7 +20,7 @@ struct Foo { baz: int } -fn hash>(_t: &T) {} +fn hash(_t: &T) {} pub fn main() { let a = Foo {bar: 4, baz: -3}; diff --git a/src/test/run-pass/deriving-meta.rs b/src/test/run-pass/deriving-meta.rs index d6a2fad08ed..82cf9db3232 100644 --- a/src/test/run-pass/deriving-meta.rs +++ b/src/test/run-pass/deriving-meta.rs @@ -17,7 +17,7 @@ struct Foo { baz: int } -fn hash>(_t: &T) {} +fn hash(_t: &T) {} pub fn main() { let a = Foo {bar: 4, baz: -3}; diff --git a/src/test/run-pass/dst-coercions.rs b/src/test/run-pass/dst-coercions.rs index dbad546ce1a..30ed0b8e402 100644 --- a/src/test/run-pass/dst-coercions.rs +++ b/src/test/run-pass/dst-coercions.rs @@ -11,7 +11,7 @@ // Test coercions involving DST and/or raw pointers struct S; -trait T {} +trait T { fn dummy(&self) { } } impl T for S {} pub fn main() { diff --git a/src/test/run-pass/enum-null-pointer-opt.rs b/src/test/run-pass/enum-null-pointer-opt.rs index 797c26556aa..023376ce473 100644 --- a/src/test/run-pass/enum-null-pointer-opt.rs +++ b/src/test/run-pass/enum-null-pointer-opt.rs @@ -16,7 +16,7 @@ use std::rc::Rc; use std::sync::Arc; -trait Trait {} +trait Trait { fn dummy(&self) { } } fn main() { // Functions diff --git a/src/test/run-pass/explicit-self-generic.rs b/src/test/run-pass/explicit-self-generic.rs index 066a5f9580a..382c5c58e92 100644 --- a/src/test/run-pass/explicit-self-generic.rs +++ b/src/test/run-pass/explicit-self-generic.rs @@ -15,21 +15,19 @@ struct LM { resize_at: uint, size: uint } enum HashMap { - HashMap_(LM) + HashMap_(LM, Vec<(K,V)>) } -impl Copy for HashMap {} - fn linear_map() -> HashMap { HashMap::HashMap_(LM{ resize_at: 32, - size: 0}) + size: 0}, Vec::new()) } impl HashMap { pub fn len(&mut self) -> uint { match *self { - HashMap::HashMap_(l) => l.size + HashMap::HashMap_(ref l, _) => l.size } } } diff --git a/src/test/run-pass/export-non-interference.rs b/src/test/run-pass/export-non-interference.rs deleted file mode 100644 index 94652e30fe6..00000000000 --- a/src/test/run-pass/export-non-interference.rs +++ /dev/null @@ -1,14 +0,0 @@ -// 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 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - - -enum list_cell { cons(Box>), nil } - -pub fn main() { } diff --git a/src/test/run-pass/foreign-fn-linkname.rs b/src/test/run-pass/foreign-fn-linkname.rs index 592ab7d0e6e..24b711328a1 100644 --- a/src/test/run-pass/foreign-fn-linkname.rs +++ b/src/test/run-pass/foreign-fn-linkname.rs @@ -24,7 +24,7 @@ mod mlibc { 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 } diff --git a/src/test/run-pass/generic-default-type-params-cross-crate.rs b/src/test/run-pass/generic-default-type-params-cross-crate.rs index ed8c6e73255..bf02b82d1a0 100644 --- a/src/test/run-pass/generic-default-type-params-cross-crate.rs +++ b/src/test/run-pass/generic-default-type-params-cross-crate.rs @@ -12,13 +12,13 @@ extern crate default_type_params_xc; -struct Vec; +struct Vec(Option<(T,A)>); struct Foo; fn main() { - let _a = Vec::; - let _b = Vec::; - let _c = default_type_params_xc::FakeVec::; - let _d = default_type_params_xc::FakeVec::; + let _a = Vec::(None); + let _b = Vec::(None); + let _c = default_type_params_xc::FakeVec:: { f: None }; + let _d = default_type_params_xc::FakeVec:: { f: None }; } diff --git a/src/test/run-pass/hrtb-opt-in-copy.rs b/src/test/run-pass/hrtb-opt-in-copy.rs index 9c9f95f61e9..7b16bb867e7 100644 --- a/src/test/run-pass/hrtb-opt-in-copy.rs +++ b/src/test/run-pass/hrtb-opt-in-copy.rs @@ -18,7 +18,7 @@ #![allow(dead_code)] -use std::marker; +use std::marker::PhantomData; #[derive(Copy)] struct Foo { x: T } @@ -26,7 +26,7 @@ struct Foo { x: T } type Ty<'tcx> = &'tcx TyS<'tcx>; enum TyS<'tcx> { - Boop(marker::InvariantLifetime<'tcx>) + Boop(PhantomData<*mut &'tcx ()>) } #[derive(Copy)] diff --git a/src/test/run-pass/inner-static.rs b/src/test/run-pass/inner-static.rs index f9b430c1553..e4026a8fd01 100644 --- a/src/test/run-pass/inner-static.rs +++ b/src/test/run-pass/inner-static.rs @@ -13,9 +13,9 @@ 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); diff --git a/src/test/run-pass/issue-10456.rs b/src/test/run-pass/issue-10456.rs index b714d87f4ef..da73c4b27ac 100644 --- a/src/test/run-pass/issue-10456.rs +++ b/src/test/run-pass/issue-10456.rs @@ -14,7 +14,9 @@ pub trait Bar { fn bar(&self); } -pub trait Baz {} +pub trait Baz { + fn baz(&self) { } +} impl Bar for T { fn bar(&self) {} diff --git a/src/test/run-pass/issue-10802.rs b/src/test/run-pass/issue-10802.rs index de2b4c51e52..174a69e1135 100644 --- a/src/test/run-pass/issue-10802.rs +++ b/src/test/run-pass/issue-10802.rs @@ -29,7 +29,7 @@ fn drop(&mut self) { } } -trait MyTrait { } +trait MyTrait { fn dummy(&self) { } } impl MyTrait for Box {} impl MyTrait for Box {} diff --git a/src/test/run-pass/issue-10902.rs b/src/test/run-pass/issue-10902.rs index 324a1701b2f..7fab6662ee0 100644 --- a/src/test/run-pass/issue-10902.rs +++ b/src/test/run-pass/issue-10902.rs @@ -9,7 +9,7 @@ // 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) @@ -17,7 +17,7 @@ pub fn f<'a>(car: &'a T, cdr: &'a T) -> P<'a> { } 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 } diff --git a/src/test/run-pass/issue-11205.rs b/src/test/run-pass/issue-11205.rs index d7c6c1b1bb2..1325b51a54f 100644 --- a/src/test/run-pass/issue-11205.rs +++ b/src/test/run-pass/issue-11205.rs @@ -12,7 +12,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -trait Foo {} +trait Foo { fn dummy(&self) { } } impl Foo for int {} fn foo(_: [&Foo; 2]) {} fn foos(_: &[&Foo]) {} diff --git a/src/test/run-pass/issue-11384.rs b/src/test/run-pass/issue-11384.rs index a511149b05e..26634fabf5a 100644 --- a/src/test/run-pass/issue-11384.rs +++ b/src/test/run-pass/issue-11384.rs @@ -8,7 +8,7 @@ // 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) {} diff --git a/src/test/run-pass/issue-11612.rs b/src/test/run-pass/issue-11612.rs index fa25d25df05..3c69377b375 100644 --- a/src/test/run-pass/issue-11612.rs +++ b/src/test/run-pass/issue-11612.rs @@ -12,7 +12,7 @@ // 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 diff --git a/src/test/run-pass/issue-11677.rs b/src/test/run-pass/issue-11677.rs index 6fa45058694..7cccac4483d 100644 --- a/src/test/run-pass/issue-11677.rs +++ b/src/test/run-pass/issue-11677.rs @@ -14,13 +14,18 @@ // this code used to cause an ICE -trait X {} +use std::marker; + +trait X { + fn dummy(&self) -> T { panic!() } +} struct S {f: Box+'static>, g: Box+'static>} struct F; -impl X for F {} +impl X for F { +} fn main() { S {f: box F, g: box F}; diff --git a/src/test/run-pass/issue-11736.rs b/src/test/run-pass/issue-11736.rs index d9bae6886fa..b901e95ff55 100644 --- a/src/test/run-pass/issue-11736.rs +++ b/src/test/run-pass/issue-11736.rs @@ -10,13 +10,13 @@ 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] { diff --git a/src/test/run-pass/issue-13105.rs b/src/test/run-pass/issue-13105.rs index 7fab36bd64e..64807dc44e0 100644 --- a/src/test/run-pass/issue-13105.rs +++ b/src/test/run-pass/issue-13105.rs @@ -8,7 +8,9 @@ // 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) {} } diff --git a/src/test/run-pass/issue-14399.rs b/src/test/run-pass/issue-14399.rs index 7e533c2cf86..db7eacce9d1 100644 --- a/src/test/run-pass/issue-14399.rs +++ b/src/test/run-pass/issue-14399.rs @@ -19,7 +19,7 @@ #[derive(Clone)] struct B1; -trait A {} +trait A { fn foo(&self) {} } impl A for B1 {} fn main() { diff --git a/src/test/run-pass/issue-14589.rs b/src/test/run-pass/issue-14589.rs index d9763baa826..71d88ee6215 100644 --- a/src/test/run-pass/issue-14589.rs +++ b/src/test/run-pass/issue-14589.rs @@ -17,17 +17,18 @@ fn main() { send::>(box Output(0)); Test::>::foo(box Output(0)); - Test::>.send(box Output(0)); + Test::>::new().send(box Output(0)); } fn send(_: T) {} -struct Test; +struct Test { marker: std::marker::PhantomData } impl Test { + fn new() -> Test { 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 {} diff --git a/src/test/run-pass/issue-14958.rs b/src/test/run-pass/issue-14958.rs index 814a743648d..6335f79be6c 100644 --- a/src/test/run-pass/issue-14958.rs +++ b/src/test/run-pass/issue-14958.rs @@ -10,7 +10,7 @@ #![feature(unboxed_closures)] -trait Foo {} +trait Foo { fn dummy(&self) { }} struct Bar; diff --git a/src/test/run-pass/issue-14959.rs b/src/test/run-pass/issue-14959.rs index 33281d7d78f..53d0f7dae05 100644 --- a/src/test/run-pass/issue-14959.rs +++ b/src/test/run-pass/issue-14959.rs @@ -12,8 +12,8 @@ use std::ops::Fn; -trait Response {} -trait Request {} +trait Response { fn dummy(&self) { } } +trait Request { fn dummy(&self) { } } trait Ingot { fn enter(&mut self, _: &mut R, _: &mut S, a: &mut Alloy) -> Status; } @@ -21,7 +21,7 @@ trait Ingot { #[allow(dead_code)] struct HelloWorld; -struct SendFile<'a>; +struct SendFile; struct Alloy; enum Status { Continue @@ -33,7 +33,7 @@ fn find(&self) -> Option { } } -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),)) {} diff --git a/src/test/run-pass/issue-15858.rs b/src/test/run-pass/issue-15858.rs index c75c6725461..6a4f78442d1 100644 --- a/src/test/run-pass/issue-15858.rs +++ b/src/test/run-pass/issue-15858.rs @@ -12,21 +12,21 @@ 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; +struct Foo(B); #[unsafe_destructor] -impl<'b, B: Bar<'b>> Drop for Foo { +impl Drop for Foo { fn drop(&mut self) { unsafe { DROP_RAN = true; @@ -37,7 +37,7 @@ fn drop(&mut self) { fn main() { { - let _x: Foo = Foo; + let _x: Foo = Foo(BarImpl); } unsafe { assert_eq!(DROP_RAN, true); diff --git a/src/test/run-pass/issue-16596.rs b/src/test/run-pass/issue-16596.rs index e01de3a3262..1ba7b142e5e 100644 --- a/src/test/run-pass/issue-16596.rs +++ b/src/test/run-pass/issue-16596.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait MatrixRow {} +trait MatrixRow { fn dummy(&self) { }} struct Mat; diff --git a/src/test/run-pass/issue-16643.rs b/src/test/run-pass/issue-16643.rs index b118c9573cd..4e57c55c5f7 100644 --- a/src/test/run-pass/issue-16643.rs +++ b/src/test/run-pass/issue-16643.rs @@ -13,5 +13,5 @@ extern crate "issue-16643" as i; pub fn main() { - i::TreeBuilder::.process_token(); + i::TreeBuilder { h: 3u }.process_token(); } diff --git a/src/test/run-pass/issue-17662.rs b/src/test/run-pass/issue-17662.rs index 45e70f59f33..7bd41cc5b52 100644 --- a/src/test/run-pass/issue-17662.rs +++ b/src/test/run-pass/issue-17662.rs @@ -12,12 +12,14 @@ 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); } diff --git a/src/test/run-pass/issue-17732.rs b/src/test/run-pass/issue-17732.rs index b4bd55da597..de9611f2592 100644 --- a/src/test/run-pass/issue-17732.rs +++ b/src/test/run-pass/issue-17732.rs @@ -10,8 +10,9 @@ trait Person { type string; + fn dummy(&self) { } } -struct Someone; +struct Someone(std::marker::PhantomData

); fn main() {} diff --git a/src/test/run-pass/issue-17771.rs b/src/test/run-pass/issue-17771.rs index 1e9550acef4..2f1b0342b8e 100644 --- a/src/test/run-pass/issue-17771.rs +++ b/src/test/run-pass/issue-17771.rs @@ -8,7 +8,7 @@ // 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) {} diff --git a/src/test/run-pass/issue-17816.rs b/src/test/run-pass/issue-17816.rs index f8fbd680dcb..a976eccf89e 100644 --- a/src/test/run-pass/issue-17816.rs +++ b/src/test/run-pass/issue-17816.rs @@ -10,9 +10,11 @@ #![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![]); } diff --git a/src/test/run-pass/issue-17904.rs b/src/test/run-pass/issue-17904.rs index 3ce347d67e3..58a0872a571 100644 --- a/src/test/run-pass/issue-17904.rs +++ b/src/test/run-pass/issue-17904.rs @@ -8,7 +8,9 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Foo where T: Copy; +// Test that we can parse where clauses on various forms of tuple +// structs. + struct Bar(T) where T: Copy; struct Bleh(T, U) where T: Copy, U: Sized; struct Baz where T: Copy { diff --git a/src/test/run-pass/issue-18232.rs b/src/test/run-pass/issue-18232.rs index 15cf5870d40..67b3239d351 100644 --- a/src/test/run-pass/issue-18232.rs +++ b/src/test/run-pass/issue-18232.rs @@ -8,7 +8,7 @@ // 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; @@ -23,7 +23,7 @@ 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); } diff --git a/src/test/run-pass/issue-18906.rs b/src/test/run-pass/issue-18906.rs index 11ffb4198da..16dd84315ed 100644 --- a/src/test/run-pass/issue-18906.rs +++ b/src/test/run-pass/issue-18906.rs @@ -24,7 +24,7 @@ fn bar(k: &K, q: &Q) where K: Borrow, Q: Foo { q.foo(k.borrow()) } -struct MyTree; +struct MyTree(K); impl MyTree { // This caused a failure in #18906 diff --git a/src/test/run-pass/issue-19121.rs b/src/test/run-pass/issue-19121.rs index d95f74ef2a2..222f67af437 100644 --- a/src/test/run-pass/issue-19121.rs +++ b/src/test/run-pass/issue-19121.rs @@ -13,6 +13,8 @@ trait Foo { type A; + + fn dummy(&self) { } } fn bar(x: &Foo) {} diff --git a/src/test/run-pass/issue-19129-2.rs b/src/test/run-pass/issue-19129-2.rs index d6b3a1908b8..cf0f48e025a 100644 --- a/src/test/run-pass/issue-19129-2.rs +++ b/src/test/run-pass/issue-19129-2.rs @@ -11,7 +11,7 @@ trait Trait { type Output; - fn method() -> bool { false } + fn method(&self, i: Input) -> bool { false } } fn main() {} diff --git a/src/test/run-pass/issue-19135.rs b/src/test/run-pass/issue-19135.rs index 031a63ba474..5e6dd567d63 100644 --- a/src/test/run-pass/issue-19135.rs +++ b/src/test/run-pass/issue-19135.rs @@ -10,13 +10,15 @@ #![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_closureFnMut(LifetimeStruct<'a>)>(mut f: F) { - f(LifetimeStruct); + f(LifetimeStruct(PhantomData)); } diff --git a/src/test/run-pass/issue-19358.rs b/src/test/run-pass/issue-19358.rs index ff657376ecc..8b5269ab92f 100644 --- a/src/test/run-pass/issue-19358.rs +++ b/src/test/run-pass/issue-19358.rs @@ -8,7 +8,7 @@ // 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 { diff --git a/src/test/run-pass/issue-19398.rs b/src/test/run-pass/issue-19398.rs index 1196162568a..e603167b26b 100644 --- a/src/test/run-pass/issue-19398.rs +++ b/src/test/run-pass/issue-19398.rs @@ -9,11 +9,11 @@ // 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() {} diff --git a/src/test/run-pass/issue-19479.rs b/src/test/run-pass/issue-19479.rs index 91bc645b2d4..38a7af3a695 100644 --- a/src/test/run-pass/issue-19479.rs +++ b/src/test/run-pass/issue-19479.rs @@ -8,12 +8,16 @@ // 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 AssocB for T { type Y = ::X; diff --git a/src/test/run-pass/issue-19631.rs b/src/test/run-pass/issue-19631.rs index 43116f63641..7bb0d055b84 100644 --- a/src/test/run-pass/issue-19631.rs +++ b/src/test/run-pass/issue-19631.rs @@ -10,6 +10,7 @@ trait PoolManager { type C; + fn dummy(&self) { } } struct InnerPool { diff --git a/src/test/run-pass/issue-19632.rs b/src/test/run-pass/issue-19632.rs index 01a073a6889..4339339d74c 100644 --- a/src/test/run-pass/issue-19632.rs +++ b/src/test/run-pass/issue-19632.rs @@ -10,6 +10,7 @@ trait PoolManager { type C; + fn dummy(&self) { } } struct InnerPool { diff --git a/src/test/run-pass/issue-20055-box-trait.rs b/src/test/run-pass/issue-20055-box-trait.rs index 836e78b5b51..572a0d82528 100644 --- a/src/test/run-pass/issue-20055-box-trait.rs +++ b/src/test/run-pass/issue-20055-box-trait.rs @@ -16,7 +16,9 @@ // 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] { } diff --git a/src/test/run-pass/issue-20343.rs b/src/test/run-pass/issue-20343.rs index 79034a4a4a6..2f9e8feed24 100644 --- a/src/test/run-pass/issue-20343.rs +++ b/src/test/run-pass/issue-20343.rs @@ -16,7 +16,7 @@ struct B { b: u32 } struct C; struct D; -trait T {} +trait T { fn dummy(&self, a: A) { } } impl T for () {} impl B { diff --git a/src/test/run-pass/issue-20763-1.rs b/src/test/run-pass/issue-20763-1.rs index 911ee715da2..97c06ac9826 100644 --- a/src/test/run-pass/issue-20763-1.rs +++ b/src/test/run-pass/issue-20763-1.rs @@ -8,7 +8,10 @@ // 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); impl T0 for S { type O = A; } diff --git a/src/test/run-pass/issue-20763-2.rs b/src/test/run-pass/issue-20763-2.rs index a17c7b6ade4..d9701763571 100644 --- a/src/test/run-pass/issue-20763-2.rs +++ b/src/test/run-pass/issue-20763-2.rs @@ -8,7 +8,10 @@ // 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); impl T0 for S { type O = A; } diff --git a/src/test/run-pass/issue-21363.rs b/src/test/run-pass/issue-21363.rs index 2fc1d9fd643..71bb3d39fe1 100644 --- a/src/test/run-pass/issue-21363.rs +++ b/src/test/run-pass/issue-21363.rs @@ -12,6 +12,7 @@ trait Iterator { type Item; + fn dummy(&self) { } } impl<'a, T> Iterator for &'a mut (Iterator + 'a) { diff --git a/src/test/run-pass/issue-21909.rs b/src/test/run-pass/issue-21909.rs index 5bbc90b2606..55b61dd1945 100644 --- a/src/test/run-pass/issue-21909.rs +++ b/src/test/run-pass/issue-21909.rs @@ -8,11 +8,15 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait A {} +trait A { + fn dummy(&self, arg: X); +} trait B { type X; type Y: A; + + fn dummy(&self); } fn main () { } diff --git a/src/test/run-pass/issue-2311-2.rs b/src/test/run-pass/issue-2311-2.rs index e0b98ab1965..5529d51b408 100644 --- a/src/test/run-pass/issue-2311-2.rs +++ b/src/test/run-pass/issue-2311-2.rs @@ -8,7 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait clam { } +trait clam { + fn get(self) -> A; +} + struct foo { x: A, } diff --git a/src/test/run-pass/issue-2311.rs b/src/test/run-pass/issue-2311.rs index dc873ed08d7..b6b3114e2a4 100644 --- a/src/test/run-pass/issue-2311.rs +++ b/src/test/run-pass/issue-2311.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait clam { } +trait clam { fn get(self) -> A; } trait foo { fn bar>(&self, c: C) -> B; } diff --git a/src/test/run-pass/issue-2312.rs b/src/test/run-pass/issue-2312.rs index 8c597552d75..3f273b56efd 100644 --- a/src/test/run-pass/issue-2312.rs +++ b/src/test/run-pass/issue-2312.rs @@ -10,7 +10,7 @@ // Testing that the B's are resolved -trait clam { } +trait clam { fn get(self) -> A; } struct foo(int); diff --git a/src/test/run-pass/issue-2383.rs b/src/test/run-pass/issue-2383.rs index b8136323df6..a5a05283f80 100644 --- a/src/test/run-pass/issue-2383.rs +++ b/src/test/run-pass/issue-2383.rs @@ -10,9 +10,9 @@ // 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); } diff --git a/src/test/run-pass/issue-2611-3.rs b/src/test/run-pass/issue-2611-3.rs index 2608c89d155..c005699ce30 100644 --- a/src/test/run-pass/issue-2611-3.rs +++ b/src/test/run-pass/issue-2611-3.rs @@ -12,7 +12,7 @@ // than the traits require. trait A { - fn b(x: C) -> C; + fn b(&self, x: C) -> C; } struct E { @@ -20,7 +20,7 @@ struct E { } impl A for E { - fn b(_x: F) -> F { panic!() } + fn b(&self, _x: F) -> F { panic!() } //~^ ERROR in method `b`, type parameter 0 has 1 bound, but } diff --git a/src/test/run-pass/issue-2734.rs b/src/test/run-pass/issue-2734.rs index 7ca439a1a19..a7b53db6b05 100644 --- a/src/test/run-pass/issue-2734.rs +++ b/src/test/run-pass/issue-2734.rs @@ -11,7 +11,9 @@ #![allow(unknown_features)] #![feature(box_syntax)] -trait hax { } +trait hax { + fn dummy(&self) { } +} impl hax for A { } fn perform_hax(x: Box) -> Box { diff --git a/src/test/run-pass/issue-2735.rs b/src/test/run-pass/issue-2735.rs index 962359537bf..1594b94879c 100644 --- a/src/test/run-pass/issue-2735.rs +++ b/src/test/run-pass/issue-2735.rs @@ -11,7 +11,9 @@ #![allow(unknown_features)] #![feature(box_syntax)] -trait hax { } +trait hax { + fn dummy(&self) { } +} impl hax for A { } fn perform_hax(x: Box) -> Box { diff --git a/src/test/run-pass/issue-4107.rs b/src/test/run-pass/issue-4107.rs index 2ed662e9f2d..d660f300ada 100644 --- a/src/test/run-pass/issue-4107.rs +++ b/src/test/run-pass/issue-4107.rs @@ -9,14 +9,14 @@ // except according to those terms. pub fn main() { - let _id: &Mat2 = &Matrix::identity(); + let _id: &Mat2 = &Matrix::identity(1.0); } -pub trait Index { } +pub trait Index { fn get(&self, Index) -> Result { panic!() } } pub trait Dimensional: Index { } -pub struct Mat2 { x: () } -pub struct Vec2 { x: () } +pub struct Mat2 { x: T } +pub struct Vec2 { x: T } impl Dimensional> for Mat2 { } impl Index> for Mat2 { } @@ -25,9 +25,9 @@ impl Dimensional for Vec2 { } impl Index for Vec2 { } pub trait Matrix: Dimensional { - fn identity() -> Self; + fn identity(t:T) -> Self; } impl Matrix> for Mat2 { - fn identity() -> Mat2 { Mat2{ x: () } } + fn identity(t:T) -> Mat2 { Mat2{ x: t } } } diff --git a/src/test/run-pass/issue-5192.rs b/src/test/run-pass/issue-5192.rs index bb79cd4d046..a6f3771bf62 100644 --- a/src/test/run-pass/issue-5192.rs +++ b/src/test/run-pass/issue-5192.rs @@ -12,6 +12,7 @@ #![feature(box_syntax)] pub trait EventLoop { + fn dummy(&self) { } } pub struct UvEventLoop { diff --git a/src/test/run-pass/issue-5708.rs b/src/test/run-pass/issue-5708.rs index fd39bcc6b61..59bca87bed0 100644 --- a/src/test/run-pass/issue-5708.rs +++ b/src/test/run-pass/issue-5708.rs @@ -48,7 +48,9 @@ pub fn main() { // minimal -pub trait MyTrait { } +pub trait MyTrait { + fn dummy(&self, t: T) -> T { panic!() } +} pub struct MyContainer<'a, T> { foos: Vec<&'a (MyTrait+'a)> , diff --git a/src/test/run-pass/issue-6128.rs b/src/test/run-pass/issue-6128.rs index d96862b588f..1746a6281dc 100644 --- a/src/test/run-pass/issue-6128.rs +++ b/src/test/run-pass/issue-6128.rs @@ -17,6 +17,7 @@ trait Graph { fn f(&self, Edge); + fn g(&self, Node); } @@ -24,6 +25,9 @@ impl Graph for HashMap { fn f(&self, _e: E) { panic!(); } + fn g(&self, _e: int) { + panic!(); + } } pub fn main() { diff --git a/src/test/run-pass/issue-6318.rs b/src/test/run-pass/issue-6318.rs index 1d8fe8bfce8..6e608d34bd5 100644 --- a/src/test/run-pass/issue-6318.rs +++ b/src/test/run-pass/issue-6318.rs @@ -15,7 +15,9 @@ pub enum Thing { A(Box) } -pub trait Foo {} +pub trait Foo { + fn dummy(&self) { } +} pub struct Struct; diff --git a/src/test/run-pass/issue-7575.rs b/src/test/run-pass/issue-7575.rs index 225213db6a4..77cfc7f0cf6 100644 --- a/src/test/run-pass/issue-7575.rs +++ b/src/test/run-pass/issue-7575.rs @@ -10,6 +10,7 @@ trait Foo { fn new() -> bool { false } + fn dummy(&self) { } } trait Bar { diff --git a/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs b/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs index b6dfbb1ca42..736860947f2 100644 --- a/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs +++ b/src/test/run-pass/issue-7673-cast-generically-implemented-trait.rs @@ -19,7 +19,10 @@ pub fn main() {} -trait A {} +trait A { + fn dummy(&self) { } +} + impl A for T {} fn owned2(a: Box) { a as Box; } diff --git a/src/test/run-pass/issue-7911.rs b/src/test/run-pass/issue-7911.rs index 86948ebcb91..3eb593708be 100644 --- a/src/test/run-pass/issue-7911.rs +++ b/src/test/run-pass/issue-7911.rs @@ -14,7 +14,9 @@ // 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 } diff --git a/src/test/run-pass/issue-8248.rs b/src/test/run-pass/issue-8248.rs index 377b9ce262c..7bc8dbe616f 100644 --- a/src/test/run-pass/issue-8248.rs +++ b/src/test/run-pass/issue-8248.rs @@ -8,7 +8,9 @@ // 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 {} diff --git a/src/test/run-pass/issue-8249.rs b/src/test/run-pass/issue-8249.rs index 44f07def531..83c9e9bf450 100644 --- a/src/test/run-pass/issue-8249.rs +++ b/src/test/run-pass/issue-8249.rs @@ -8,7 +8,9 @@ // 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 {} diff --git a/src/test/run-pass/issue-9719.rs b/src/test/run-pass/issue-9719.rs index 8fc86eb49e7..aa1e65efaa4 100644 --- a/src/test/run-pass/issue-9719.rs +++ b/src/test/run-pass/issue-9719.rs @@ -13,7 +13,9 @@ pub enum Enum { A(T), } - pub trait X {} + pub trait X { + fn dummy(&self) { } + } impl X for int {} pub struct Z<'a>(Enum<&'a (X+'a)>); @@ -21,7 +23,9 @@ impl X for int {} } mod b { - trait X {} + trait X { + fn dummy(&self) { } + } impl X for int {} struct Y<'a>{ x:Option<&'a (X+'a)>, diff --git a/src/test/run-pass/lint-cstack.rs b/src/test/run-pass/lint-cstack.rs index 2194453aac2..f180ffcd4e8 100644 --- a/src/test/run-pass/lint-cstack.rs +++ b/src/test/run-pass/lint-cstack.rs @@ -15,7 +15,7 @@ } trait A { - fn foo() { + fn foo(&self) { unsafe { rust_get_test_int(); } diff --git a/src/test/run-pass/method-early-bound-lifetimes-on-self.rs b/src/test/run-pass/method-early-bound-lifetimes-on-self.rs index 25ce0d774eb..cec9753a2fe 100644 --- a/src/test/run-pass/method-early-bound-lifetimes-on-self.rs +++ b/src/test/run-pass/method-early-bound-lifetimes-on-self.rs @@ -13,7 +13,11 @@ #![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; @@ -28,7 +32,7 @@ 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); } diff --git a/src/test/run-pass/method-recursive-blanket-impl.rs b/src/test/run-pass/method-recursive-blanket-impl.rs index 338bd89ab5c..15eb2ae2e4b 100644 --- a/src/test/run-pass/method-recursive-blanket-impl.rs +++ b/src/test/run-pass/method-recursive-blanket-impl.rs @@ -17,16 +17,16 @@ // Note: this must be generic for the problem to show up trait Foo { - fn foo(&self); + fn foo(&self, a: A); } impl Foo for [u8] { - fn foo(&self) {} + fn foo(&self, a: u8) {} } impl<'a, A, T> Foo for &'a T where T: Foo { - fn foo(&self) { - Foo::foo(*self) + fn foo(&self, a: A) { + Foo::foo(*self, a) } } diff --git a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs index eb17aa78bd9..1164ef1a3c9 100644 --- a/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs +++ b/src/test/run-pass/monomorphized-callees-with-ty-params-3314.rs @@ -8,8 +8,9 @@ // 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 { diff --git a/src/test/run-pass/overloaded-autoderef-vtable.rs b/src/test/run-pass/overloaded-autoderef-vtable.rs index be2b309b821..d50f2efe0e7 100644 --- a/src/test/run-pass/overloaded-autoderef-vtable.rs +++ b/src/test/run-pass/overloaded-autoderef-vtable.rs @@ -11,7 +11,8 @@ use std::ops::Deref; struct DerefWithHelper { - helper: H + helper: H, + value: T } trait Helper { @@ -39,6 +40,7 @@ fn foo(&self) -> int {self.x} } pub fn main() { - let x: DerefWithHelper, Foo> = DerefWithHelper { helper: Some(Foo {x: 5}) }; + let x: DerefWithHelper, Foo> = + DerefWithHelper { helper: Some(Foo {x: 5}), value: Foo { x: 2 } }; assert!(x.foo() == 5); } diff --git a/src/test/run-pass/overloaded-calls-param-vtables.rs b/src/test/run-pass/overloaded-calls-param-vtables.rs index 2838909c1be..2ef9e08134c 100644 --- a/src/test/run-pass/overloaded-calls-param-vtables.rs +++ b/src/test/run-pass/overloaded-calls-param-vtables.rs @@ -12,10 +12,11 @@ #![feature(unboxed_closures)] +use std::marker::PhantomData; use std::ops::Fn; use std::ops::Add; -struct G; +struct G(PhantomData); impl<'a, A: Add> Fn<(A,)> for G { type Output = i32; @@ -27,5 +28,5 @@ extern "rust-call" fn call(&self, (arg,): (A,)) -> i32 { fn main() { // ICE trigger - G(1_i32); + (G(PhantomData))(1_i32); } diff --git a/src/test/run-pass/parameterized-trait-with-bounds.rs b/src/test/run-pass/parameterized-trait-with-bounds.rs index 840e58848a7..061c9168955 100644 --- a/src/test/run-pass/parameterized-trait-with-bounds.rs +++ b/src/test/run-pass/parameterized-trait-with-bounds.rs @@ -11,12 +11,12 @@ #![allow(dead_code)] -trait A {} -trait B {} -trait C<'a, U> {} +trait A { fn get(self) -> T; } +trait B { 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(_: &(A + Send)) {} diff --git a/src/test/run-pass/privacy-ns.rs b/src/test/run-pass/privacy-ns.rs index f3380352f5f..e9b8e694d60 100644 --- a/src/test/run-pass/privacy-ns.rs +++ b/src/test/run-pass/privacy-ns.rs @@ -19,6 +19,7 @@ // public type, private value pub mod foo1 { pub trait Bar { + fn dummy(&self) { } } pub struct Baz; @@ -50,6 +51,7 @@ fn test_glob1() { // private type, public value pub mod foo2 { trait Bar { + fn dummy(&self) { } } pub struct Baz; @@ -81,6 +83,7 @@ fn test_glob2() { // public type, public value pub mod foo3 { pub trait Bar { + fn dummy(&self) { } } pub struct Baz; diff --git a/src/test/run-pass/regions-assoc-type-static-bound.rs b/src/test/run-pass/regions-assoc-type-static-bound.rs index 6b629a9035d..80ae371e509 100644 --- a/src/test/run-pass/regions-assoc-type-static-bound.rs +++ b/src/test/run-pass/regions-assoc-type-static-bound.rs @@ -11,7 +11,10 @@ // 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() {} diff --git a/src/test/run-pass/regions-bound-lists-feature-gate-2.rs b/src/test/run-pass/regions-bound-lists-feature-gate-2.rs index 0a95a89d57c..a06e0f6da78 100644 --- a/src/test/run-pass/regions-bound-lists-feature-gate-2.rs +++ b/src/test/run-pass/regions-bound-lists-feature-gate-2.rs @@ -12,7 +12,9 @@ #![feature(issue_5723_bootstrap)] -trait Foo { } +trait Foo { + fn dummy(&self) { } +} fn foo<'a, 'b, 'c:'a+'b, 'd>() { } diff --git a/src/test/run-pass/regions-bound-lists-feature-gate.rs b/src/test/run-pass/regions-bound-lists-feature-gate.rs index c5baecf7272..996583dc6de 100644 --- a/src/test/run-pass/regions-bound-lists-feature-gate.rs +++ b/src/test/run-pass/regions-bound-lists-feature-gate.rs @@ -12,8 +12,9 @@ #![feature(issue_5723_bootstrap)] - -trait Foo { } +trait Foo { + fn dummy(&self) { } +} fn foo<'a>(x: Box) { } diff --git a/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs b/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs index 978383c2447..bdc0d41c94e 100644 --- a/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs +++ b/src/test/run-pass/regions-early-bound-lifetime-in-assoc-fn.rs @@ -14,6 +14,8 @@ // lifetime parameters must be early bound in the type of the // associated item. +use std::marker; + pub enum Value<'v> { A(&'v str), B, @@ -23,7 +25,9 @@ pub trait Decoder<'v> { 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; } diff --git a/src/test/run-pass/regions-early-bound-trait-param.rs b/src/test/run-pass/regions-early-bound-trait-param.rs index 6fcfaf58a02..3f434a4838d 100644 --- a/src/test/run-pass/regions-early-bound-trait-param.rs +++ b/src/test/run-pass/regions-early-bound-trait-param.rs @@ -53,11 +53,11 @@ fn field_invoke2<'l, 'm, 'n>(x: &'n Struct2<'l,'m>) -> int { x.f.short() } -trait MakerTrait<'o> { +trait MakerTrait { fn mk() -> Self; } -fn make_val<'p, T:MakerTrait<'p>>() -> T { +fn make_val() -> T { MakerTrait::mk() } @@ -80,7 +80,7 @@ fn short<'b>(&'b self) -> int { } } -impl<'t> MakerTrait<'t> for Box+'static> { +impl<'t> MakerTrait for Box+'static> { fn mk() -> Box+'static> { box() (4,5) as Box } } diff --git a/src/test/run-pass/regions-infer-bivariance.rs b/src/test/run-pass/regions-infer-bivariance.rs deleted file mode 100644 index a3288e2e1b9..00000000000 --- a/src/test/run-pass/regions-infer-bivariance.rs +++ /dev/null @@ -1,28 +0,0 @@ -// 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 or the MIT license -// , 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() {} diff --git a/src/test/run-pass/regions-issue-21422.rs b/src/test/run-pass/regions-issue-21422.rs new file mode 100644 index 00000000000..c59bf15afc3 --- /dev/null +++ b/src/test/run-pass/regions-issue-21422.rs @@ -0,0 +1,25 @@ +// 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 or the MIT license +// , 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() {} diff --git a/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs b/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs index d3464f01203..5964ac65d5f 100644 --- a/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs +++ b/src/test/run-pass/regions-no-bound-in-argument-cleanup.rs @@ -10,7 +10,9 @@ #![feature(unsafe_destructor)] -pub struct Foo; +use std::marker; + +pub struct Foo(marker::PhantomData); impl Iterator for Foo { type Item = T; diff --git a/src/test/run-pass/regions-no-variance-from-fn-generics.rs b/src/test/run-pass/regions-no-variance-from-fn-generics.rs index a35ab1bfc0c..80c478afa64 100644 --- a/src/test/run-pass/regions-no-variance-from-fn-generics.rs +++ b/src/test/run-pass/regions-no-variance-from-fn-generics.rs @@ -12,7 +12,9 @@ // 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; @@ -23,7 +25,11 @@ trait UseLife02 { } -pub trait HasType { } +pub trait HasType +{ + fn dummy(&self, t: T) -> T { panic!() } +} + trait UseLife03 { fn refs<'a, H: HasType<&'a T>>(&'a self) -> H; diff --git a/src/test/run-pass/regions-refcell.rs b/src/test/run-pass/regions-refcell.rs index 10c9aef7c3b..a224017780e 100644 --- a/src/test/run-pass/regions-refcell.rs +++ b/src/test/run-pass/regions-refcell.rs @@ -19,7 +19,7 @@ #[cfg(cannot_use_this_yet)] fn foo<'a>(map: RefCell>) { 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)] @@ -45,9 +45,9 @@ fn main() { 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); } diff --git a/src/test/run-pass/rename-directory.rs b/src/test/run-pass/rename-directory.rs index a21b5aa1dab..abe6ffe7d4c 100644 --- a/src/test/run-pass/rename-directory.rs +++ b/src/test/run-pass/rename-directory.rs @@ -31,12 +31,12 @@ fn rename_directory() { 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, diff --git a/src/test/run-pass/self-impl.rs b/src/test/run-pass/self-impl.rs index 40a4dc52a70..af2b2de8ab8 100644 --- a/src/test/run-pass/self-impl.rs +++ b/src/test/run-pass/self-impl.rs @@ -29,6 +29,7 @@ pub struct Baz { trait Bar { fn bar(x: Self, y: &Self, z: Box) -> Self; + fn dummy(&self, x: X) { } } impl Bar for Box> { diff --git a/src/test/run-pass/send_str_hashmap.rs b/src/test/run-pass/send_str_hashmap.rs index c58654670d1..33e4fa85bcb 100644 --- a/src/test/run-pass/send_str_hashmap.rs +++ b/src/test/run-pass/send_str_hashmap.rs @@ -13,7 +13,7 @@ use std::collections::HashMap; use std::borrow::{Cow, IntoCow}; -type SendStr = Cow<'static, String, str>; +type SendStr = Cow<'static, str>; pub fn main() { let mut map: HashMap = HashMap::new(); diff --git a/src/test/run-pass/send_str_treemap.rs b/src/test/run-pass/send_str_treemap.rs index 438724a2b06..3390369242d 100644 --- a/src/test/run-pass/send_str_treemap.rs +++ b/src/test/run-pass/send_str_treemap.rs @@ -13,7 +13,7 @@ use self::collections::BTreeMap; use std::borrow::{Cow, IntoCow}; -type SendStr = Cow<'static, String, str>; +type SendStr = Cow<'static, str>; pub fn main() { let mut map: BTreeMap = BTreeMap::new(); diff --git a/src/test/run-pass/simple-match-generic-tag.rs b/src/test/run-pass/simple-match-generic-tag.rs index 7ed8cb434ca..2217dddbd21 100644 --- a/src/test/run-pass/simple-match-generic-tag.rs +++ b/src/test/run-pass/simple-match-generic-tag.rs @@ -8,11 +8,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. - - -enum opt { none, } +enum opt { none, some(T) } pub fn main() { let x = opt::none::; - match x { opt::none:: => { println!("hello world"); } } + match x { + opt::none:: => { println!("hello world"); } + opt::some(_) => { } + } } diff --git a/src/test/run-pass/syntax-trait-polarity.rs b/src/test/run-pass/syntax-trait-polarity.rs index 3344844d49f..340ad2a531a 100644 --- a/src/test/run-pass/syntax-trait-polarity.rs +++ b/src/test/run-pass/syntax-trait-polarity.rs @@ -10,17 +10,17 @@ #![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; +struct TestType2(T); impl TestType2 {} diff --git a/src/test/run-pass/trailing-comma.rs b/src/test/run-pass/trailing-comma.rs index b5ae259bc63..76c62a83e75 100644 --- a/src/test/run-pass/trailing-comma.rs +++ b/src/test/run-pass/trailing-comma.rs @@ -12,7 +12,7 @@ fn f(_: T,) {} -struct Foo; +struct Foo(T); struct Bar; @@ -34,7 +34,7 @@ pub fn main() { let [_, _, .., _,] = [1, 1, 1, 1,]; let [_, _, _.., _,] = [1, 1, 1, 1,]; - let x: Foo = Foo::; + let x: Foo = Foo::(1); Bar::f(0,); Bar.g(0,); diff --git a/src/test/run-pass/trait-bounds-basic.rs b/src/test/run-pass/trait-bounds-basic.rs index d03496403ad..ed25bf8b02e 100644 --- a/src/test/run-pass/trait-bounds-basic.rs +++ b/src/test/run-pass/trait-bounds-basic.rs @@ -9,7 +9,7 @@ // except according to those terms. -trait Foo { +trait Foo : ::std::marker::MarkerTrait { } fn b(_x: Box) { diff --git a/src/test/run-pass/trait-bounds-on-structs-and-enums.rs b/src/test/run-pass/trait-bounds-on-structs-and-enums.rs index e3234f03754..976120908b2 100644 --- a/src/test/run-pass/trait-bounds-on-structs-and-enums.rs +++ b/src/test/run-pass/trait-bounds-on-structs-and-enums.rs @@ -8,10 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait U {} -trait T {} +trait U : ::std::marker::MarkerTrait {} +trait T { fn get(self) -> X; } -trait S2 { +trait S2 : ::std::marker::MarkerTrait { fn m(x: Box+'static>) {} } diff --git a/src/test/run-pass/trait-bounds-recursion.rs b/src/test/run-pass/trait-bounds-recursion.rs index 49f8999cd45..7135dad7d19 100644 --- a/src/test/run-pass/trait-bounds-recursion.rs +++ b/src/test/run-pass/trait-bounds-recursion.rs @@ -10,17 +10,17 @@ trait I { fn i(&self) -> Self; } -trait A { +trait A : ::std::marker::MarkerTrait { fn id(x:T) -> T { x.i() } } -trait J { fn j(&self) -> Self; } +trait J { fn j(&self) -> T; } -trait B> { +trait B> : ::std::marker::MarkerTrait { fn id(x:T) -> T { x.j() } } -trait C { +trait C : ::std::marker::MarkerTrait { fn id>(x:T) -> T { x.j() } } diff --git a/src/test/run-pass/trait-default-method-bound-subst4.rs b/src/test/run-pass/trait-default-method-bound-subst4.rs index 3efe2507470..383849ca512 100644 --- a/src/test/run-pass/trait-default-method-bound-subst4.rs +++ b/src/test/run-pass/trait-default-method-bound-subst4.rs @@ -11,6 +11,7 @@ trait A { fn g(&self, x: uint) -> uint { x } + fn h(&self, x: T) { } } impl A for int { } diff --git a/src/test/run-pass/trait-impl.rs b/src/test/run-pass/trait-impl.rs index 16ef315c206..325fba8a0ee 100644 --- a/src/test/run-pass/trait-impl.rs +++ b/src/test/run-pass/trait-impl.rs @@ -16,7 +16,9 @@ static mut COUNT: uint = 1; -trait T {} +trait T { + fn t(&self) {} +} impl<'a> T+'a { fn foo(&self) { diff --git a/src/test/run-pass/trait-inheritance-num2.rs b/src/test/run-pass/trait-inheritance-num2.rs index 1e6e7227a06..f89eea46090 100644 --- a/src/test/run-pass/trait-inheritance-num2.rs +++ b/src/test/run-pass/trait-inheritance-num2.rs @@ -14,8 +14,7 @@ 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 {} diff --git a/src/test/run-pass/trait-inheritance-static2.rs b/src/test/run-pass/trait-inheritance-static2.rs index 3b454aad03e..8f3b325a513 100644 --- a/src/test/run-pass/trait-inheritance-static2.rs +++ b/src/test/run-pass/trait-inheritance-static2.rs @@ -8,9 +8,9 @@ // 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; } diff --git a/src/test/run-pass/trait-object-generics.rs b/src/test/run-pass/trait-object-generics.rs index 76352c799a0..6f89490716f 100644 --- a/src/test/run-pass/trait-object-generics.rs +++ b/src/test/run-pass/trait-object-generics.rs @@ -13,11 +13,14 @@ #![allow(unknown_features)] #![feature(box_syntax)] +use std::marker; + pub trait Trait2 { - fn doit(&self); + fn doit(&self) -> A; } pub struct Impl { + m1: marker::PhantomData<(A1,A2,A3)>, /* * With A2 we get the ICE: * task failed at 'index out of bounds: the len is 1 but the index is 1', @@ -28,13 +31,13 @@ pub struct Impl { impl Impl { pub fn step(&self) { - self.t.doit() + self.t.doit(); } } // test for #8601 -enum Type { Constant } +enum Type { Constant(T) } trait Trait { fn method(&self,Type<(K,V)>) -> int; @@ -46,5 +49,5 @@ fn method(&self, _x: Type<(u8,V)>) -> int { 0 } pub fn main() { let a = box() () as Box>; - assert_eq!(a.method(Type::Constant), 0); + assert_eq!(a.method(Type::Constant((1u8, 2u8))), 0); } diff --git a/src/test/run-pass/trait-static-method-overwriting.rs b/src/test/run-pass/trait-static-method-overwriting.rs index a8cea24db0c..10439d5c86a 100644 --- a/src/test/run-pass/trait-static-method-overwriting.rs +++ b/src/test/run-pass/trait-static-method-overwriting.rs @@ -10,7 +10,7 @@ // except according to those terms. mod base { - pub trait HasNew { + pub trait HasNew { fn new() -> Self; } @@ -18,7 +18,7 @@ pub struct Foo { dummy: (), } - impl ::base::HasNew for Foo { + impl ::base::HasNew for Foo { fn new() -> Foo { println!("Foo"); Foo { dummy: () } @@ -29,7 +29,7 @@ pub struct Bar { dummy: (), } - impl ::base::HasNew for Bar { + impl ::base::HasNew for Bar { fn new() -> Bar { println!("Bar"); Bar { dummy: () } @@ -38,6 +38,6 @@ fn new() -> Bar { } pub fn main() { - let _f: base::Foo = base::HasNew::::new(); - let _b: base::Bar = base::HasNew::::new(); + let _f: base::Foo = base::HasNew::new(); + let _b: base::Bar = base::HasNew::new(); } diff --git a/src/test/run-pass/traits-issue-22019.rs b/src/test/run-pass/traits-issue-22019.rs index 5d3195e1937..7e0f60d55a8 100644 --- a/src/test/run-pass/traits-issue-22019.rs +++ b/src/test/run-pass/traits-issue-22019.rs @@ -23,18 +23,18 @@ pub trait GraphWalk<'c, N> { /// Returns all the nodes in this graph. - fn nodes(&'c self) where [N]:ToOwned>; + fn nodes(&'c self) where [N]:ToOwned>; } impl<'g> GraphWalk<'g, Node<'g>> for u32 { - fn nodes(&'g self) where [Node<'g>]:ToOwned>> + fn nodes(&'g self) where [Node<'g>]:ToOwned>> { loop { } } } impl<'h> GraphWalk<'h, Node<'h>> for u64 { - fn nodes(&'h self) where [Node<'h>]:ToOwned>> + fn nodes(&'h self) where [Node<'h>]:ToOwned>> { loop { } } } diff --git a/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs b/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs index 1f9b821178c..2d1ba7f39b2 100644 --- a/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs +++ b/src/test/run-pass/unboxed-closures-infer-recursive-fn.rs @@ -10,7 +10,7 @@ #![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 @@ -20,12 +20,12 @@ struct YCombinator { func: F, - marker: CovariantType<(A,R)>, + marker: PhantomData<(A,R)>, } impl YCombinator { fn new(f: F) -> YCombinator { - YCombinator { func: f, marker: CovariantType } + YCombinator { func: f, marker: PhantomData } } } diff --git a/src/test/run-pass/unique-object-move.rs b/src/test/run-pass/unique-object-move.rs index cec523a0671..f01a56142e0 100644 --- a/src/test/run-pass/unique-object-move.rs +++ b/src/test/run-pass/unique-object-move.rs @@ -13,7 +13,7 @@ #![allow(unknown_features)] #![feature(box_syntax)] -pub trait EventLoop { } +pub trait EventLoop { fn foo(&self) {} } pub struct UvEventLoop { uvio: int diff --git a/src/test/run-pass/unsized.rs b/src/test/run-pass/unsized.rs index e6dd8d46952..ae175d27b0a 100644 --- a/src/test/run-pass/unsized.rs +++ b/src/test/run-pass/unsized.rs @@ -12,17 +12,19 @@ // Test syntax checks for `?Sized` syntax. -trait T1 {} -pub trait T2 {} -trait T3 : T2 {} -trait T4 {} -trait T5 {} -trait T6 {} -trait T7 {} -trait T8 {} -trait T9 {} -struct S1; -enum E {} +use std::marker::{PhantomData, PhantomFn}; + +trait T1 : PhantomFn { } +pub trait T2 : PhantomFn { } +trait T3 : T2 + PhantomFn { } +trait T4 : PhantomFn<(Self,X)> {} +trait T5 : PhantomFn<(Self,X,Y)> {} +trait T6 : PhantomFn<(Self,X,Y)> {} +trait T7 : PhantomFn<(Self,X,Y)> {} +trait T8 : PhantomFn<(Self,X)> {} +trait T9 : PhantomFn<(Self,X)> {} +struct S1(PhantomData); +enum E { E1(PhantomData) } impl T1 for S1 {} fn f() {} type TT = T; diff --git a/src/test/run-pass/unsized2.rs b/src/test/run-pass/unsized2.rs index 285100dd719..10b2f2fb709 100644 --- a/src/test/run-pass/unsized2.rs +++ b/src/test/run-pass/unsized2.rs @@ -15,6 +15,8 @@ // Test sized-ness checking in substitution. +use std::marker; + // Unbounded. fn f1(x: &X) { f1::(x); @@ -25,7 +27,7 @@ fn f2(x: &X) { } // Bounded. -trait T {} +trait T { fn dummy(&self) { } } fn f3(x: &X) { f3::(x); } @@ -66,20 +68,24 @@ fn f7(x: &X) { } trait T4 { - fn m1(x: &T4); - fn m2(x: &T5); + fn dummy(&self) { } + fn m1(x: &T4, y: X); + fn m2(x: &T5, y: X); } trait T5 { + fn dummy(&self) { } // not an error (for now) fn m1(x: &T4); fn m2(x: &T5); } trait T6 { + fn dummy(&self) { } fn m1(x: &T4); fn m2(x: &T5); } trait T7 { + fn dummy(&self) { } // not an error (for now) fn m1(x: &T4); fn m2(x: &T5); diff --git a/src/test/run-pass/variadic-ffi.rs b/src/test/run-pass/variadic-ffi.rs index a729fedb271..5a476ed9ee2 100644 --- a/src/test/run-pass/variadic-ffi.rs +++ b/src/test/run-pass/variadic-ffi.rs @@ -29,11 +29,11 @@ pub fn main() { 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()); }); @@ -44,11 +44,11 @@ pub fn main() { // 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()); }); diff --git a/src/test/run-pass/variance-intersection-of-ref-and-opt-ref.rs b/src/test/run-pass/variance-intersection-of-ref-and-opt-ref.rs new file mode 100644 index 00000000000..948d68e0ccd --- /dev/null +++ b/src/test/run-pass/variance-intersection-of-ref-and-opt-ref.rs @@ -0,0 +1,34 @@ +// 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 or the MIT license +// , 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); +} diff --git a/src/test/run-pass/variance-trait-matching.rs b/src/test/run-pass/variance-trait-matching.rs new file mode 100644 index 00000000000..10441bee3cb --- /dev/null +++ b/src/test/run-pass/variance-trait-matching.rs @@ -0,0 +1,49 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(dead_code)] + +// Get is covariant in T +trait Get { + fn get(&self) -> T; +} + +struct Cloner { + t: T +} + +impl Get for Cloner { + 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); +} + + diff --git a/src/test/run-pass/variance-vec-covariant.rs b/src/test/run-pass/variance-vec-covariant.rs new file mode 100644 index 00000000000..caec6df5a4d --- /dev/null +++ b/src/test/run-pass/variance-vec-covariant.rs @@ -0,0 +1,28 @@ +// 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 or the MIT license +// , 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); +} diff --git a/src/test/run-pass/visible-private-types-feature-gate.rs b/src/test/run-pass/visible-private-types-feature-gate.rs index 9518671b479..46e93b25697 100644 --- a/src/test/run-pass/visible-private-types-feature-gate.rs +++ b/src/test/run-pass/visible-private-types-feature-gate.rs @@ -10,7 +10,7 @@ #![feature(visible_private_types)] -trait Foo {} +trait Foo { fn dummy(&self) { } } pub trait Bar : Foo {} diff --git a/src/test/run-pass/where-clause-bounds-inconsistency.rs b/src/test/run-pass/where-clause-bounds-inconsistency.rs index a1a61127f68..3374f47ed5f 100644 --- a/src/test/run-pass/where-clause-bounds-inconsistency.rs +++ b/src/test/run-pass/where-clause-bounds-inconsistency.rs @@ -8,7 +8,9 @@ // 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(&self, T) where T: Bound; diff --git a/src/test/run-pass/where-clause-early-bound-lifetimes.rs b/src/test/run-pass/where-clause-early-bound-lifetimes.rs index cade99b83a2..4a149d4d3df 100644 --- a/src/test/run-pass/where-clause-early-bound-lifetimes.rs +++ b/src/test/run-pass/where-clause-early-bound-lifetimes.rs @@ -8,7 +8,7 @@ // 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 { } diff --git a/src/test/run-pass/where-clause-method-substituion.rs b/src/test/run-pass/where-clause-method-substituion.rs index b391df8500b..ecc210ea579 100644 --- a/src/test/run-pass/where-clause-method-substituion.rs +++ b/src/test/run-pass/where-clause-method-substituion.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -trait Foo {} +trait Foo { fn dummy(&self, arg: T) { } } trait Bar { fn method(&self) where A: Foo; @@ -19,7 +19,7 @@ trait Bar { impl Foo for X {} -impl Bar for int { +impl Bar for i32 { fn method(&self) where X: Foo { } } diff --git a/src/test/run-pass/where-for-self.rs b/src/test/run-pass/where-for-self.rs index 5d426793c2e..1fd223b0dd3 100644 --- a/src/test/run-pass/where-for-self.rs +++ b/src/test/run-pass/where-for-self.rs @@ -11,13 +11,19 @@ // 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); }