mirror of
https://github.com/rust-lang/rust.git
synced 2025-05-14 02:49:40 +00:00
Auto merge of #22541 - Manishearth:rollup, r=Gankro
Continued from #22520
This commit is contained in:
commit
522d09dfec
46
README.md
46
README.md
@ -1,14 +1,16 @@
|
|||||||
# The Rust Programming Language
|
# The Rust Programming Language
|
||||||
|
|
||||||
This is a compiler for Rust, including standard libraries, tools and
|
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
|
## 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
|
["Installing Rust"]: http://doc.rust-lang.org/book/installing-rust.html
|
||||||
[trpl]: http://doc.rust-lang.org/book/index.html
|
[The Book]: http://doc.rust-lang.org/book/index.html
|
||||||
|
|
||||||
## Building from Source
|
## Building from Source
|
||||||
|
|
||||||
@ -19,22 +21,14 @@ Read ["Installing Rust"][install] from [The Book][trpl].
|
|||||||
* `curl`
|
* `curl`
|
||||||
* `git`
|
* `git`
|
||||||
|
|
||||||
2. Download and build Rust:
|
2. Clone the [source] with `git`:
|
||||||
|
|
||||||
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:
|
|
||||||
|
|
||||||
$ git clone https://github.com/rust-lang/rust.git
|
$ git clone https://github.com/rust-lang/rust.git
|
||||||
$ cd rust
|
$ 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
|
$ ./configure
|
||||||
$ make && make install
|
$ make && make install
|
||||||
@ -46,7 +40,10 @@ Read ["Installing Rust"][install] from [The Book][trpl].
|
|||||||
|
|
||||||
When complete, `make install` will place several programs into
|
When complete, `make install` will place several programs into
|
||||||
`/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the
|
`/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
|
### Building on Windows
|
||||||
|
|
||||||
@ -72,9 +69,6 @@ $ pacman -S base-devel
|
|||||||
$ ./configure
|
$ ./configure
|
||||||
$ make && make install
|
$ make && make install
|
||||||
|
|
||||||
[repo]: https://github.com/rust-lang/rust
|
|
||||||
[tarball]: https://static.rust-lang.org/dist/rustc-nightly-src.tar.gz
|
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
Since the Rust compiler is written in Rust, it must be built by a
|
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
|
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.
|
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
|
## Getting help
|
||||||
|
|
||||||
@ -114,6 +108,14 @@ The Rust community congregates in a few places:
|
|||||||
|
|
||||||
To contribute to Rust, please see [CONTRIBUTING.md](CONTRIBUTING.md).
|
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
|
## License
|
||||||
|
|
||||||
Rust is primarily distributed under the terms of both the MIT license
|
Rust is primarily distributed under the terms of both the MIT license
|
||||||
|
1
configure
vendored
1
configure
vendored
@ -1056,6 +1056,7 @@ do
|
|||||||
make_dir $h/test/run-pass-fulldeps
|
make_dir $h/test/run-pass-fulldeps
|
||||||
make_dir $h/test/run-fail
|
make_dir $h/test/run-fail
|
||||||
make_dir $h/test/compile-fail
|
make_dir $h/test/compile-fail
|
||||||
|
make_dir $h/test/parse-fail
|
||||||
make_dir $h/test/compile-fail-fulldeps
|
make_dir $h/test/compile-fail-fulldeps
|
||||||
make_dir $h/test/bench
|
make_dir $h/test/bench
|
||||||
make_dir $h/test/perf
|
make_dir $h/test/perf
|
||||||
|
17
mk/tests.mk
17
mk/tests.mk
@ -174,12 +174,12 @@ check-notidy: cleantmptestlogs cleantestlibs all check-stage2
|
|||||||
check-lite: cleantestlibs cleantmptestlogs \
|
check-lite: cleantestlibs cleantmptestlogs \
|
||||||
$(foreach crate,$(TEST_TARGET_CRATES),check-stage2-$(crate)) \
|
$(foreach crate,$(TEST_TARGET_CRATES),check-stage2-$(crate)) \
|
||||||
check-stage2-rpass check-stage2-rpass-valgrind \
|
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
|
$(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
|
||||||
|
|
||||||
# Only check the 'reference' tests: rpass/cfail/rfail/rmake.
|
# Only check the 'reference' tests: rpass/cfail/rfail/rmake.
|
||||||
check-ref: cleantestlibs cleantmptestlogs check-stage2-rpass check-stage2-rpass-valgrind \
|
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
|
$(Q)$(CFG_PYTHON) $(S)src/etc/check-summary.py tmp/*.log
|
||||||
|
|
||||||
# Only check the docs.
|
# 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)-rpass-exec \
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-rfail-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)-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-valgrind-exec \
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
|
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
|
||||||
check-stage$(1)-T-$(2)-H-$(3)-cfail-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)
|
RPASS_FULL_TESTS := $(RPASS_FULL_RS)
|
||||||
CFAIL_FULL_TESTS := $(CFAIL_FULL_RS)
|
CFAIL_FULL_TESTS := $(CFAIL_FULL_RS)
|
||||||
RFAIL_TESTS := $(RFAIL_RS)
|
RFAIL_TESTS := $(RFAIL_RS)
|
||||||
CFAIL_TESTS := $(CFAIL_RS) $(PFAIL_RS)
|
CFAIL_TESTS := $(CFAIL_RS)
|
||||||
|
PFAIL_TESTS := $(PFAIL_RS)
|
||||||
BENCH_TESTS := $(BENCH_RS)
|
BENCH_TESTS := $(BENCH_RS)
|
||||||
PERF_TESTS := $(PERF_RS)
|
PERF_TESTS := $(PERF_RS)
|
||||||
PRETTY_TESTS := $(PRETTY_RS)
|
PRETTY_TESTS := $(PRETTY_RS)
|
||||||
@ -508,6 +510,11 @@ CTEST_BUILD_BASE_cfail = compile-fail
|
|||||||
CTEST_MODE_cfail = compile-fail
|
CTEST_MODE_cfail = compile-fail
|
||||||
CTEST_RUNTOOL_cfail = $(CTEST_RUNTOOL)
|
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_SRC_BASE_bench = bench
|
||||||
CTEST_BUILD_BASE_bench = bench
|
CTEST_BUILD_BASE_bench = bench
|
||||||
CTEST_MODE_bench = run-pass
|
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_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_rfail_$(1)-T-$(2)-H-$(3) = $$(RFAIL_TESTS)
|
||||||
CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_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_bench_$(1)-T-$(2)-H-$(3) = $$(BENCH_TESTS)
|
||||||
CTEST_DEPS_perf_$(1)-T-$(2)-H-$(3) = $$(PERF_TESTS)
|
CTEST_DEPS_perf_$(1)-T-$(2)-H-$(3) = $$(PERF_TESTS)
|
||||||
CTEST_DEPS_debuginfo-gdb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_GDB_TESTS)
|
CTEST_DEPS_debuginfo-gdb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_GDB_TESTS)
|
||||||
@ -698,7 +706,7 @@ endif
|
|||||||
|
|
||||||
endef
|
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), \
|
$(foreach host,$(CFG_HOST), \
|
||||||
$(eval $(foreach target,$(CFG_TARGET), \
|
$(eval $(foreach target,$(CFG_TARGET), \
|
||||||
@ -857,6 +865,7 @@ TEST_GROUPS = \
|
|||||||
cfail-full \
|
cfail-full \
|
||||||
rfail \
|
rfail \
|
||||||
cfail \
|
cfail \
|
||||||
|
pfail \
|
||||||
bench \
|
bench \
|
||||||
perf \
|
perf \
|
||||||
rmake \
|
rmake \
|
||||||
|
@ -15,6 +15,7 @@ use std::str::FromStr;
|
|||||||
#[derive(Clone, Copy, PartialEq, Debug)]
|
#[derive(Clone, Copy, PartialEq, Debug)]
|
||||||
pub enum Mode {
|
pub enum Mode {
|
||||||
CompileFail,
|
CompileFail,
|
||||||
|
ParseFail,
|
||||||
RunFail,
|
RunFail,
|
||||||
RunPass,
|
RunPass,
|
||||||
RunPassValgrind,
|
RunPassValgrind,
|
||||||
@ -29,6 +30,7 @@ impl FromStr for Mode {
|
|||||||
fn from_str(s: &str) -> Result<Mode, ()> {
|
fn from_str(s: &str) -> Result<Mode, ()> {
|
||||||
match s {
|
match s {
|
||||||
"compile-fail" => Ok(CompileFail),
|
"compile-fail" => Ok(CompileFail),
|
||||||
|
"parse-fail" => Ok(ParseFail),
|
||||||
"run-fail" => Ok(RunFail),
|
"run-fail" => Ok(RunFail),
|
||||||
"run-pass" => Ok(RunPass),
|
"run-pass" => Ok(RunPass),
|
||||||
"run-pass-valgrind" => Ok(RunPassValgrind),
|
"run-pass-valgrind" => Ok(RunPassValgrind),
|
||||||
@ -45,6 +47,7 @@ impl fmt::Display for Mode {
|
|||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Display::fmt(match *self {
|
fmt::Display::fmt(match *self {
|
||||||
CompileFail => "compile-fail",
|
CompileFail => "compile-fail",
|
||||||
|
ParseFail => "parse-fail",
|
||||||
RunFail => "run-fail",
|
RunFail => "run-fail",
|
||||||
RunPass => "run-pass",
|
RunPass => "run-pass",
|
||||||
RunPassValgrind => "run-pass-valgrind",
|
RunPassValgrind => "run-pass-valgrind",
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#![feature(test)]
|
#![feature(test)]
|
||||||
#![feature(unicode)]
|
#![feature(unicode)]
|
||||||
#![feature(env)]
|
#![feature(env)]
|
||||||
|
#![feature(core)]
|
||||||
|
|
||||||
#![deny(warnings)]
|
#![deny(warnings)]
|
||||||
|
|
||||||
@ -72,7 +73,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
|
|||||||
reqopt("", "aux-base", "directory to find auxiliary test files", "PATH"),
|
reqopt("", "aux-base", "directory to find auxiliary test files", "PATH"),
|
||||||
reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET"),
|
reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET"),
|
||||||
reqopt("", "mode", "which sort of compile tests to run",
|
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"),
|
optflag("", "ignored", "run tests marked as ignored"),
|
||||||
optopt("", "runtool", "supervisor program to run tests under \
|
optopt("", "runtool", "supervisor program to run tests under \
|
||||||
(eg. emulator, valgrind)", "PROGRAM"),
|
(eg. emulator, valgrind)", "PROGRAM"),
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
use self::TargetLocation::*;
|
use self::TargetLocation::*;
|
||||||
|
|
||||||
use common::Config;
|
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 common::{Codegen, DebugInfoLldb};
|
||||||
use errors;
|
use errors;
|
||||||
use header::TestProps;
|
use header::TestProps;
|
||||||
@ -66,6 +66,7 @@ pub fn run_metrics(config: Config, testfile: String, mm: &mut MetricMap) {
|
|||||||
debug!("loaded props");
|
debug!("loaded props");
|
||||||
match config.mode {
|
match config.mode {
|
||||||
CompileFail => run_cfail_test(&config, &props, &testfile),
|
CompileFail => run_cfail_test(&config, &props, &testfile),
|
||||||
|
ParseFail => run_cfail_test(&config, &props, &testfile),
|
||||||
RunFail => run_rfail_test(&config, &props, &testfile),
|
RunFail => run_rfail_test(&config, &props, &testfile),
|
||||||
RunPass => run_rpass_test(&config, &props, &testfile),
|
RunPass => run_rpass_test(&config, &props, &testfile),
|
||||||
RunPassValgrind => run_valgrind_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);
|
let proc_res = compile_test(config, props, testfile);
|
||||||
|
|
||||||
if proc_res.status.success() {
|
if proc_res.status.success() {
|
||||||
fatal_proc_rec("compile-fail test compiled successfully!",
|
fatal_proc_rec(&format!("{} test compiled successfully!", config.mode)[],
|
||||||
&proc_res);
|
&proc_res);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -688,7 +689,7 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.to_string();
|
.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("type summary add --no-value ");
|
||||||
script_str.push_str("--python-function lldb_rust_formatters.print_val ");
|
script_str.push_str("--python-function lldb_rust_formatters.print_val ");
|
||||||
script_str.push_str("-x \".*\" --category Rust\n");
|
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
|
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||||
let mut link_args = vec!("-L".to_string(),
|
let mut link_args = vec!("-L".to_string(),
|
||||||
aux_dir.as_str().unwrap().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,
|
let args = make_compile_args(config,
|
||||||
props,
|
props,
|
||||||
link_args,
|
link_args,
|
||||||
|
@ -572,7 +572,7 @@ the final namespace qualifier is omitted.
|
|||||||
Two examples of paths with type arguments:
|
Two examples of paths with type arguments:
|
||||||
|
|
||||||
```
|
```
|
||||||
# struct HashMap<K, V>;
|
# struct HashMap<K, V>(K,V);
|
||||||
# fn f() {
|
# fn f() {
|
||||||
# fn id<T>(t: T) -> T { t }
|
# fn id<T>(t: T) -> T { t }
|
||||||
type T = HashMap<i32,String>; // Type arguments used in a type expression
|
type T = HashMap<i32,String>; // 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 is in scope) to pointers to the trait name, used as a type.
|
||||||
|
|
||||||
```
|
```
|
||||||
# trait Shape { }
|
# trait Shape { fn dummy(&self) { } }
|
||||||
# impl Shape for i32 { }
|
# impl Shape for i32 { }
|
||||||
# let mycircle = 0i32;
|
# let mycircle = 0i32;
|
||||||
let myshape: Box<Shape> = Box::new(mycircle) as Box<Shape>;
|
let myshape: Box<Shape> = Box::new(mycircle) as Box<Shape>;
|
||||||
@ -1630,8 +1630,8 @@ let x: f64 = Num::from_i32(42);
|
|||||||
Traits may inherit from other traits. For example, in
|
Traits may inherit from other traits. For example, in
|
||||||
|
|
||||||
```
|
```
|
||||||
trait Shape { fn area() -> f64; }
|
trait Shape { fn area(&self) -> f64; }
|
||||||
trait Circle : Shape { fn radius() -> f64; }
|
trait Circle : Shape { fn radius(&self) -> f64; }
|
||||||
```
|
```
|
||||||
|
|
||||||
the syntax `Circle : Shape` means that types that implement `Circle` must also
|
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.
|
are written after the `impl` keyword.
|
||||||
|
|
||||||
```
|
```
|
||||||
# trait Seq<T> { }
|
# trait Seq<T> { fn dummy(&self, _: T) { } }
|
||||||
impl<T> Seq<T> for Vec<T> {
|
impl<T> Seq<T> for Vec<T> {
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
@ -3583,7 +3583,7 @@ An example of each kind:
|
|||||||
```{rust}
|
```{rust}
|
||||||
let vec: Vec<i32> = vec![1, 2, 3];
|
let vec: Vec<i32> = vec![1, 2, 3];
|
||||||
let arr: [i32; 3] = [1, 2, 3];
|
let arr: [i32; 3] = [1, 2, 3];
|
||||||
let s: &[i32] = &vec[];
|
let s: &[i32] = &vec[..];
|
||||||
```
|
```
|
||||||
|
|
||||||
As you can see, the `vec!` macro allows you to create a `Vec<T>` easily. The
|
As you can see, the `vec!` macro allows you to create a `Vec<T>` easily. The
|
||||||
|
@ -435,8 +435,8 @@ extern {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let prompt = CString::from_slice(b"[my-awesome-shell] $");
|
let prompt = CString::new("[my-awesome-shell] $").unwrap();
|
||||||
unsafe {
|
unsafe {
|
||||||
rl_prompt = prompt.as_ptr();
|
rl_prompt = prompt.as_ptr();
|
||||||
|
|
||||||
println!("{:?}", rl_prompt);
|
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
|
The `extern` makes this function adhere to the C calling convention, as
|
||||||
discussed above in "[Foreign Calling
|
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.
|
attribute turns off Rust's name mangling, so that it is easier to link to.
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ If you want to match against a slice or array, you can use `&`:
|
|||||||
fn main() {
|
fn main() {
|
||||||
let v = vec!["match_this", "1"];
|
let v = vec!["match_this", "1"];
|
||||||
|
|
||||||
match &v[] {
|
match &v[..] {
|
||||||
["match_this", second] => println!("The second element is {}", second),
|
["match_this", second] => println!("The second element is {}", second),
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,6 @@ use core::prelude::*;
|
|||||||
|
|
||||||
use core::atomic;
|
use core::atomic;
|
||||||
use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst};
|
use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst};
|
||||||
use core::borrow::BorrowFrom;
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::cmp::{Ordering};
|
use core::cmp::{Ordering};
|
||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
@ -244,12 +243,6 @@ impl<T> Clone for Arc<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> BorrowFrom<Arc<T>> for T {
|
|
||||||
fn borrow_from(owned: &Arc<T>) -> &T {
|
|
||||||
&**owned
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> Deref for Arc<T> {
|
impl<T> Deref for Arc<T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
@ -605,11 +598,19 @@ impl<T: Default + Sync + Send> Default for Arc<T> {
|
|||||||
fn default() -> Arc<T> { Arc::new(Default::default()) }
|
fn default() -> Arc<T> { Arc::new(Default::default()) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
impl<H: Hasher, T: Hash<H>> Hash<H> for Arc<T> {
|
impl<H: Hasher, T: Hash<H>> Hash<H> for Arc<T> {
|
||||||
fn hash(&self, state: &mut H) {
|
fn hash(&self, state: &mut H) {
|
||||||
(**self).hash(state)
|
(**self).hash(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T: Hash> Hash for Arc<T> {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
(**self).hash(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
@ -10,13 +10,14 @@
|
|||||||
|
|
||||||
//! A pointer type for heap allocation.
|
//! A pointer type for heap allocation.
|
||||||
//!
|
//!
|
||||||
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of heap allocation in
|
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of
|
||||||
//! Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of
|
//! heap allocation in Rust. Boxes provide ownership for this allocation, and
|
||||||
//! scope.
|
//! drop their contents when they go out of scope.
|
||||||
//!
|
//!
|
||||||
//! Boxes are useful in two situations: recursive data structures, and occasionally when returning
|
//! Boxes are useful in two situations: recursive data structures, and
|
||||||
//! data. [The Pointer chapter of the Book](../../../book/pointers.html#best-practices-1) explains
|
//! occasionally when returning data. [The Pointer chapter of the
|
||||||
//! these cases in detail.
|
//! Book](../../../book/pointers.html#best-practices-1) explains these cases in
|
||||||
|
//! detail.
|
||||||
//!
|
//!
|
||||||
//! # Examples
|
//! # Examples
|
||||||
//!
|
//!
|
||||||
@ -58,8 +59,8 @@ use core::ops::{Deref, DerefMut};
|
|||||||
use core::ptr::Unique;
|
use core::ptr::Unique;
|
||||||
use core::raw::TraitObject;
|
use core::raw::TraitObject;
|
||||||
|
|
||||||
/// A value that represents the heap. This is the default place that the `box` keyword allocates
|
/// A value that represents the heap. This is the default place that the `box`
|
||||||
/// into when no place is supplied.
|
/// keyword allocates into when no place is supplied.
|
||||||
///
|
///
|
||||||
/// The following two examples are equivalent:
|
/// The following two examples are equivalent:
|
||||||
///
|
///
|
||||||
@ -219,12 +220,20 @@ impl<T: ?Sized + Ord> Ord for Box<T> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: ?Sized + Eq> Eq for Box<T> {}
|
impl<T: ?Sized + Eq> Eq for Box<T> {}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
impl<S: hash::Hasher, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
|
impl<S: hash::Hasher, T: ?Sized + Hash<S>> Hash<S> for Box<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
(**self).hash(state);
|
(**self).hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T: ?Sized + Hash> Hash for Box<T> {
|
||||||
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
|
(**self).hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Extension methods for an owning `Any` trait object.
|
/// Extension methods for an owning `Any` trait object.
|
||||||
#[unstable(feature = "alloc",
|
#[unstable(feature = "alloc",
|
||||||
|
@ -73,7 +73,6 @@
|
|||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
#![feature(unsafe_no_drop_flag)]
|
#![feature(unsafe_no_drop_flag)]
|
||||||
#![feature(core)]
|
#![feature(core)]
|
||||||
#![feature(hash)]
|
|
||||||
#![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")),
|
#![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")),
|
||||||
feature(libc))]
|
feature(libc))]
|
||||||
|
|
||||||
|
@ -144,13 +144,12 @@
|
|||||||
|
|
||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
use core::borrow::BorrowFrom;
|
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use core::clone::Clone;
|
use core::clone::Clone;
|
||||||
use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
|
use core::cmp::{PartialEq, PartialOrd, Eq, Ord, Ordering};
|
||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::hash::{self, Hash};
|
use core::hash::{Hasher, Hash};
|
||||||
use core::marker;
|
use core::marker;
|
||||||
use core::mem::{transmute, min_align_of, size_of, forget};
|
use core::mem::{transmute, min_align_of, size_of, forget};
|
||||||
use core::nonzero::NonZero;
|
use core::nonzero::NonZero;
|
||||||
@ -349,12 +348,6 @@ impl<T: Clone> Rc<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> BorrowFrom<Rc<T>> for T {
|
|
||||||
fn borrow_from(owned: &Rc<T>) -> &T {
|
|
||||||
&**owned
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> Deref for Rc<T> {
|
impl<T> Deref for Rc<T> {
|
||||||
type Target = T;
|
type Target = T;
|
||||||
@ -599,12 +592,20 @@ impl<T: Ord> Ord for Rc<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME (#18248) Make `T` `Sized?`
|
// FIXME (#18248) Make `T` `Sized?`
|
||||||
impl<S: hash::Hasher, T: Hash<S>> Hash<S> for Rc<T> {
|
#[cfg(stage0)]
|
||||||
|
impl<S: Hasher, T: Hash<S>> Hash<S> for Rc<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
(**self).hash(state);
|
(**self).hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T: Hash> Hash for Rc<T> {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
(**self).hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: fmt::Display> fmt::Display for Rc<T> {
|
impl<T: fmt::Display> fmt::Display for Rc<T> {
|
||||||
|
@ -96,7 +96,7 @@ pub struct Arena<'longer_than_self> {
|
|||||||
head: RefCell<Chunk>,
|
head: RefCell<Chunk>,
|
||||||
copy_head: RefCell<Chunk>,
|
copy_head: RefCell<Chunk>,
|
||||||
chunks: RefCell<Vec<Chunk>>,
|
chunks: RefCell<Vec<Chunk>>,
|
||||||
_invariant: marker::InvariantLifetime<'longer_than_self>,
|
_marker: marker::PhantomData<*mut &'longer_than_self()>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Arena<'a> {
|
impl<'a> Arena<'a> {
|
||||||
@ -111,7 +111,7 @@ impl<'a> Arena<'a> {
|
|||||||
head: RefCell::new(chunk(initial_size, false)),
|
head: RefCell::new(chunk(initial_size, false)),
|
||||||
copy_head: RefCell::new(chunk(initial_size, true)),
|
copy_head: RefCell::new(chunk(initial_size, true)),
|
||||||
chunks: RefCell::new(Vec::new()),
|
chunks: RefCell::new(Vec::new()),
|
||||||
_invariant: marker::InvariantLifetime,
|
_marker: marker::PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -361,6 +361,8 @@ pub struct TypedArena<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct TypedArenaChunk<T> {
|
struct TypedArenaChunk<T> {
|
||||||
|
marker: marker::PhantomData<T>,
|
||||||
|
|
||||||
/// Pointer to the next arena segment.
|
/// Pointer to the next arena segment.
|
||||||
next: *mut TypedArenaChunk<T>,
|
next: *mut TypedArenaChunk<T>,
|
||||||
|
|
||||||
|
@ -650,8 +650,8 @@ impl<'a, T: 'a> ExactSizeIterator for Drain<'a, T> {}
|
|||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Ord> FromIterator<T> for BinaryHeap<T> {
|
impl<T: Ord> FromIterator<T> for BinaryHeap<T> {
|
||||||
fn from_iter<Iter: Iterator<Item=T>>(iter: Iter) -> BinaryHeap<T> {
|
fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> BinaryHeap<T> {
|
||||||
BinaryHeap::from_vec(iter.collect())
|
BinaryHeap::from_vec(iter.into_iter().collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -677,7 +677,8 @@ impl<'a, T> IntoIterator for &'a BinaryHeap<T> where T: Ord {
|
|||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Ord> Extend<T> for BinaryHeap<T> {
|
impl<T: Ord> Extend<T> for BinaryHeap<T> {
|
||||||
fn extend<Iter: Iterator<Item=T>>(&mut self, iter: Iter) {
|
fn extend<I: IntoIterator<Item=T>>(&mut self, iterable: I) {
|
||||||
|
let iter = iterable.into_iter();
|
||||||
let (lower, _) = iter.size_hint();
|
let (lower, _) = iter.size_hint();
|
||||||
|
|
||||||
self.reserve(lower);
|
self.reserve(lower);
|
||||||
|
File diff suppressed because it is too large
Load Diff
316
src/libcollections/borrow.rs
Normal file
316
src/libcollections/borrow.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! A module for working with borrowed data.
|
||||||
|
|
||||||
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
|
use core::clone::Clone;
|
||||||
|
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
|
||||||
|
use core::hash::{Hash, Hasher};
|
||||||
|
use core::marker::Sized;
|
||||||
|
use core::ops::Deref;
|
||||||
|
use core::option::Option;
|
||||||
|
|
||||||
|
use fmt;
|
||||||
|
use alloc::{rc, arc};
|
||||||
|
|
||||||
|
use self::Cow::*;
|
||||||
|
|
||||||
|
/// A trait for borrowing data.
|
||||||
|
///
|
||||||
|
/// In general, there may be several ways to "borrow" a piece of data. The
|
||||||
|
/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
|
||||||
|
/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
|
||||||
|
/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
|
||||||
|
///
|
||||||
|
/// When writing generic code, it is often desirable to abstract over all ways
|
||||||
|
/// of borrowing data from a given type. That is the role of the `Borrow`
|
||||||
|
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`. A given
|
||||||
|
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
|
||||||
|
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub trait Borrow<Borrowed: ?Sized> {
|
||||||
|
/// Immutably borrow from an owned value.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
fn borrow(&self) -> &Borrowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A trait for mutably borrowing data.
|
||||||
|
///
|
||||||
|
/// Similar to `Borrow`, but for mutable borrows.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
|
||||||
|
/// Mutably borrow from an owned value.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
fn borrow_mut(&mut self) -> &mut Borrowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T: ?Sized> Borrow<T> for T {
|
||||||
|
fn borrow(&self) -> &T { self }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T: ?Sized> BorrowMut<T> for T {
|
||||||
|
fn borrow_mut(&mut self) -> &mut T { self }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, T: ?Sized> Borrow<T> for &'a T {
|
||||||
|
fn borrow(&self) -> &T { &**self }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, T: ?Sized> Borrow<T> for &'a mut T {
|
||||||
|
fn borrow(&self) -> &T { &**self }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, T: ?Sized> BorrowMut<T> for &'a mut T {
|
||||||
|
fn borrow_mut(&mut self) -> &mut T { &mut **self }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Borrow<T> for rc::Rc<T> {
|
||||||
|
fn borrow(&self) -> &T { &**self }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Borrow<T> for arc::Arc<T> {
|
||||||
|
fn borrow(&self) -> &T { &**self }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> where B: ToOwned, <B as ToOwned>::Owned: 'a {
|
||||||
|
fn borrow(&self) -> &B {
|
||||||
|
&**self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A generalization of Clone to borrowed data.
|
||||||
|
///
|
||||||
|
/// Some types make it possible to go from borrowed to owned, usually by
|
||||||
|
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
|
||||||
|
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
|
||||||
|
/// from any borrow of a given type.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub trait ToOwned {
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
type Owned: Borrow<Self>;
|
||||||
|
|
||||||
|
/// Create owned data from borrowed data, usually by copying.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
fn to_owned(&self) -> Self::Owned;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T> ToOwned for T where T: Clone {
|
||||||
|
type Owned = T;
|
||||||
|
fn to_owned(&self) -> T { self.clone() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A clone-on-write smart pointer.
|
||||||
|
///
|
||||||
|
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
|
||||||
|
/// can enclose and provide immutable access to borrowed data, and clone the
|
||||||
|
/// data lazily when mutation or ownership is required. The type is designed to
|
||||||
|
/// work with general borrowed data via the `Borrow` trait.
|
||||||
|
///
|
||||||
|
/// `Cow` implements both `Deref`, which means that you can call
|
||||||
|
/// non-mutating methods directly on the data it encloses. If mutation
|
||||||
|
/// is desired, `to_mut` will obtain a mutable references to an owned
|
||||||
|
/// value, cloning if necessary.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use std::borrow::Cow;
|
||||||
|
///
|
||||||
|
/// fn abs_all(input: &mut Cow<[int]>) {
|
||||||
|
/// for i in 0..input.len() {
|
||||||
|
/// let v = input[i];
|
||||||
|
/// if v < 0 {
|
||||||
|
/// // clones into a vector the first time (if not already owned)
|
||||||
|
/// input.to_mut()[i] = -v;
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned {
|
||||||
|
/// Borrowed data.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
Borrowed(&'a B),
|
||||||
|
|
||||||
|
/// Owned data.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
Owned(<B as ToOwned>::Owned)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
|
||||||
|
fn clone(&self) -> Cow<'a, B> {
|
||||||
|
match *self {
|
||||||
|
Borrowed(b) => Borrowed(b),
|
||||||
|
Owned(ref o) => {
|
||||||
|
let b: &B = o.borrow();
|
||||||
|
Owned(b.to_owned())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
|
||||||
|
/// Acquire a mutable reference to the owned form of the data.
|
||||||
|
///
|
||||||
|
/// Copies the data if it is not already owned.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned {
|
||||||
|
match *self {
|
||||||
|
Borrowed(borrowed) => {
|
||||||
|
*self = Owned(borrowed.to_owned());
|
||||||
|
self.to_mut()
|
||||||
|
}
|
||||||
|
Owned(ref mut owned) => owned
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extract the owned data.
|
||||||
|
///
|
||||||
|
/// Copies the data if it is not already owned.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub fn into_owned(self) -> <B as ToOwned>::Owned {
|
||||||
|
match self {
|
||||||
|
Borrowed(borrowed) => borrowed.to_owned(),
|
||||||
|
Owned(owned) => owned
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if this `Cow` wraps a borrowed value
|
||||||
|
#[deprecated(since = "1.0.0", reason = "match on the enum instead")]
|
||||||
|
#[unstable(feature = "std_misc")]
|
||||||
|
pub fn is_borrowed(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Borrowed(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if this `Cow` wraps an owned value
|
||||||
|
#[deprecated(since = "1.0.0", reason = "match on the enum instead")]
|
||||||
|
#[unstable(feature = "std_misc")]
|
||||||
|
pub fn is_owned(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Owned(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> Deref for Cow<'a, B> where B: ToOwned {
|
||||||
|
type Target = B;
|
||||||
|
|
||||||
|
fn deref(&self) -> &B {
|
||||||
|
match *self {
|
||||||
|
Borrowed(borrowed) => borrowed,
|
||||||
|
Owned(ref owned) => owned.borrow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned {}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> Ord for Cow<'a, B> where B: Ord + ToOwned {
|
||||||
|
#[inline]
|
||||||
|
fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
|
||||||
|
Ord::cmp(&**self, &**other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> where
|
||||||
|
B: PartialEq<C> + ToOwned, C: ToOwned,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn eq(&self, other: &Cow<'b, C>) -> bool {
|
||||||
|
PartialEq::eq(&**self, &**other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where B: PartialOrd + ToOwned,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
|
||||||
|
PartialOrd::partial_cmp(&**self, &**other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where
|
||||||
|
B: fmt::Debug + ToOwned,
|
||||||
|
<B as ToOwned>::Owned: fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Borrowed(ref b) => fmt::Debug::fmt(b, f),
|
||||||
|
Owned(ref o) => fmt::Debug::fmt(o, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where
|
||||||
|
B: fmt::Display + ToOwned,
|
||||||
|
<B as ToOwned>::Owned: fmt::Display,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Borrowed(ref b) => fmt::Display::fmt(b, f),
|
||||||
|
Owned(ref o) => fmt::Display::fmt(o, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg(stage0)]
|
||||||
|
impl<'a, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, B> where B: Hash<S> + ToOwned
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, state: &mut S) {
|
||||||
|
Hash::hash(&**self, state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
impl<'a, B: ?Sized> Hash for Cow<'a, B> where B: Hash + ToOwned
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
Hash::hash(&**self, state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait for moving into a `Cow`
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
|
||||||
|
/// Moves `self` into `Cow`
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
fn into_cow(self) -> Cow<'a, B>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
|
||||||
|
fn into_cow(self) -> Cow<'a, B> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
313
src/libcollections/borrow_stage0.rs
Normal file
313
src/libcollections/borrow_stage0.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! A module for working with borrowed data.
|
||||||
|
|
||||||
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
|
use core::clone::Clone;
|
||||||
|
use core::cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
|
||||||
|
use core::hash::{Hash, Hasher};
|
||||||
|
use core::marker::Sized;
|
||||||
|
use core::ops::Deref;
|
||||||
|
use core::option::Option;
|
||||||
|
|
||||||
|
use fmt;
|
||||||
|
use alloc::{rc, arc};
|
||||||
|
|
||||||
|
use self::Cow::*;
|
||||||
|
|
||||||
|
/// A trait for borrowing data.
|
||||||
|
///
|
||||||
|
/// In general, there may be several ways to "borrow" a piece of data. The
|
||||||
|
/// typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
|
||||||
|
/// (a mutable borrow). But types like `Vec<T>` provide additional kinds of
|
||||||
|
/// borrows: the borrowed slices `&[T]` and `&mut [T]`.
|
||||||
|
///
|
||||||
|
/// When writing generic code, it is often desirable to abstract over all ways
|
||||||
|
/// of borrowing data from a given type. That is the role of the `Borrow`
|
||||||
|
/// trait: if `T: Borrow<U>`, then `&U` can be borrowed from `&T`. A given
|
||||||
|
/// type can be borrowed as multiple different types. In particular, `Vec<T>:
|
||||||
|
/// Borrow<Vec<T>>` and `Vec<T>: Borrow<[T]>`.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub trait Borrow<Borrowed: ?Sized> {
|
||||||
|
/// Immutably borrow from an owned value.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
fn borrow(&self) -> &Borrowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A trait for mutably borrowing data.
|
||||||
|
///
|
||||||
|
/// Similar to `Borrow`, but for mutable borrows.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub trait BorrowMut<Borrowed: ?Sized> : Borrow<Borrowed> {
|
||||||
|
/// Mutably borrow from an owned value.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
fn borrow_mut(&mut self) -> &mut Borrowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T: ?Sized> Borrow<T> for T {
|
||||||
|
fn borrow(&self) -> &T { self }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T: ?Sized> BorrowMut<T> for T {
|
||||||
|
fn borrow_mut(&mut self) -> &mut T { self }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, T: ?Sized> Borrow<T> for &'a T {
|
||||||
|
fn borrow(&self) -> &T { &**self }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, T: ?Sized> Borrow<T> for &'a mut T {
|
||||||
|
fn borrow(&self) -> &T { &**self }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, T: ?Sized> BorrowMut<T> for &'a mut T {
|
||||||
|
fn borrow_mut(&mut self) -> &mut T { &mut **self }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Borrow<T> for rc::Rc<T> {
|
||||||
|
fn borrow(&self) -> &T { &**self }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Borrow<T> for arc::Arc<T> {
|
||||||
|
fn borrow(&self) -> &T { &**self }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> Borrow<B> for Cow<'a, B> where B: ToOwned, <B as ToOwned>::Owned: 'a {
|
||||||
|
fn borrow(&self) -> &B {
|
||||||
|
&**self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A generalization of Clone to borrowed data.
|
||||||
|
///
|
||||||
|
/// Some types make it possible to go from borrowed to owned, usually by
|
||||||
|
/// implementing the `Clone` trait. But `Clone` works only for going from `&T`
|
||||||
|
/// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
|
||||||
|
/// from any borrow of a given type.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub trait ToOwned {
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
type Owned: Borrow<Self>;
|
||||||
|
|
||||||
|
/// Create owned data from borrowed data, usually by copying.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
fn to_owned(&self) -> Self::Owned;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T> ToOwned for T where T: Clone {
|
||||||
|
type Owned = T;
|
||||||
|
fn to_owned(&self) -> T { self.clone() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A clone-on-write smart pointer.
|
||||||
|
///
|
||||||
|
/// The type `Cow` is a smart pointer providing clone-on-write functionality: it
|
||||||
|
/// can enclose and provide immutable access to borrowed data, and clone the
|
||||||
|
/// data lazily when mutation or ownership is required. The type is designed to
|
||||||
|
/// work with general borrowed data via the `Borrow` trait.
|
||||||
|
///
|
||||||
|
/// `Cow` implements both `Deref`, which means that you can call
|
||||||
|
/// non-mutating methods directly on the data it encloses. If mutation
|
||||||
|
/// is desired, `to_mut` will obtain a mutable references to an owned
|
||||||
|
/// value, cloning if necessary.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use std::borrow::Cow;
|
||||||
|
///
|
||||||
|
/// fn abs_all(input: &mut Cow<[int]>) {
|
||||||
|
/// for i in 0..input.len() {
|
||||||
|
/// let v = input[i];
|
||||||
|
/// if v < 0 {
|
||||||
|
/// // clones into a vector the first time (if not already owned)
|
||||||
|
/// input.to_mut()[i] = -v;
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub enum Cow<'a, B: ?Sized + 'a> where B: ToOwned {
|
||||||
|
/// Borrowed data.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
Borrowed(&'a B),
|
||||||
|
|
||||||
|
/// Owned data.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
Owned(<B as ToOwned>::Owned)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
|
||||||
|
fn clone(&self) -> Cow<'a, B> {
|
||||||
|
match *self {
|
||||||
|
Borrowed(b) => Borrowed(b),
|
||||||
|
Owned(ref o) => {
|
||||||
|
let b: &B = o.borrow();
|
||||||
|
Owned(b.to_owned())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned, <B as ToOwned>::Owned: 'a {
|
||||||
|
/// Acquire a mutable reference to the owned form of the data.
|
||||||
|
///
|
||||||
|
/// Copies the data if it is not already owned.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub fn to_mut(&mut self) -> &mut <B as ToOwned>::Owned where <B as ToOwned>::Owned: 'a {
|
||||||
|
match *self {
|
||||||
|
Borrowed(borrowed) => {
|
||||||
|
*self = Owned(borrowed.to_owned());
|
||||||
|
self.to_mut()
|
||||||
|
}
|
||||||
|
Owned(ref mut owned) => owned
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extract the owned data.
|
||||||
|
///
|
||||||
|
/// Copies the data if it is not already owned.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub fn into_owned(self) -> <B as ToOwned>::Owned {
|
||||||
|
match self {
|
||||||
|
Borrowed(borrowed) => borrowed.to_owned(),
|
||||||
|
Owned(owned) => owned
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if this `Cow` wraps a borrowed value
|
||||||
|
#[deprecated(since = "1.0.0", reason = "match on the enum instead")]
|
||||||
|
#[unstable(feature = "std_misc")]
|
||||||
|
pub fn is_borrowed(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Borrowed(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns true if this `Cow` wraps an owned value
|
||||||
|
#[deprecated(since = "1.0.0", reason = "match on the enum instead")]
|
||||||
|
#[unstable(feature = "std_misc")]
|
||||||
|
pub fn is_owned(&self) -> bool {
|
||||||
|
match *self {
|
||||||
|
Owned(_) => true,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> Deref for Cow<'a, B> where
|
||||||
|
B: ToOwned, <B as ToOwned>::Owned: 'a
|
||||||
|
{
|
||||||
|
type Target = B;
|
||||||
|
|
||||||
|
fn deref(&self) -> &B {
|
||||||
|
match *self {
|
||||||
|
Borrowed(borrowed) => borrowed,
|
||||||
|
Owned(ref owned) => owned.borrow()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> Eq for Cow<'a, B> where B: Eq + ToOwned, <B as ToOwned>::Owned: 'a {}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> Ord for Cow<'a, B> where
|
||||||
|
B: Ord + ToOwned, <B as ToOwned>::Owned: 'a
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn cmp(&self, other: &Cow<'a, B>) -> Ordering {
|
||||||
|
Ord::cmp(&**self, &**other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, 'b, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, C>> for Cow<'a, B> where
|
||||||
|
B: PartialEq<C> + ToOwned, C: ToOwned,
|
||||||
|
<B as ToOwned>::Owned: 'a, <C as ToOwned>::Owned: 'b,
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn eq(&self, other: &Cow<'b, C>) -> bool {
|
||||||
|
PartialEq::eq(&**self, &**other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> PartialOrd for Cow<'a, B> where
|
||||||
|
B: PartialOrd + ToOwned, <B as ToOwned>::Owned: 'a
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn partial_cmp(&self, other: &Cow<'a, B>) -> Option<Ordering> {
|
||||||
|
PartialOrd::partial_cmp(&**self, &**other)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> fmt::Debug for Cow<'a, B> where
|
||||||
|
B: fmt::Debug + ToOwned,
|
||||||
|
<B as ToOwned>::Owned: fmt::Debug,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Borrowed(ref b) => fmt::Debug::fmt(b, f),
|
||||||
|
Owned(ref o) => fmt::Debug::fmt(o, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> fmt::Display for Cow<'a, B> where
|
||||||
|
B: fmt::Display + ToOwned,
|
||||||
|
<B as ToOwned>::Owned: fmt::Display,
|
||||||
|
{
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
match *self {
|
||||||
|
Borrowed(ref b) => fmt::Display::fmt(b, f),
|
||||||
|
Owned(ref o) => fmt::Display::fmt(o, f),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, B> where
|
||||||
|
B: Hash<S> + ToOwned, <B as ToOwned>::Owned: 'a
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, state: &mut S) {
|
||||||
|
Hash::hash(&**self, state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Trait for moving into a `Cow`
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub trait IntoCow<'a, B: ?Sized> where B: ToOwned {
|
||||||
|
/// Moves `self` into `Cow`
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
fn into_cow(self) -> Cow<'a, B>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, B: ?Sized> IntoCow<'a, B> for Cow<'a, B> where B: ToOwned {
|
||||||
|
fn into_cow(self) -> Cow<'a, B> {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
@ -19,7 +19,6 @@ use self::Entry::*;
|
|||||||
|
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
|
|
||||||
use core::borrow::BorrowFrom;
|
|
||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
@ -29,7 +28,8 @@ use core::ops::{Index, IndexMut};
|
|||||||
use core::{iter, fmt, mem};
|
use core::{iter, fmt, mem};
|
||||||
use Bound::{self, Included, Excluded, Unbounded};
|
use Bound::{self, Included, Excluded, Unbounded};
|
||||||
|
|
||||||
use ring_buf::RingBuf;
|
use borrow::Borrow;
|
||||||
|
use vec_deque::VecDeque;
|
||||||
|
|
||||||
use self::Continuation::{Continue, Finished};
|
use self::Continuation::{Continue, Finished};
|
||||||
use self::StackOp::*;
|
use self::StackOp::*;
|
||||||
@ -75,7 +75,7 @@ pub struct BTreeMap<K, V> {
|
|||||||
|
|
||||||
/// An abstract base over-which all other BTree iterators are built.
|
/// An abstract base over-which all other BTree iterators are built.
|
||||||
struct AbsIter<T> {
|
struct AbsIter<T> {
|
||||||
traversals: RingBuf<T>,
|
traversals: VecDeque<T>,
|
||||||
size: usize,
|
size: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -208,7 +208,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||||||
/// assert_eq!(map.get(&2), None);
|
/// assert_eq!(map.get(&2), None);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V> where Q: BorrowFrom<K> + Ord {
|
pub fn get<Q: ?Sized>(&self, key: &Q) -> Option<&V> where K: Borrow<Q>, Q: Ord {
|
||||||
let mut cur_node = &self.root;
|
let mut cur_node = &self.root;
|
||||||
loop {
|
loop {
|
||||||
match Node::search(cur_node, key) {
|
match Node::search(cur_node, key) {
|
||||||
@ -240,7 +240,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||||||
/// assert_eq!(map.contains_key(&2), false);
|
/// assert_eq!(map.contains_key(&2), false);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool where Q: BorrowFrom<K> + Ord {
|
pub fn contains_key<Q: ?Sized>(&self, key: &Q) -> bool where K: Borrow<Q>, Q: Ord {
|
||||||
self.get(key).is_some()
|
self.get(key).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,7 +264,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||||||
/// ```
|
/// ```
|
||||||
// See `get` for implementation notes, this is basically a copy-paste with mut's added
|
// See `get` for implementation notes, this is basically a copy-paste with mut's added
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom<K> + Ord {
|
pub fn get_mut<Q: ?Sized>(&mut self, key: &Q) -> Option<&mut V> where K: Borrow<Q>, Q: Ord {
|
||||||
// temp_node is a Borrowck hack for having a mutable value outlive a loop iteration
|
// temp_node is a Borrowck hack for having a mutable value outlive a loop iteration
|
||||||
let mut temp_node = &mut self.root;
|
let mut temp_node = &mut self.root;
|
||||||
loop {
|
loop {
|
||||||
@ -434,7 +434,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
|
|||||||
/// assert_eq!(map.remove(&1), None);
|
/// assert_eq!(map.remove(&1), None);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V> where Q: BorrowFrom<K> + Ord {
|
pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V> where K: Borrow<Q>, Q: Ord {
|
||||||
// See `swap` for a more thorough description of the stuff going on in here
|
// See `swap` for a more thorough description of the stuff going on in here
|
||||||
let mut stack = stack::PartialSearchStack::new(self);
|
let mut stack = stack::PartialSearchStack::new(self);
|
||||||
loop {
|
loop {
|
||||||
@ -512,13 +512,22 @@ mod stack {
|
|||||||
use super::super::node::handle;
|
use super::super::node::handle;
|
||||||
use vec::Vec;
|
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
|
/// 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`
|
/// 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,
|
/// 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.
|
/// where `&'static` can be used in any function expecting any lifetime reference.
|
||||||
pub struct IdRef<'id, T: 'id> {
|
pub struct IdRef<'id, T: 'id> {
|
||||||
inner: &'id mut T,
|
inner: &'id mut T,
|
||||||
marker: marker::InvariantLifetime<'id>
|
_marker: InvariantLifetime<'id>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'id, T> Deref for IdRef<'id, T> {
|
impl<'id, T> Deref for IdRef<'id, T> {
|
||||||
@ -560,7 +569,7 @@ mod stack {
|
|||||||
pub struct Pusher<'id, 'a, K:'a, V:'a> {
|
pub struct Pusher<'id, 'a, K:'a, V:'a> {
|
||||||
map: &'a mut BTreeMap<K, V>,
|
map: &'a mut BTreeMap<K, V>,
|
||||||
stack: Stack<K, V>,
|
stack: Stack<K, V>,
|
||||||
marker: marker::InvariantLifetime<'id>
|
_marker: InvariantLifetime<'id>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, K, V> PartialSearchStack<'a, K, V> {
|
impl<'a, K, V> PartialSearchStack<'a, K, V> {
|
||||||
@ -595,11 +604,11 @@ mod stack {
|
|||||||
let pusher = Pusher {
|
let pusher = Pusher {
|
||||||
map: self.map,
|
map: self.map,
|
||||||
stack: self.stack,
|
stack: self.stack,
|
||||||
marker: marker::InvariantLifetime
|
_marker: InvariantLifetime::new(),
|
||||||
};
|
};
|
||||||
let node = IdRef {
|
let node = IdRef {
|
||||||
inner: unsafe { &mut *self.next },
|
inner: unsafe { &mut *self.next },
|
||||||
marker: marker::InvariantLifetime
|
_marker: InvariantLifetime::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
closure(pusher, node)
|
closure(pusher, node)
|
||||||
@ -826,7 +835,7 @@ mod stack {
|
|||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
|
impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
|
||||||
fn from_iter<T: Iterator<Item=(K, V)>>(iter: T) -> BTreeMap<K, V> {
|
fn from_iter<T: IntoIterator<Item=(K, V)>>(iter: T) -> BTreeMap<K, V> {
|
||||||
let mut map = BTreeMap::new();
|
let mut map = BTreeMap::new();
|
||||||
map.extend(iter);
|
map.extend(iter);
|
||||||
map
|
map
|
||||||
@ -836,13 +845,14 @@ impl<K: Ord, V> FromIterator<(K, V)> for BTreeMap<K, V> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
|
impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn extend<T: Iterator<Item=(K, V)>>(&mut self, iter: T) {
|
fn extend<T: IntoIterator<Item=(K, V)>>(&mut self, iter: T) {
|
||||||
for (k, v) in iter {
|
for (k, v) in iter {
|
||||||
self.insert(k, v);
|
self.insert(k, v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<S: Hasher, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
|
impl<S: Hasher, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
@ -851,6 +861,15 @@ impl<S: Hasher, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<K: Hash, V: Hash> Hash for BTreeMap<K, V> {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
for elt in self {
|
||||||
|
elt.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<K: Ord, V> Default for BTreeMap<K, V> {
|
impl<K: Ord, V> Default for BTreeMap<K, V> {
|
||||||
@ -903,7 +922,7 @@ impl<K: Debug, V: Debug> Debug for BTreeMap<K, V> {
|
|||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<K: Ord, Q: ?Sized, V> Index<Q> for BTreeMap<K, V>
|
impl<K: Ord, Q: ?Sized, V> Index<Q> for BTreeMap<K, V>
|
||||||
where Q: BorrowFrom<K> + Ord
|
where K: Borrow<Q>, Q: Ord
|
||||||
{
|
{
|
||||||
type Output = V;
|
type Output = V;
|
||||||
|
|
||||||
@ -914,7 +933,7 @@ impl<K: Ord, Q: ?Sized, V> Index<Q> for BTreeMap<K, V>
|
|||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<K: Ord, Q: ?Sized, V> IndexMut<Q> for BTreeMap<K, V>
|
impl<K: Ord, Q: ?Sized, V> IndexMut<Q> for BTreeMap<K, V>
|
||||||
where Q: BorrowFrom<K> + Ord
|
where K: Borrow<Q>, Q: Ord
|
||||||
{
|
{
|
||||||
fn index_mut(&mut self, key: &Q) -> &mut V {
|
fn index_mut(&mut self, key: &Q) -> &mut V {
|
||||||
self.get_mut(key).expect("no entry found for key")
|
self.get_mut(key).expect("no entry found for key")
|
||||||
@ -1189,7 +1208,7 @@ impl<K, V> BTreeMap<K, V> {
|
|||||||
pub fn iter(&self) -> Iter<K, V> {
|
pub fn iter(&self) -> Iter<K, V> {
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
// NB. The initial capacity for ringbuf is large enough to avoid reallocs in many cases.
|
// 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));
|
lca.push_back(Traverse::traverse(&self.root));
|
||||||
Iter {
|
Iter {
|
||||||
inner: AbsIter {
|
inner: AbsIter {
|
||||||
@ -1221,7 +1240,7 @@ impl<K, V> BTreeMap<K, V> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn iter_mut(&mut self) -> IterMut<K, V> {
|
pub fn iter_mut(&mut self) -> IterMut<K, V> {
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
let mut lca = RingBuf::new();
|
let mut lca = VecDeque::new();
|
||||||
lca.push_back(Traverse::traverse(&mut self.root));
|
lca.push_back(Traverse::traverse(&mut self.root));
|
||||||
IterMut {
|
IterMut {
|
||||||
inner: AbsIter {
|
inner: AbsIter {
|
||||||
@ -1250,7 +1269,7 @@ impl<K, V> BTreeMap<K, V> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn into_iter(self) -> IntoIter<K, V> {
|
pub fn into_iter(self) -> IntoIter<K, V> {
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
let mut lca = RingBuf::new();
|
let mut lca = VecDeque::new();
|
||||||
lca.push_back(Traverse::traverse(self.root));
|
lca.push_back(Traverse::traverse(self.root));
|
||||||
IntoIter {
|
IntoIter {
|
||||||
inner: AbsIter {
|
inner: AbsIter {
|
||||||
@ -1342,7 +1361,7 @@ macro_rules! range_impl {
|
|||||||
// A deque that encodes two search paths containing (left-to-right):
|
// 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,
|
// a series of truncated-from-the-left iterators, the LCA's doubly-truncated iterator,
|
||||||
// and a series of truncated-from-the-right iterators.
|
// 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 (root, min, max) = ($root, $min, $max);
|
||||||
|
|
||||||
let mut leftmost = None;
|
let mut leftmost = None;
|
||||||
|
@ -18,13 +18,15 @@ pub use self::TraversalItem::*;
|
|||||||
|
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
|
|
||||||
use core::borrow::BorrowFrom;
|
|
||||||
use core::cmp::Ordering::{Greater, Less, Equal};
|
use core::cmp::Ordering::{Greater, Less, Equal};
|
||||||
use core::iter::Zip;
|
use core::iter::Zip;
|
||||||
|
use core::marker::PhantomData;
|
||||||
use core::ops::{Deref, DerefMut, Index, IndexMut};
|
use core::ops::{Deref, DerefMut, Index, IndexMut};
|
||||||
use core::ptr::Unique;
|
use core::ptr::Unique;
|
||||||
use core::{slice, mem, ptr, cmp, num, raw};
|
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
|
/// Represents the result of an Insertion: either the item fit, or the node had to split
|
||||||
pub enum InsertionResult<K, V> {
|
pub enum InsertionResult<K, V> {
|
||||||
@ -57,8 +59,8 @@ pub struct Node<K, V> {
|
|||||||
keys: Unique<K>,
|
keys: Unique<K>,
|
||||||
vals: Unique<V>,
|
vals: Unique<V>,
|
||||||
|
|
||||||
// In leaf nodes, this will be null, and no space will be allocated for edges.
|
// In leaf nodes, this will be None, and no space will be allocated for edges.
|
||||||
edges: Unique<Node<K, V>>,
|
edges: Option<Unique<Node<K, V>>>,
|
||||||
|
|
||||||
// At any given time, there will be `_len` keys, `_len` values, and (in an internal node)
|
// 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.
|
// `_len + 1` edges. In a leaf node, there will never be any edges.
|
||||||
@ -278,8 +280,11 @@ impl<T> Drop for RawItems<T> {
|
|||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
impl<K, V> Drop for Node<K, V> {
|
impl<K, V> Drop for Node<K, V> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if self.keys.ptr.is_null() {
|
if self.keys.is_null() {
|
||||||
// We have already cleaned up this node.
|
// 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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -292,7 +297,7 @@ impl<K, V> Drop for Node<K, V> {
|
|||||||
self.destroy();
|
self.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
self.keys.ptr = ptr::null_mut();
|
self.keys = unsafe { Unique::new(0 as *mut K) };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,9 +313,9 @@ impl<K, V> Node<K, V> {
|
|||||||
let (vals_offset, edges_offset) = calculate_offsets_generic::<K, V>(capacity, false);
|
let (vals_offset, edges_offset) = calculate_offsets_generic::<K, V>(capacity, false);
|
||||||
|
|
||||||
Node {
|
Node {
|
||||||
keys: Unique(buffer as *mut K),
|
keys: Unique::new(buffer as *mut K),
|
||||||
vals: Unique(buffer.offset(vals_offset as isize) as *mut V),
|
vals: Unique::new(buffer.offset(vals_offset as isize) as *mut V),
|
||||||
edges: Unique(buffer.offset(edges_offset as isize) as *mut Node<K, V>),
|
edges: Some(Unique::new(buffer.offset(edges_offset as isize) as *mut Node<K, V>)),
|
||||||
_len: 0,
|
_len: 0,
|
||||||
_capacity: capacity,
|
_capacity: capacity,
|
||||||
}
|
}
|
||||||
@ -326,9 +331,9 @@ impl<K, V> Node<K, V> {
|
|||||||
let (vals_offset, _) = calculate_offsets_generic::<K, V>(capacity, true);
|
let (vals_offset, _) = calculate_offsets_generic::<K, V>(capacity, true);
|
||||||
|
|
||||||
Node {
|
Node {
|
||||||
keys: Unique(buffer as *mut K),
|
keys: unsafe { Unique::new(buffer as *mut K) },
|
||||||
vals: Unique(unsafe { buffer.offset(vals_offset as isize) as *mut V }),
|
vals: unsafe { Unique::new(buffer.offset(vals_offset as isize) as *mut V) },
|
||||||
edges: Unique(ptr::null_mut()),
|
edges: None,
|
||||||
_len: 0,
|
_len: 0,
|
||||||
_capacity: capacity,
|
_capacity: capacity,
|
||||||
}
|
}
|
||||||
@ -337,18 +342,18 @@ impl<K, V> Node<K, V> {
|
|||||||
unsafe fn destroy(&mut self) {
|
unsafe fn destroy(&mut self) {
|
||||||
let (alignment, size) =
|
let (alignment, size) =
|
||||||
calculate_allocation_generic::<K, V>(self.capacity(), self.is_leaf());
|
calculate_allocation_generic::<K, V>(self.capacity(), self.is_leaf());
|
||||||
heap::deallocate(self.keys.ptr as *mut u8, size, alignment);
|
heap::deallocate(*self.keys as *mut u8, size, alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn as_slices<'a>(&'a self) -> (&'a [K], &'a [V]) {
|
pub fn as_slices<'a>(&'a self) -> (&'a [K], &'a [V]) {
|
||||||
unsafe {(
|
unsafe {(
|
||||||
mem::transmute(raw::Slice {
|
mem::transmute(raw::Slice {
|
||||||
data: self.keys.ptr,
|
data: *self.keys as *const K,
|
||||||
len: self.len()
|
len: self.len()
|
||||||
}),
|
}),
|
||||||
mem::transmute(raw::Slice {
|
mem::transmute(raw::Slice {
|
||||||
data: self.vals.ptr,
|
data: *self.vals as *const V,
|
||||||
len: self.len()
|
len: self.len()
|
||||||
})
|
})
|
||||||
)}
|
)}
|
||||||
@ -367,8 +372,12 @@ impl<K, V> Node<K, V> {
|
|||||||
&[]
|
&[]
|
||||||
} else {
|
} else {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let data = match self.edges {
|
||||||
|
None => heap::EMPTY as *const Node<K,V>,
|
||||||
|
Some(ref p) => **p as *const Node<K,V>,
|
||||||
|
};
|
||||||
mem::transmute(raw::Slice {
|
mem::transmute(raw::Slice {
|
||||||
data: self.edges.ptr,
|
data: data,
|
||||||
len: self.len() + 1
|
len: self.len() + 1
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -524,7 +533,8 @@ impl<K: Clone, V: Clone> Clone for Node<K, V> {
|
|||||||
#[derive(Copy)]
|
#[derive(Copy)]
|
||||||
pub struct Handle<NodeRef, Type, NodeType> {
|
pub struct Handle<NodeRef, Type, NodeType> {
|
||||||
node: NodeRef,
|
node: NodeRef,
|
||||||
index: usize
|
index: usize,
|
||||||
|
marker: PhantomData<(Type, NodeType)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod handle {
|
pub mod handle {
|
||||||
@ -543,13 +553,13 @@ impl<K: Ord, V> Node<K, V> {
|
|||||||
/// `Found` will be yielded with the matching index. If it doesn't find an exact match,
|
/// `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.
|
/// `GoDown` will be yielded with the index of the subtree the key must lie in.
|
||||||
pub fn search<Q: ?Sized, NodeRef: Deref<Target=Node<K, V>>>(node: NodeRef, key: &Q)
|
pub fn search<Q: ?Sized, NodeRef: Deref<Target=Node<K, V>>>(node: NodeRef, key: &Q)
|
||||||
-> SearchResult<NodeRef> where Q: BorrowFrom<K> + Ord {
|
-> SearchResult<NodeRef> where K: Borrow<Q>, Q: Ord {
|
||||||
// FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V).
|
// 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*
|
// For the B configured as of this writing (B = 6), binary search was *significantly*
|
||||||
// worse for usizes.
|
// worse for usizes.
|
||||||
match node.as_slices_internal().search_linear(key) {
|
match node.as_slices_internal().search_linear(key) {
|
||||||
(index, true) => Found(Handle { node: node, index: index }),
|
(index, true) => Found(Handle { node: node, index: index, marker: PhantomData }),
|
||||||
(index, false) => GoDown(Handle { node: node, index: index }),
|
(index, false) => GoDown(Handle { node: node, index: index, marker: PhantomData }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -586,7 +596,7 @@ impl <K, V> Node<K, V> {
|
|||||||
|
|
||||||
/// If the node has any children
|
/// If the node has any children
|
||||||
pub fn is_leaf(&self) -> bool {
|
pub fn is_leaf(&self) -> bool {
|
||||||
self.edges.ptr.is_null()
|
self.edges.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// if the node has too few elements
|
/// if the node has too few elements
|
||||||
@ -618,7 +628,8 @@ impl<K, V, NodeRef, Type, NodeType> Handle<NodeRef, Type, NodeType> where
|
|||||||
pub fn as_raw(&mut self) -> Handle<*mut Node<K, V>, Type, NodeType> {
|
pub fn as_raw(&mut self) -> Handle<*mut Node<K, V>, Type, NodeType> {
|
||||||
Handle {
|
Handle {
|
||||||
node: &mut *self.node as *mut _,
|
node: &mut *self.node as *mut _,
|
||||||
index: self.index
|
index: self.index,
|
||||||
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -630,7 +641,8 @@ impl<K, V, Type, NodeType> Handle<*mut Node<K, V>, Type, NodeType> {
|
|||||||
pub unsafe fn from_raw<'a>(&'a self) -> Handle<&'a Node<K, V>, Type, NodeType> {
|
pub unsafe fn from_raw<'a>(&'a self) -> Handle<&'a Node<K, V>, Type, NodeType> {
|
||||||
Handle {
|
Handle {
|
||||||
node: &*self.node,
|
node: &*self.node,
|
||||||
index: self.index
|
index: self.index,
|
||||||
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -640,7 +652,8 @@ impl<K, V, Type, NodeType> Handle<*mut Node<K, V>, Type, NodeType> {
|
|||||||
pub unsafe fn from_raw_mut<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, Type, NodeType> {
|
pub unsafe fn from_raw_mut<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, Type, NodeType> {
|
||||||
Handle {
|
Handle {
|
||||||
node: &mut *self.node,
|
node: &mut *self.node,
|
||||||
index: self.index
|
index: self.index,
|
||||||
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -688,12 +701,14 @@ impl<K, V, NodeRef: Deref<Target=Node<K, V>>, Type> Handle<NodeRef, Type, handle
|
|||||||
if self.node.is_leaf() {
|
if self.node.is_leaf() {
|
||||||
Leaf(Handle {
|
Leaf(Handle {
|
||||||
node: self.node,
|
node: self.node,
|
||||||
index: self.index
|
index: self.index,
|
||||||
|
marker: PhantomData,
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
Internal(Handle {
|
Internal(Handle {
|
||||||
node: self.node,
|
node: self.node,
|
||||||
index: self.index
|
index: self.index,
|
||||||
|
marker: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -826,7 +841,8 @@ impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::Edge, NodeType> where
|
|||||||
unsafe fn left_kv<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::KV, NodeType> {
|
unsafe fn left_kv<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::KV, NodeType> {
|
||||||
Handle {
|
Handle {
|
||||||
node: &mut *self.node,
|
node: &mut *self.node,
|
||||||
index: self.index - 1
|
index: self.index - 1,
|
||||||
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -836,7 +852,8 @@ impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::Edge, NodeType> where
|
|||||||
unsafe fn right_kv<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::KV, NodeType> {
|
unsafe fn right_kv<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::KV, NodeType> {
|
||||||
Handle {
|
Handle {
|
||||||
node: &mut *self.node,
|
node: &mut *self.node,
|
||||||
index: self.index
|
index: self.index,
|
||||||
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -876,7 +893,8 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<&'a mut Node<K, V>, handle::KV, NodeType
|
|||||||
pub fn into_left_edge(self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> {
|
pub fn into_left_edge(self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> {
|
||||||
Handle {
|
Handle {
|
||||||
node: &mut *self.node,
|
node: &mut *self.node,
|
||||||
index: self.index
|
index: self.index,
|
||||||
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -926,7 +944,8 @@ impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::KV, NodeType> where
|
|||||||
pub fn left_edge<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> {
|
pub fn left_edge<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> {
|
||||||
Handle {
|
Handle {
|
||||||
node: &mut *self.node,
|
node: &mut *self.node,
|
||||||
index: self.index
|
index: self.index,
|
||||||
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -935,7 +954,8 @@ impl<K, V, NodeRef, NodeType> Handle<NodeRef, handle::KV, NodeType> where
|
|||||||
pub fn right_edge<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> {
|
pub fn right_edge<'a>(&'a mut self) -> Handle<&'a mut Node<K, V>, handle::Edge, NodeType> {
|
||||||
Handle {
|
Handle {
|
||||||
node: &mut *self.node,
|
node: &mut *self.node,
|
||||||
index: self.index + 1
|
index: self.index + 1,
|
||||||
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1044,7 +1064,8 @@ impl<K, V> Node<K, V> {
|
|||||||
debug_assert!(index < self.len(), "kv_handle index out of bounds");
|
debug_assert!(index < self.len(), "kv_handle index out of bounds");
|
||||||
Handle {
|
Handle {
|
||||||
node: self,
|
node: self,
|
||||||
index: index
|
index: index,
|
||||||
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1064,7 +1085,7 @@ impl<K, V> Node<K, V> {
|
|||||||
vals: RawItems::from_slice(self.vals()),
|
vals: RawItems::from_slice(self.vals()),
|
||||||
edges: RawItems::from_slice(self.edges()),
|
edges: RawItems::from_slice(self.edges()),
|
||||||
|
|
||||||
ptr: self.keys.ptr as *mut u8,
|
ptr: *self.keys as *mut u8,
|
||||||
capacity: self.capacity(),
|
capacity: self.capacity(),
|
||||||
is_leaf: self.is_leaf()
|
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> {
|
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).
|
/// Performs linear search in a slice. Returns a tuple of (index, is_exact_match).
|
||||||
fn search_linear<Q: ?Sized>(&self, key: &Q) -> (usize, bool)
|
fn search_linear<Q: ?Sized>(&self, key: &Q) -> (usize, bool)
|
||||||
where Q: BorrowFrom<K> + Ord {
|
where K: Borrow<Q>, Q: Ord {
|
||||||
for (i, k) in self.keys.iter().enumerate() {
|
for (i, k) in self.keys.iter().enumerate() {
|
||||||
match key.cmp(BorrowFrom::borrow_from(k)) {
|
match key.cmp(k.borrow()) {
|
||||||
Greater => {},
|
Greater => {},
|
||||||
Equal => return (i, true),
|
Equal => return (i, true),
|
||||||
Less => return (i, false),
|
Less => return (i, false),
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
|
|
||||||
use core::borrow::BorrowFrom;
|
|
||||||
use core::cmp::Ordering::{self, Less, Greater, Equal};
|
use core::cmp::Ordering::{self, Less, Greater, Equal};
|
||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
use core::fmt::Debug;
|
use core::fmt::Debug;
|
||||||
@ -21,6 +20,7 @@ use core::fmt;
|
|||||||
use core::iter::{Peekable, Map, FromIterator, IntoIterator};
|
use core::iter::{Peekable, Map, FromIterator, IntoIterator};
|
||||||
use core::ops::{BitOr, BitAnd, BitXor, Sub};
|
use core::ops::{BitOr, BitAnd, BitXor, Sub};
|
||||||
|
|
||||||
|
use borrow::Borrow;
|
||||||
use btree_map::{BTreeMap, Keys};
|
use btree_map::{BTreeMap, Keys};
|
||||||
use Bound;
|
use Bound;
|
||||||
|
|
||||||
@ -336,7 +336,7 @@ impl<T: Ord> BTreeSet<T> {
|
|||||||
/// assert_eq!(set.contains(&4), false);
|
/// assert_eq!(set.contains(&4), false);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
|
pub fn contains<Q: ?Sized>(&self, value: &Q) -> bool where T: Borrow<Q>, Q: Ord {
|
||||||
self.map.contains_key(value)
|
self.map.contains_key(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -466,14 +466,14 @@ impl<T: Ord> BTreeSet<T> {
|
|||||||
/// assert_eq!(set.remove(&2), false);
|
/// assert_eq!(set.remove(&2), false);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
|
pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool where T: Borrow<Q>, Q: Ord {
|
||||||
self.map.remove(value).is_some()
|
self.map.remove(value).is_some()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Ord> FromIterator<T> for BTreeSet<T> {
|
impl<T: Ord> FromIterator<T> for BTreeSet<T> {
|
||||||
fn from_iter<Iter: Iterator<Item=T>>(iter: Iter) -> BTreeSet<T> {
|
fn from_iter<I: IntoIterator<Item=T>>(iter: I) -> BTreeSet<T> {
|
||||||
let mut set = BTreeSet::new();
|
let mut set = BTreeSet::new();
|
||||||
set.extend(iter);
|
set.extend(iter);
|
||||||
set
|
set
|
||||||
@ -503,7 +503,7 @@ impl<'a, T> IntoIterator for &'a BTreeSet<T> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Ord> Extend<T> for BTreeSet<T> {
|
impl<T: Ord> Extend<T> for BTreeSet<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn extend<Iter: Iterator<Item=T>>(&mut self, iter: Iter) {
|
fn extend<Iter: IntoIterator<Item=T>>(&mut self, iter: Iter) {
|
||||||
for elem in iter {
|
for elem in iter {
|
||||||
self.insert(elem);
|
self.insert(elem);
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
//! representation to hold C-like enum variants.
|
//! representation to hold C-like enum variants.
|
||||||
|
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
|
use core::marker;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::num::Int;
|
use core::num::Int;
|
||||||
use core::iter::{FromIterator, IntoIterator};
|
use core::iter::{FromIterator, IntoIterator};
|
||||||
@ -26,7 +27,8 @@ use core::ops::{Sub, BitOr, BitAnd, BitXor};
|
|||||||
pub struct EnumSet<E> {
|
pub struct EnumSet<E> {
|
||||||
// We must maintain the invariant that no bits are set
|
// We must maintain the invariant that no bits are set
|
||||||
// for which no variant exists
|
// for which no variant exists
|
||||||
bits: usize
|
bits: usize,
|
||||||
|
marker: marker::PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E> Copy for EnumSet<E> {}
|
impl<E> Copy for EnumSet<E> {}
|
||||||
@ -86,7 +88,7 @@ impl<E:CLike> EnumSet<E> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "matches collection reform specification, waiting for dust to settle")]
|
reason = "matches collection reform specification, waiting for dust to settle")]
|
||||||
pub fn new() -> EnumSet<E> {
|
pub fn new() -> EnumSet<E> {
|
||||||
EnumSet {bits: 0}
|
EnumSet {bits: 0, marker: marker::PhantomData}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of elements in the given `EnumSet`.
|
/// Returns the number of elements in the given `EnumSet`.
|
||||||
@ -130,12 +132,14 @@ impl<E:CLike> EnumSet<E> {
|
|||||||
|
|
||||||
/// Returns the union of both `EnumSets`.
|
/// Returns the union of both `EnumSets`.
|
||||||
pub fn union(&self, e: EnumSet<E>) -> EnumSet<E> {
|
pub fn union(&self, e: EnumSet<E>) -> EnumSet<E> {
|
||||||
EnumSet {bits: self.bits | e.bits}
|
EnumSet {bits: self.bits | e.bits,
|
||||||
|
marker: marker::PhantomData}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the intersection of both `EnumSets`.
|
/// Returns the intersection of both `EnumSets`.
|
||||||
pub fn intersection(&self, e: EnumSet<E>) -> EnumSet<E> {
|
pub fn intersection(&self, e: EnumSet<E>) -> EnumSet<E> {
|
||||||
EnumSet {bits: self.bits & e.bits}
|
EnumSet {bits: self.bits & e.bits,
|
||||||
|
marker: marker::PhantomData}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds an enum to the `EnumSet`, and returns `true` if it wasn't there before
|
/// Adds an enum to the `EnumSet`, and returns `true` if it wasn't there before
|
||||||
@ -175,7 +179,7 @@ impl<E:CLike> Sub for EnumSet<E> {
|
|||||||
type Output = EnumSet<E>;
|
type Output = EnumSet<E>;
|
||||||
|
|
||||||
fn sub(self, e: EnumSet<E>) -> EnumSet<E> {
|
fn sub(self, e: EnumSet<E>) -> EnumSet<E> {
|
||||||
EnumSet {bits: self.bits & !e.bits}
|
EnumSet {bits: self.bits & !e.bits, marker: marker::PhantomData}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -183,7 +187,7 @@ impl<E:CLike> BitOr for EnumSet<E> {
|
|||||||
type Output = EnumSet<E>;
|
type Output = EnumSet<E>;
|
||||||
|
|
||||||
fn bitor(self, e: EnumSet<E>) -> EnumSet<E> {
|
fn bitor(self, e: EnumSet<E>) -> EnumSet<E> {
|
||||||
EnumSet {bits: self.bits | e.bits}
|
EnumSet {bits: self.bits | e.bits, marker: marker::PhantomData}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,7 +195,7 @@ impl<E:CLike> BitAnd for EnumSet<E> {
|
|||||||
type Output = EnumSet<E>;
|
type Output = EnumSet<E>;
|
||||||
|
|
||||||
fn bitand(self, e: EnumSet<E>) -> EnumSet<E> {
|
fn bitand(self, e: EnumSet<E>) -> EnumSet<E> {
|
||||||
EnumSet {bits: self.bits & e.bits}
|
EnumSet {bits: self.bits & e.bits, marker: marker::PhantomData}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,7 +203,7 @@ impl<E:CLike> BitXor for EnumSet<E> {
|
|||||||
type Output = EnumSet<E>;
|
type Output = EnumSet<E>;
|
||||||
|
|
||||||
fn bitxor(self, e: EnumSet<E>) -> EnumSet<E> {
|
fn bitxor(self, e: EnumSet<E>) -> EnumSet<E> {
|
||||||
EnumSet {bits: self.bits ^ e.bits}
|
EnumSet {bits: self.bits ^ e.bits, marker: marker::PhantomData}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,6 +211,7 @@ impl<E:CLike> BitXor for EnumSet<E> {
|
|||||||
pub struct Iter<E> {
|
pub struct Iter<E> {
|
||||||
index: usize,
|
index: usize,
|
||||||
bits: usize,
|
bits: usize,
|
||||||
|
marker: marker::PhantomData<E>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
|
// FIXME(#19839) Remove in favor of `#[derive(Clone)]`
|
||||||
@ -215,13 +220,14 @@ impl<E> Clone for Iter<E> {
|
|||||||
Iter {
|
Iter {
|
||||||
index: self.index,
|
index: self.index,
|
||||||
bits: self.bits,
|
bits: self.bits,
|
||||||
|
marker: marker::PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<E:CLike> Iter<E> {
|
impl<E:CLike> Iter<E> {
|
||||||
fn new(bits: usize) -> Iter<E> {
|
fn new(bits: usize) -> Iter<E> {
|
||||||
Iter { index: 0, bits: bits }
|
Iter { index: 0, bits: bits, marker: marker::PhantomData }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -250,9 +256,9 @@ impl<E:CLike> Iterator for Iter<E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<E:CLike> FromIterator<E> for EnumSet<E> {
|
impl<E:CLike> FromIterator<E> for EnumSet<E> {
|
||||||
fn from_iter<I:Iterator<Item=E>>(iterator: I) -> EnumSet<E> {
|
fn from_iter<I: IntoIterator<Item=E>>(iter: I) -> EnumSet<E> {
|
||||||
let mut ret = EnumSet::new();
|
let mut ret = EnumSet::new();
|
||||||
ret.extend(iterator);
|
ret.extend(iter);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -268,8 +274,8 @@ impl<'a, E> IntoIterator for &'a EnumSet<E> where E: CLike {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<E:CLike> Extend<E> for EnumSet<E> {
|
impl<E:CLike> Extend<E> for EnumSet<E> {
|
||||||
fn extend<I: Iterator<Item=E>>(&mut self, iterator: I) {
|
fn extend<I: IntoIterator<Item=E>>(&mut self, iter: I) {
|
||||||
for element in iterator {
|
for element in iter {
|
||||||
self.insert(element);
|
self.insert(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,6 @@
|
|||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(box_patterns)]
|
#![feature(box_patterns)]
|
||||||
#![feature(core)]
|
#![feature(core)]
|
||||||
#![feature(hash)]
|
|
||||||
#![feature(staged_api)]
|
#![feature(staged_api)]
|
||||||
#![feature(unboxed_closures)]
|
#![feature(unboxed_closures)]
|
||||||
#![feature(unicode)]
|
#![feature(unicode)]
|
||||||
@ -49,17 +48,33 @@ extern crate alloc;
|
|||||||
#[cfg(test)] #[macro_use] extern crate log;
|
#[cfg(test)] #[macro_use] extern crate log;
|
||||||
|
|
||||||
pub use binary_heap::BinaryHeap;
|
pub use binary_heap::BinaryHeap;
|
||||||
pub use bitv::Bitv;
|
pub use bit_vec::BitVec;
|
||||||
pub use bitv_set::BitvSet;
|
pub use bit_set::BitSet;
|
||||||
pub use btree_map::BTreeMap;
|
pub use btree_map::BTreeMap;
|
||||||
pub use btree_set::BTreeSet;
|
pub use btree_set::BTreeSet;
|
||||||
pub use dlist::DList;
|
pub use linked_list::LinkedList;
|
||||||
pub use enum_set::EnumSet;
|
pub use enum_set::EnumSet;
|
||||||
pub use ring_buf::RingBuf;
|
pub use vec_deque::VecDeque;
|
||||||
pub use string::String;
|
pub use string::String;
|
||||||
pub use vec::Vec;
|
pub use vec::Vec;
|
||||||
pub use vec_map::VecMap;
|
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
|
// Needed for the vec! macro
|
||||||
pub use alloc::boxed;
|
pub use alloc::boxed;
|
||||||
|
|
||||||
@ -71,27 +86,42 @@ mod macros;
|
|||||||
pub mod binary_heap;
|
pub mod binary_heap;
|
||||||
mod bit;
|
mod bit;
|
||||||
mod btree;
|
mod btree;
|
||||||
pub mod dlist;
|
pub mod linked_list;
|
||||||
pub mod enum_set;
|
pub mod enum_set;
|
||||||
pub mod fmt;
|
pub mod fmt;
|
||||||
pub mod ring_buf;
|
pub mod vec_deque;
|
||||||
pub mod slice;
|
pub mod slice;
|
||||||
pub mod str;
|
pub mod str;
|
||||||
pub mod string;
|
pub mod string;
|
||||||
pub mod vec;
|
pub mod vec;
|
||||||
pub mod vec_map;
|
pub mod vec_map;
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
|
#[path = "borrow_stage0.rs"]
|
||||||
|
pub mod borrow;
|
||||||
|
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
pub mod borrow;
|
||||||
|
|
||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "RFC 509")]
|
reason = "RFC 509")]
|
||||||
pub mod bitv {
|
pub mod bit_vec {
|
||||||
pub use bit::{Bitv, Iter};
|
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",
|
#[unstable(feature = "collections",
|
||||||
reason = "RFC 509")]
|
reason = "RFC 509")]
|
||||||
pub mod bitv_set {
|
pub mod bit_set {
|
||||||
pub use bit::{BitvSet, Union, Intersection, Difference, SymmetricDifference};
|
pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference};
|
||||||
pub use bit::SetIter as Iter;
|
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")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@ -117,7 +147,6 @@ mod std {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod prelude {
|
mod prelude {
|
||||||
// from core.
|
// from core.
|
||||||
pub use core::borrow::IntoCow;
|
|
||||||
pub use core::clone::Clone;
|
pub use core::clone::Clone;
|
||||||
pub use core::cmp::{PartialEq, Eq, PartialOrd, Ord};
|
pub use core::cmp::{PartialEq, Eq, PartialOrd, Ord};
|
||||||
pub use core::cmp::Ordering::{Less, Equal, Greater};
|
pub use core::cmp::Ordering::{Less, Equal, Greater};
|
||||||
@ -143,6 +172,7 @@ mod prelude {
|
|||||||
pub use unicode::char::CharExt;
|
pub use unicode::char::CharExt;
|
||||||
|
|
||||||
// from collections.
|
// from collections.
|
||||||
|
pub use borrow::IntoCow;
|
||||||
pub use slice::SliceConcatExt;
|
pub use slice::SliceConcatExt;
|
||||||
pub use string::{String, ToString};
|
pub use string::{String, ToString};
|
||||||
pub use vec::Vec;
|
pub use vec::Vec;
|
||||||
|
@ -10,13 +10,13 @@
|
|||||||
|
|
||||||
//! A doubly-linked list with owned nodes.
|
//! A doubly-linked list with owned nodes.
|
||||||
//!
|
//!
|
||||||
//! The `DList` allows pushing and popping elements at either end and is thus
|
//! The `LinkedList` allows pushing and popping elements at either end and is thus
|
||||||
//! efficiently usable as a double-ended queue.
|
//! efficiently usable as a double-ended queue.
|
||||||
|
|
||||||
// DList is constructed like a singly-linked list over the field `next`.
|
// LinkedList is constructed like a singly-linked list over the field `next`.
|
||||||
// including the last link being None; each Node owns its `next` field.
|
// 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
|
// Backlinks over LinkedList::prev are raw pointers that form a full chain in
|
||||||
// the reverse direction.
|
// the reverse direction.
|
||||||
|
|
||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
@ -27,14 +27,20 @@ use alloc::boxed::Box;
|
|||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::hash::{Writer, Hasher, Hash};
|
use core::hash::{Hasher, Hash};
|
||||||
|
#[cfg(stage0)]
|
||||||
|
use core::hash::Writer;
|
||||||
use core::iter::{self, FromIterator, IntoIterator};
|
use core::iter::{self, FromIterator, IntoIterator};
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
|
||||||
|
#[deprecated(since = "1.0.0", reason = "renamed to LinkedList")]
|
||||||
|
#[unstable(feature = "collections")]
|
||||||
|
pub use LinkedList as DList;
|
||||||
|
|
||||||
/// A doubly-linked list.
|
/// A doubly-linked list.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct DList<T> {
|
pub struct LinkedList<T> {
|
||||||
length: usize,
|
length: usize,
|
||||||
list_head: Link<T>,
|
list_head: Link<T>,
|
||||||
list_tail: Rawlink<Node<T>>,
|
list_tail: Rawlink<Node<T>>,
|
||||||
@ -56,7 +62,7 @@ struct Node<T> {
|
|||||||
value: T,
|
value: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over references to the items of a `DList`.
|
/// An iterator over references to the items of a `LinkedList`.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct Iter<'a, T:'a> {
|
pub struct Iter<'a, T:'a> {
|
||||||
head: &'a Link<T>,
|
head: &'a Link<T>,
|
||||||
@ -76,20 +82,20 @@ impl<'a, T> Clone for Iter<'a, T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over mutable references to the items of a `DList`.
|
/// An iterator over mutable references to the items of a `LinkedList`.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct IterMut<'a, T:'a> {
|
pub struct IterMut<'a, T:'a> {
|
||||||
list: &'a mut DList<T>,
|
list: &'a mut LinkedList<T>,
|
||||||
head: Rawlink<Node<T>>,
|
head: Rawlink<Node<T>>,
|
||||||
tail: Rawlink<Node<T>>,
|
tail: Rawlink<Node<T>>,
|
||||||
nelem: usize,
|
nelem: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over mutable references to the items of a `DList`.
|
/// An iterator over mutable references to the items of a `LinkedList`.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct IntoIter<T> {
|
pub struct IntoIter<T> {
|
||||||
list: DList<T>
|
list: LinkedList<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Rawlink is a type like Option<T> but for holding a raw pointer
|
/// Rawlink is a type like Option<T> but for holding a raw pointer
|
||||||
@ -147,7 +153,7 @@ fn link_with_prev<T>(mut next: Box<Node<T>>, prev: Rawlink<Node<T>>)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// private methods
|
// private methods
|
||||||
impl<T> DList<T> {
|
impl<T> LinkedList<T> {
|
||||||
/// Add a Node first in the list
|
/// Add a Node first in the list
|
||||||
#[inline]
|
#[inline]
|
||||||
fn push_front_node(&mut self, mut new_head: Box<Node<T>>) {
|
fn push_front_node(&mut self, mut new_head: Box<Node<T>>) {
|
||||||
@ -207,18 +213,18 @@ impl<T> DList<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> Default for DList<T> {
|
impl<T> Default for LinkedList<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn default() -> DList<T> { DList::new() }
|
fn default() -> LinkedList<T> { LinkedList::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> DList<T> {
|
impl<T> LinkedList<T> {
|
||||||
/// Creates an empty `DList`.
|
/// Creates an empty `LinkedList`.
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn new() -> DList<T> {
|
pub fn new() -> LinkedList<T> {
|
||||||
DList{list_head: None, list_tail: Rawlink::none(), length: 0}
|
LinkedList{list_head: None, list_tail: Rawlink::none(), length: 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Moves all elements from `other` to the end of the list.
|
/// Moves all elements from `other` to the end of the list.
|
||||||
@ -231,10 +237,10 @@ impl<T> DList<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut a = DList::new();
|
/// let mut a = LinkedList::new();
|
||||||
/// let mut b = DList::new();
|
/// let mut b = LinkedList::new();
|
||||||
/// a.push_back(1);
|
/// a.push_back(1);
|
||||||
/// a.push_back(2);
|
/// a.push_back(2);
|
||||||
/// b.push_back(3);
|
/// b.push_back(3);
|
||||||
@ -247,7 +253,7 @@ impl<T> DList<T> {
|
|||||||
/// }
|
/// }
|
||||||
/// println!("{}", b.len()); // prints 0
|
/// println!("{}", b.len()); // prints 0
|
||||||
/// ```
|
/// ```
|
||||||
pub fn append(&mut self, other: &mut DList<T>) {
|
pub fn append(&mut self, other: &mut LinkedList<T>) {
|
||||||
match self.list_tail.resolve() {
|
match self.list_tail.resolve() {
|
||||||
None => {
|
None => {
|
||||||
self.length = other.length;
|
self.length = other.length;
|
||||||
@ -301,16 +307,16 @@ impl<T> DList<T> {
|
|||||||
IntoIter{list: self}
|
IntoIter{list: self}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `true` if the `DList` is empty.
|
/// Returns `true` if the `LinkedList` is empty.
|
||||||
///
|
///
|
||||||
/// This operation should compute in O(1) time.
|
/// This operation should compute in O(1) time.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut dl = DList::new();
|
/// let mut dl = LinkedList::new();
|
||||||
/// assert!(dl.is_empty());
|
/// assert!(dl.is_empty());
|
||||||
///
|
///
|
||||||
/// dl.push_front("foo");
|
/// dl.push_front("foo");
|
||||||
@ -322,16 +328,16 @@ impl<T> DList<T> {
|
|||||||
self.list_head.is_none()
|
self.list_head.is_none()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the length of the `DList`.
|
/// Returns the length of the `LinkedList`.
|
||||||
///
|
///
|
||||||
/// This operation should compute in O(1) time.
|
/// This operation should compute in O(1) time.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut dl = DList::new();
|
/// let mut dl = LinkedList::new();
|
||||||
///
|
///
|
||||||
/// dl.push_front(2);
|
/// dl.push_front(2);
|
||||||
/// assert_eq!(dl.len(), 1);
|
/// assert_eq!(dl.len(), 1);
|
||||||
@ -349,16 +355,16 @@ impl<T> DList<T> {
|
|||||||
self.length
|
self.length
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes all elements from the `DList`.
|
/// Removes all elements from the `LinkedList`.
|
||||||
///
|
///
|
||||||
/// This operation should compute in O(n) time.
|
/// This operation should compute in O(n) time.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut dl = DList::new();
|
/// let mut dl = LinkedList::new();
|
||||||
///
|
///
|
||||||
/// dl.push_front(2);
|
/// dl.push_front(2);
|
||||||
/// dl.push_front(1);
|
/// dl.push_front(1);
|
||||||
@ -373,7 +379,7 @@ impl<T> DList<T> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn clear(&mut self) {
|
pub fn clear(&mut self) {
|
||||||
*self = DList::new()
|
*self = LinkedList::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides a reference to the front element, or `None` if the list is
|
/// Provides a reference to the front element, or `None` if the list is
|
||||||
@ -382,9 +388,9 @@ impl<T> DList<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut dl = DList::new();
|
/// let mut dl = LinkedList::new();
|
||||||
/// assert_eq!(dl.front(), None);
|
/// assert_eq!(dl.front(), None);
|
||||||
///
|
///
|
||||||
/// dl.push_front(1);
|
/// dl.push_front(1);
|
||||||
@ -403,9 +409,9 @@ impl<T> DList<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut dl = DList::new();
|
/// let mut dl = LinkedList::new();
|
||||||
/// assert_eq!(dl.front(), None);
|
/// assert_eq!(dl.front(), None);
|
||||||
///
|
///
|
||||||
/// dl.push_front(1);
|
/// dl.push_front(1);
|
||||||
@ -430,9 +436,9 @@ impl<T> DList<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut dl = DList::new();
|
/// let mut dl = LinkedList::new();
|
||||||
/// assert_eq!(dl.back(), None);
|
/// assert_eq!(dl.back(), None);
|
||||||
///
|
///
|
||||||
/// dl.push_back(1);
|
/// dl.push_back(1);
|
||||||
@ -451,9 +457,9 @@ impl<T> DList<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut dl = DList::new();
|
/// let mut dl = LinkedList::new();
|
||||||
/// assert_eq!(dl.back(), None);
|
/// assert_eq!(dl.back(), None);
|
||||||
///
|
///
|
||||||
/// dl.push_back(1);
|
/// dl.push_back(1);
|
||||||
@ -479,9 +485,9 @@ impl<T> DList<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut dl = DList::new();
|
/// let mut dl = LinkedList::new();
|
||||||
///
|
///
|
||||||
/// dl.push_front(2);
|
/// dl.push_front(2);
|
||||||
/// assert_eq!(dl.front().unwrap(), &2);
|
/// assert_eq!(dl.front().unwrap(), &2);
|
||||||
@ -503,9 +509,9 @@ impl<T> DList<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut d = DList::new();
|
/// let mut d = LinkedList::new();
|
||||||
/// assert_eq!(d.pop_front(), None);
|
/// assert_eq!(d.pop_front(), None);
|
||||||
///
|
///
|
||||||
/// d.push_front(1);
|
/// d.push_front(1);
|
||||||
@ -526,9 +532,9 @@ impl<T> DList<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut d = DList::new();
|
/// let mut d = LinkedList::new();
|
||||||
/// d.push_back(1);
|
/// d.push_back(1);
|
||||||
/// d.push_back(3);
|
/// d.push_back(3);
|
||||||
/// assert_eq!(3, *d.back().unwrap());
|
/// assert_eq!(3, *d.back().unwrap());
|
||||||
@ -544,9 +550,9 @@ impl<T> DList<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut d = DList::new();
|
/// let mut d = LinkedList::new();
|
||||||
/// assert_eq!(d.pop_back(), None);
|
/// assert_eq!(d.pop_back(), None);
|
||||||
/// d.push_back(1);
|
/// d.push_back(1);
|
||||||
/// d.push_back(3);
|
/// d.push_back(3);
|
||||||
@ -569,9 +575,9 @@ impl<T> DList<T> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut d = DList::new();
|
/// let mut d = LinkedList::new();
|
||||||
///
|
///
|
||||||
/// d.push_front(1);
|
/// d.push_front(1);
|
||||||
/// d.push_front(2);
|
/// d.push_front(2);
|
||||||
@ -583,13 +589,13 @@ impl<T> DList<T> {
|
|||||||
/// assert_eq!(splitted.pop_front(), None);
|
/// assert_eq!(splitted.pop_front(), None);
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn split_off(&mut self, at: usize) -> DList<T> {
|
pub fn split_off(&mut self, at: usize) -> LinkedList<T> {
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
assert!(at <= len, "Cannot split off at a nonexistent index");
|
assert!(at <= len, "Cannot split off at a nonexistent index");
|
||||||
if at == 0 {
|
if at == 0 {
|
||||||
return mem::replace(self, DList::new());
|
return mem::replace(self, LinkedList::new());
|
||||||
} else if at == len {
|
} else if at == len {
|
||||||
return DList::new();
|
return LinkedList::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Below, we iterate towards the `i-1`th node, either from the start or the end,
|
// Below, we iterate towards the `i-1`th node, either from the start or the end,
|
||||||
@ -612,7 +618,7 @@ impl<T> DList<T> {
|
|||||||
iter.tail
|
iter.tail
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut splitted_list = DList {
|
let mut splitted_list = LinkedList {
|
||||||
list_head: None,
|
list_head: None,
|
||||||
list_tail: self.list_tail,
|
list_tail: self.list_tail,
|
||||||
length: len - at
|
length: len - at
|
||||||
@ -628,9 +634,9 @@ impl<T> DList<T> {
|
|||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> Drop for DList<T> {
|
impl<T> Drop for LinkedList<T> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
// Dissolve the dlist in backwards direction
|
// Dissolve the linked_list in backwards direction
|
||||||
// Just dropping the list_head can lead to stack exhaustion
|
// Just dropping the list_head can lead to stack exhaustion
|
||||||
// when length is >> 1_000_000
|
// when length is >> 1_000_000
|
||||||
let mut tail = self.list_tail;
|
let mut tail = self.list_tail;
|
||||||
@ -761,9 +767,9 @@ impl<'a, A> IterMut<'a, A> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut list: DList<_> = vec![1, 3, 4].into_iter().collect();
|
/// let mut list: LinkedList<_> = vec![1, 3, 4].into_iter().collect();
|
||||||
///
|
///
|
||||||
/// {
|
/// {
|
||||||
/// let mut it = list.iter_mut();
|
/// let mut it = list.iter_mut();
|
||||||
@ -788,9 +794,9 @@ impl<'a, A> IterMut<'a, A> {
|
|||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use std::collections::DList;
|
/// use std::collections::LinkedList;
|
||||||
///
|
///
|
||||||
/// let mut list: DList<_> = vec![1, 2, 3].into_iter().collect();
|
/// let mut list: LinkedList<_> = vec![1, 2, 3].into_iter().collect();
|
||||||
///
|
///
|
||||||
/// let mut it = list.iter_mut();
|
/// let mut it = list.iter_mut();
|
||||||
/// assert_eq!(it.next().unwrap(), &1);
|
/// assert_eq!(it.next().unwrap(), &1);
|
||||||
@ -829,16 +835,16 @@ impl<A> DoubleEndedIterator for IntoIter<A> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<A> FromIterator<A> for DList<A> {
|
impl<A> FromIterator<A> for LinkedList<A> {
|
||||||
fn from_iter<T: Iterator<Item=A>>(iterator: T) -> DList<A> {
|
fn from_iter<T: IntoIterator<Item=A>>(iter: T) -> LinkedList<A> {
|
||||||
let mut ret = DList::new();
|
let mut ret = DList::new();
|
||||||
ret.extend(iterator);
|
ret.extend(iter);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> IntoIterator for DList<T> {
|
impl<T> IntoIterator for LinkedList<T> {
|
||||||
type Item = T;
|
type Item = T;
|
||||||
type IntoIter = IntoIter<T>;
|
type IntoIter = IntoIter<T>;
|
||||||
|
|
||||||
@ -848,7 +854,7 @@ impl<T> IntoIterator for DList<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a, T> IntoIterator for &'a DList<T> {
|
impl<'a, T> IntoIterator for &'a LinkedList<T> {
|
||||||
type Item = &'a T;
|
type Item = &'a T;
|
||||||
type IntoIter = Iter<'a, T>;
|
type IntoIter = Iter<'a, T>;
|
||||||
|
|
||||||
@ -857,7 +863,7 @@ impl<'a, T> IntoIterator for &'a DList<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> IntoIterator for &'a mut DList<T> {
|
impl<'a, T> IntoIterator for &'a mut LinkedList<T> {
|
||||||
type Item = &'a mut T;
|
type Item = &'a mut T;
|
||||||
type IntoIter = IterMut<'a, T>;
|
type IntoIter = IterMut<'a, T>;
|
||||||
|
|
||||||
@ -867,54 +873,54 @@ impl<'a, T> IntoIterator for &'a mut DList<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<A> Extend<A> for DList<A> {
|
impl<A> Extend<A> for LinkedList<A> {
|
||||||
fn extend<T: Iterator<Item=A>>(&mut self, iterator: T) {
|
fn extend<T: IntoIterator<Item=A>>(&mut self, iter: T) {
|
||||||
for elt in iterator { self.push_back(elt); }
|
for elt in iter { self.push_back(elt); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<A: PartialEq> PartialEq for DList<A> {
|
impl<A: PartialEq> PartialEq for LinkedList<A> {
|
||||||
fn eq(&self, other: &DList<A>) -> bool {
|
fn eq(&self, other: &LinkedList<A>) -> bool {
|
||||||
self.len() == other.len() &&
|
self.len() == other.len() &&
|
||||||
iter::order::eq(self.iter(), other.iter())
|
iter::order::eq(self.iter(), other.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ne(&self, other: &DList<A>) -> bool {
|
fn ne(&self, other: &LinkedList<A>) -> bool {
|
||||||
self.len() != other.len() ||
|
self.len() != other.len() ||
|
||||||
iter::order::ne(self.iter(), other.iter())
|
iter::order::ne(self.iter(), other.iter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<A: Eq> Eq for DList<A> {}
|
impl<A: Eq> Eq for LinkedList<A> {}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<A: PartialOrd> PartialOrd for DList<A> {
|
impl<A: PartialOrd> PartialOrd for LinkedList<A> {
|
||||||
fn partial_cmp(&self, other: &DList<A>) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &LinkedList<A>) -> Option<Ordering> {
|
||||||
iter::order::partial_cmp(self.iter(), other.iter())
|
iter::order::partial_cmp(self.iter(), other.iter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<A: Ord> Ord for DList<A> {
|
impl<A: Ord> Ord for LinkedList<A> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn cmp(&self, other: &DList<A>) -> Ordering {
|
fn cmp(&self, other: &LinkedList<A>) -> Ordering {
|
||||||
iter::order::cmp(self.iter(), other.iter())
|
iter::order::cmp(self.iter(), other.iter())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<A: Clone> Clone for DList<A> {
|
impl<A: Clone> Clone for LinkedList<A> {
|
||||||
fn clone(&self) -> DList<A> {
|
fn clone(&self) -> LinkedList<A> {
|
||||||
self.iter().map(|x| x.clone()).collect()
|
self.iter().cloned().collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<A: fmt::Debug> fmt::Debug for DList<A> {
|
impl<A: fmt::Debug> fmt::Debug for LinkedList<A> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
try!(write!(f, "DList ["));
|
try!(write!(f, "LinkedList ["));
|
||||||
|
|
||||||
for (i, e) in self.iter().enumerate() {
|
for (i, e) in self.iter().enumerate() {
|
||||||
if i != 0 { try!(write!(f, ", ")); }
|
if i != 0 { try!(write!(f, ", ")); }
|
||||||
@ -926,7 +932,8 @@ impl<A: fmt::Debug> fmt::Debug for DList<A> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for DList<A> {
|
#[cfg(stage0)]
|
||||||
|
impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for LinkedList<A> {
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
self.len().hash(state);
|
self.len().hash(state);
|
||||||
for elt in self {
|
for elt in self {
|
||||||
@ -934,6 +941,16 @@ impl<S: Writer + Hasher, A: Hash<S>> Hash<S> for DList<A> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
impl<A: Hash> Hash for LinkedList<A> {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.len().hash(state);
|
||||||
|
for elt in self {
|
||||||
|
elt.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
@ -944,9 +961,9 @@ mod tests {
|
|||||||
use test::Bencher;
|
use test::Bencher;
|
||||||
use test;
|
use test;
|
||||||
|
|
||||||
use super::{DList, Node};
|
use super::{LinkedList, Node};
|
||||||
|
|
||||||
pub fn check_links<T>(list: &DList<T>) {
|
pub fn check_links<T>(list: &LinkedList<T>) {
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
let mut last_ptr: Option<&Node<T>> = None;
|
let mut last_ptr: Option<&Node<T>> = None;
|
||||||
let mut node_ptr: &Node<T>;
|
let mut node_ptr: &Node<T>;
|
||||||
@ -980,7 +997,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic() {
|
fn test_basic() {
|
||||||
let mut m = DList::new();
|
let mut m = LinkedList::new();
|
||||||
assert_eq!(m.pop_front(), None);
|
assert_eq!(m.pop_front(), None);
|
||||||
assert_eq!(m.pop_back(), None);
|
assert_eq!(m.pop_back(), None);
|
||||||
assert_eq!(m.pop_front(), None);
|
assert_eq!(m.pop_front(), None);
|
||||||
@ -999,7 +1016,7 @@ mod tests {
|
|||||||
m.push_back(box 7);
|
m.push_back(box 7);
|
||||||
assert_eq!(m.pop_front(), Some(box 1));
|
assert_eq!(m.pop_front(), Some(box 1));
|
||||||
|
|
||||||
let mut n = DList::new();
|
let mut n = LinkedList::new();
|
||||||
n.push_front(2);
|
n.push_front(2);
|
||||||
n.push_front(3);
|
n.push_front(3);
|
||||||
{
|
{
|
||||||
@ -1019,21 +1036,21 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn generate_test() -> DList<i32> {
|
fn generate_test() -> LinkedList<i32> {
|
||||||
list_from(&[0,1,2,3,4,5,6])
|
list_from(&[0,1,2,3,4,5,6])
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn list_from<T: Clone>(v: &[T]) -> DList<T> {
|
fn list_from<T: Clone>(v: &[T]) -> LinkedList<T> {
|
||||||
v.iter().map(|x| (*x).clone()).collect()
|
v.iter().cloned().collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_append() {
|
fn test_append() {
|
||||||
// Empty to empty
|
// Empty to empty
|
||||||
{
|
{
|
||||||
let mut m = DList::<i32>::new();
|
let mut m = LinkedList::<i32>::new();
|
||||||
let mut n = DList::new();
|
let mut n = LinkedList::new();
|
||||||
m.append(&mut n);
|
m.append(&mut n);
|
||||||
check_links(&m);
|
check_links(&m);
|
||||||
assert_eq!(m.len(), 0);
|
assert_eq!(m.len(), 0);
|
||||||
@ -1041,8 +1058,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
// Non-empty to empty
|
// Non-empty to empty
|
||||||
{
|
{
|
||||||
let mut m = DList::new();
|
let mut m = LinkedList::new();
|
||||||
let mut n = DList::new();
|
let mut n = LinkedList::new();
|
||||||
n.push_back(2);
|
n.push_back(2);
|
||||||
m.append(&mut n);
|
m.append(&mut n);
|
||||||
check_links(&m);
|
check_links(&m);
|
||||||
@ -1053,8 +1070,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
// Empty to non-empty
|
// Empty to non-empty
|
||||||
{
|
{
|
||||||
let mut m = DList::new();
|
let mut m = LinkedList::new();
|
||||||
let mut n = DList::new();
|
let mut n = LinkedList::new();
|
||||||
m.push_back(2);
|
m.push_back(2);
|
||||||
m.append(&mut n);
|
m.append(&mut n);
|
||||||
check_links(&m);
|
check_links(&m);
|
||||||
@ -1089,7 +1106,7 @@ mod tests {
|
|||||||
fn test_split_off() {
|
fn test_split_off() {
|
||||||
// singleton
|
// singleton
|
||||||
{
|
{
|
||||||
let mut m = DList::new();
|
let mut m = LinkedList::new();
|
||||||
m.push_back(1);
|
m.push_back(1);
|
||||||
|
|
||||||
let p = m.split_off(0);
|
let p = m.split_off(0);
|
||||||
@ -1130,7 +1147,7 @@ mod tests {
|
|||||||
|
|
||||||
// no-op on the last index
|
// no-op on the last index
|
||||||
{
|
{
|
||||||
let mut m = DList::new();
|
let mut m = LinkedList::new();
|
||||||
m.push_back(1);
|
m.push_back(1);
|
||||||
|
|
||||||
let p = m.split_off(1);
|
let p = m.split_off(1);
|
||||||
@ -1148,7 +1165,7 @@ mod tests {
|
|||||||
for (i, elt) in m.iter().enumerate() {
|
for (i, elt) in m.iter().enumerate() {
|
||||||
assert_eq!(i as i32, *elt);
|
assert_eq!(i as i32, *elt);
|
||||||
}
|
}
|
||||||
let mut n = DList::new();
|
let mut n = LinkedList::new();
|
||||||
assert_eq!(n.iter().next(), None);
|
assert_eq!(n.iter().next(), None);
|
||||||
n.push_front(4);
|
n.push_front(4);
|
||||||
let mut it = n.iter();
|
let mut it = n.iter();
|
||||||
@ -1160,7 +1177,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iterator_clone() {
|
fn test_iterator_clone() {
|
||||||
let mut n = DList::new();
|
let mut n = LinkedList::new();
|
||||||
n.push_back(2);
|
n.push_back(2);
|
||||||
n.push_back(3);
|
n.push_back(3);
|
||||||
n.push_back(4);
|
n.push_back(4);
|
||||||
@ -1174,7 +1191,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iterator_double_end() {
|
fn test_iterator_double_end() {
|
||||||
let mut n = DList::new();
|
let mut n = LinkedList::new();
|
||||||
assert_eq!(n.iter().next(), None);
|
assert_eq!(n.iter().next(), None);
|
||||||
n.push_front(4);
|
n.push_front(4);
|
||||||
n.push_front(5);
|
n.push_front(5);
|
||||||
@ -1196,7 +1213,7 @@ mod tests {
|
|||||||
for (i, elt) in m.iter().rev().enumerate() {
|
for (i, elt) in m.iter().rev().enumerate() {
|
||||||
assert_eq!((6 - i) as i32, *elt);
|
assert_eq!((6 - i) as i32, *elt);
|
||||||
}
|
}
|
||||||
let mut n = DList::new();
|
let mut n = LinkedList::new();
|
||||||
assert_eq!(n.iter().rev().next(), None);
|
assert_eq!(n.iter().rev().next(), None);
|
||||||
n.push_front(4);
|
n.push_front(4);
|
||||||
let mut it = n.iter().rev();
|
let mut it = n.iter().rev();
|
||||||
@ -1215,7 +1232,7 @@ mod tests {
|
|||||||
len -= 1;
|
len -= 1;
|
||||||
}
|
}
|
||||||
assert_eq!(len, 0);
|
assert_eq!(len, 0);
|
||||||
let mut n = DList::new();
|
let mut n = LinkedList::new();
|
||||||
assert!(n.iter_mut().next().is_none());
|
assert!(n.iter_mut().next().is_none());
|
||||||
n.push_front(4);
|
n.push_front(4);
|
||||||
n.push_back(5);
|
n.push_back(5);
|
||||||
@ -1229,7 +1246,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iterator_mut_double_end() {
|
fn test_iterator_mut_double_end() {
|
||||||
let mut n = DList::new();
|
let mut n = LinkedList::new();
|
||||||
assert!(n.iter_mut().next_back().is_none());
|
assert!(n.iter_mut().next_back().is_none());
|
||||||
n.push_front(4);
|
n.push_front(4);
|
||||||
n.push_front(5);
|
n.push_front(5);
|
||||||
@ -1278,7 +1295,7 @@ mod tests {
|
|||||||
for (i, elt) in m.iter_mut().rev().enumerate() {
|
for (i, elt) in m.iter_mut().rev().enumerate() {
|
||||||
assert_eq!((6 - i) as i32, *elt);
|
assert_eq!((6 - i) as i32, *elt);
|
||||||
}
|
}
|
||||||
let mut n = DList::new();
|
let mut n = LinkedList::new();
|
||||||
assert!(n.iter_mut().rev().next().is_none());
|
assert!(n.iter_mut().rev().next().is_none());
|
||||||
n.push_front(4);
|
n.push_front(4);
|
||||||
let mut it = n.iter_mut().rev();
|
let mut it = n.iter_mut().rev();
|
||||||
@ -1313,8 +1330,8 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_hash() {
|
fn test_hash() {
|
||||||
let mut x = DList::new();
|
let mut x = LinkedList::new();
|
||||||
let mut y = DList::new();
|
let mut y = LinkedList::new();
|
||||||
|
|
||||||
assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y));
|
assert!(hash::hash::<_, SipHasher>(&x) == hash::hash::<_, SipHasher>(&y));
|
||||||
|
|
||||||
@ -1382,16 +1399,16 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_show() {
|
fn test_show() {
|
||||||
let list: DList<_> = (0..10).collect();
|
let list: LinkedList<_> = (0..10).collect();
|
||||||
assert_eq!(format!("{:?}", list), "DList [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
|
assert_eq!(format!("{:?}", list), "LinkedList [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
|
||||||
|
|
||||||
let list: DList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect();
|
let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect();
|
||||||
assert_eq!(format!("{:?}", list), "DList [\"just\", \"one\", \"test\", \"more\"]");
|
assert_eq!(format!("{:?}", list), "LinkedList [\"just\", \"one\", \"test\", \"more\"]");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn fuzz_test(sz: i32) {
|
fn fuzz_test(sz: i32) {
|
||||||
let mut m: DList<_> = DList::new();
|
let mut m: LinkedList<_> = LinkedList::new();
|
||||||
let mut v = vec![];
|
let mut v = vec![];
|
||||||
for i in 0..sz {
|
for i in 0..sz {
|
||||||
check_links(&m);
|
check_links(&m);
|
||||||
@ -1432,13 +1449,13 @@ mod tests {
|
|||||||
fn bench_collect_into(b: &mut test::Bencher) {
|
fn bench_collect_into(b: &mut test::Bencher) {
|
||||||
let v = &[0; 64];
|
let v = &[0; 64];
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let _: DList<_> = v.iter().cloned().collect();
|
let _: LinkedList<_> = v.iter().cloned().collect();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_push_front(b: &mut test::Bencher) {
|
fn bench_push_front(b: &mut test::Bencher) {
|
||||||
let mut m: DList<_> = DList::new();
|
let mut m: LinkedList<_> = LinkedList::new();
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
m.push_front(0);
|
m.push_front(0);
|
||||||
})
|
})
|
||||||
@ -1446,7 +1463,7 @@ mod tests {
|
|||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_push_back(b: &mut test::Bencher) {
|
fn bench_push_back(b: &mut test::Bencher) {
|
||||||
let mut m: DList<_> = DList::new();
|
let mut m: LinkedList<_> = LinkedList::new();
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
m.push_back(0);
|
m.push_back(0);
|
||||||
})
|
})
|
||||||
@ -1454,7 +1471,7 @@ mod tests {
|
|||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_push_back_pop_back(b: &mut test::Bencher) {
|
fn bench_push_back_pop_back(b: &mut test::Bencher) {
|
||||||
let mut m: DList<_> = DList::new();
|
let mut m: LinkedList<_> = LinkedList::new();
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
m.push_back(0);
|
m.push_back(0);
|
||||||
m.pop_back();
|
m.pop_back();
|
||||||
@ -1463,7 +1480,7 @@ mod tests {
|
|||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_push_front_pop_front(b: &mut test::Bencher) {
|
fn bench_push_front_pop_front(b: &mut test::Bencher) {
|
||||||
let mut m: DList<_> = DList::new();
|
let mut m: LinkedList<_> = LinkedList::new();
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
m.push_front(0);
|
m.push_front(0);
|
||||||
m.pop_front();
|
m.pop_front();
|
||||||
@ -1473,7 +1490,7 @@ mod tests {
|
|||||||
#[bench]
|
#[bench]
|
||||||
fn bench_iter(b: &mut test::Bencher) {
|
fn bench_iter(b: &mut test::Bencher) {
|
||||||
let v = &[0; 128];
|
let v = &[0; 128];
|
||||||
let m: DList<_> = v.iter().cloned().collect();
|
let m: LinkedList<_> = v.iter().cloned().collect();
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
assert!(m.iter().count() == 128);
|
assert!(m.iter().count() == 128);
|
||||||
})
|
})
|
||||||
@ -1481,7 +1498,7 @@ mod tests {
|
|||||||
#[bench]
|
#[bench]
|
||||||
fn bench_iter_mut(b: &mut test::Bencher) {
|
fn bench_iter_mut(b: &mut test::Bencher) {
|
||||||
let v = &[0; 128];
|
let v = &[0; 128];
|
||||||
let mut m: DList<_> = v.iter().cloned().collect();
|
let mut m: LinkedList<_> = v.iter().cloned().collect();
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
assert!(m.iter_mut().count() == 128);
|
assert!(m.iter_mut().count() == 128);
|
||||||
})
|
})
|
||||||
@ -1489,7 +1506,7 @@ mod tests {
|
|||||||
#[bench]
|
#[bench]
|
||||||
fn bench_iter_rev(b: &mut test::Bencher) {
|
fn bench_iter_rev(b: &mut test::Bencher) {
|
||||||
let v = &[0; 128];
|
let v = &[0; 128];
|
||||||
let m: DList<_> = v.iter().cloned().collect();
|
let m: LinkedList<_> = v.iter().cloned().collect();
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
assert!(m.iter().rev().count() == 128);
|
assert!(m.iter().rev().count() == 128);
|
||||||
})
|
})
|
||||||
@ -1497,7 +1514,7 @@ mod tests {
|
|||||||
#[bench]
|
#[bench]
|
||||||
fn bench_iter_mut_rev(b: &mut test::Bencher) {
|
fn bench_iter_mut_rev(b: &mut test::Bencher) {
|
||||||
let v = &[0; 128];
|
let v = &[0; 128];
|
||||||
let mut m: DList<_> = v.iter().cloned().collect();
|
let mut m: LinkedList<_> = v.iter().cloned().collect();
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
assert!(m.iter_mut().rev().count() == 128);
|
assert!(m.iter_mut().rev().count() == 128);
|
||||||
})
|
})
|
@ -88,7 +88,6 @@
|
|||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use core::borrow::{BorrowFrom, BorrowFromMut, ToOwned};
|
|
||||||
use core::clone::Clone;
|
use core::clone::Clone;
|
||||||
use core::cmp::Ordering::{self, Greater, Less};
|
use core::cmp::Ordering::{self, Greater, Less};
|
||||||
use core::cmp::{self, Ord, PartialEq};
|
use core::cmp::{self, Ord, PartialEq};
|
||||||
@ -105,6 +104,7 @@ use core::result::Result;
|
|||||||
use core::slice as core_slice;
|
use core::slice as core_slice;
|
||||||
use self::Direction::*;
|
use self::Direction::*;
|
||||||
|
|
||||||
|
use borrow::{Borrow, BorrowMut, ToOwned};
|
||||||
use vec::Vec;
|
use vec::Vec;
|
||||||
|
|
||||||
pub use core::slice::{Chunks, AsSlice, Windows};
|
pub use core::slice::{Chunks, AsSlice, Windows};
|
||||||
@ -1175,18 +1175,19 @@ impl ElementSwaps {
|
|||||||
// Standard trait implementations for slices
|
// Standard trait implementations for slices
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[unstable(feature = "collections", reason = "trait is unstable")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> BorrowFrom<Vec<T>> for [T] {
|
impl<T> Borrow<[T]> for Vec<T> {
|
||||||
fn borrow_from(owned: &Vec<T>) -> &[T] { &owned[] }
|
fn borrow(&self) -> &[T] { &self[..] }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections", reason = "trait is unstable")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> BorrowFromMut<Vec<T>> for [T] {
|
impl<T> BorrowMut<[T]> for Vec<T> {
|
||||||
fn borrow_from_mut(owned: &mut Vec<T>) -> &mut [T] { &mut owned[] }
|
fn borrow_mut(&mut self) -> &mut [T] { &mut self[..] }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections", reason = "trait is unstable")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Clone> ToOwned<Vec<T>> for [T] {
|
impl<T: Clone> ToOwned for [T] {
|
||||||
|
type Owned = Vec<T>;
|
||||||
fn to_owned(&self) -> Vec<T> { self.to_vec() }
|
fn to_owned(&self) -> Vec<T> { self.to_vec() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1743,7 +1744,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_slice_from() {
|
fn test_slice_from() {
|
||||||
let vec: &[_] = &[1, 2, 3, 4];
|
let vec: &[_] = &[1, 2, 3, 4];
|
||||||
assert_eq!(&vec[], vec);
|
assert_eq!(&vec[..], vec);
|
||||||
let b: &[_] = &[3, 4];
|
let b: &[_] = &[3, 4];
|
||||||
assert_eq!(&vec[2..], b);
|
assert_eq!(&vec[2..], b);
|
||||||
let b: &[_] = &[];
|
let b: &[_] = &[];
|
||||||
@ -2264,15 +2265,15 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_total_ord() {
|
fn test_total_ord() {
|
||||||
let c = &[1, 2, 3];
|
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];
|
let c = &[1, 2, 3, 4];
|
||||||
[1, 2, 3][].cmp(c) == Less;
|
[1, 2, 3][..].cmp(c) == Less;
|
||||||
let c = &[1, 2, 3, 6];
|
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];
|
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];
|
let c = &[1, 2, 3, 4];
|
||||||
[2, 2][].cmp(c) == Greater;
|
[2, 2][..].cmp(c) == Greater;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -55,7 +55,6 @@
|
|||||||
use self::RecompositionState::*;
|
use self::RecompositionState::*;
|
||||||
use self::DecompositionType::*;
|
use self::DecompositionType::*;
|
||||||
|
|
||||||
use core::borrow::{BorrowFrom, ToOwned};
|
|
||||||
use core::char::CharExt;
|
use core::char::CharExt;
|
||||||
use core::clone::Clone;
|
use core::clone::Clone;
|
||||||
use core::iter::AdditiveIterator;
|
use core::iter::AdditiveIterator;
|
||||||
@ -68,7 +67,8 @@ use core::slice::AsSlice;
|
|||||||
use core::str as core_str;
|
use core::str as core_str;
|
||||||
use unicode::str::{UnicodeStr, Utf16Encoder};
|
use unicode::str::{UnicodeStr, Utf16Encoder};
|
||||||
|
|
||||||
use ring_buf::RingBuf;
|
use vec_deque::VecDeque;
|
||||||
|
use borrow::{Borrow, ToOwned};
|
||||||
use slice::SliceExt;
|
use slice::SliceExt;
|
||||||
use string::String;
|
use string::String;
|
||||||
use unicode;
|
use unicode;
|
||||||
@ -261,7 +261,7 @@ enum RecompositionState {
|
|||||||
pub struct Recompositions<'a> {
|
pub struct Recompositions<'a> {
|
||||||
iter: Decompositions<'a>,
|
iter: Decompositions<'a>,
|
||||||
state: RecompositionState,
|
state: RecompositionState,
|
||||||
buffer: RingBuf<char>,
|
buffer: VecDeque<char>,
|
||||||
composee: Option<char>,
|
composee: Option<char>,
|
||||||
last_ccc: Option<u8>
|
last_ccc: Option<u8>
|
||||||
}
|
}
|
||||||
@ -386,13 +386,14 @@ macro_rules! utf8_acc_cont_byte {
|
|||||||
($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63u8) as u32)
|
($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63u8) as u32)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections", reason = "trait is unstable")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl BorrowFrom<String> for str {
|
impl Borrow<str> for String {
|
||||||
fn borrow_from(owned: &String) -> &str { &owned[] }
|
fn borrow(&self) -> &str { &self[..] }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections", reason = "trait is unstable")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl ToOwned<String> for str {
|
impl ToOwned for str {
|
||||||
|
type Owned = String;
|
||||||
fn to_owned(&self) -> String {
|
fn to_owned(&self) -> String {
|
||||||
unsafe {
|
unsafe {
|
||||||
String::from_utf8_unchecked(self.as_bytes().to_owned())
|
String::from_utf8_unchecked(self.as_bytes().to_owned())
|
||||||
@ -466,7 +467,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
reason = "this functionality may be moved to libunicode")]
|
reason = "this functionality may be moved to libunicode")]
|
||||||
fn nfd_chars(&self) -> Decompositions {
|
fn nfd_chars(&self) -> Decompositions {
|
||||||
Decompositions {
|
Decompositions {
|
||||||
iter: self[].chars(),
|
iter: self[..].chars(),
|
||||||
buffer: Vec::new(),
|
buffer: Vec::new(),
|
||||||
sorted: false,
|
sorted: false,
|
||||||
kind: Canonical
|
kind: Canonical
|
||||||
@ -480,7 +481,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
reason = "this functionality may be moved to libunicode")]
|
reason = "this functionality may be moved to libunicode")]
|
||||||
fn nfkd_chars(&self) -> Decompositions {
|
fn nfkd_chars(&self) -> Decompositions {
|
||||||
Decompositions {
|
Decompositions {
|
||||||
iter: self[].chars(),
|
iter: self[..].chars(),
|
||||||
buffer: Vec::new(),
|
buffer: Vec::new(),
|
||||||
sorted: false,
|
sorted: false,
|
||||||
kind: Compatible
|
kind: Compatible
|
||||||
@ -496,7 +497,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
Recompositions {
|
Recompositions {
|
||||||
iter: self.nfd_chars(),
|
iter: self.nfd_chars(),
|
||||||
state: Composing,
|
state: Composing,
|
||||||
buffer: RingBuf::new(),
|
buffer: VecDeque::new(),
|
||||||
composee: None,
|
composee: None,
|
||||||
last_ccc: None
|
last_ccc: None
|
||||||
}
|
}
|
||||||
@ -511,7 +512,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
Recompositions {
|
Recompositions {
|
||||||
iter: self.nfkd_chars(),
|
iter: self.nfkd_chars(),
|
||||||
state: Composing,
|
state: Composing,
|
||||||
buffer: RingBuf::new(),
|
buffer: VecDeque::new(),
|
||||||
composee: None,
|
composee: None,
|
||||||
last_ccc: None
|
last_ccc: None
|
||||||
}
|
}
|
||||||
@ -530,7 +531,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn contains(&self, pat: &str) -> bool {
|
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.
|
/// Returns true if a string contains a char pattern.
|
||||||
@ -547,7 +548,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "might get removed in favour of a more generic contains()")]
|
reason = "might get removed in favour of a more generic contains()")]
|
||||||
fn contains_char<P: CharEq>(&self, pat: P) -> bool {
|
fn contains_char<P: CharEq>(&self, pat: P) -> bool {
|
||||||
core_str::StrExt::contains_char(&self[], pat)
|
core_str::StrExt::contains_char(&self[..], pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over the characters of `self`. Note, this iterates
|
/// An iterator over the characters of `self`. Note, this iterates
|
||||||
@ -561,7 +562,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn chars(&self) -> Chars {
|
fn chars(&self) -> Chars {
|
||||||
core_str::StrExt::chars(&self[])
|
core_str::StrExt::chars(&self[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over the bytes of `self`
|
/// An iterator over the bytes of `self`
|
||||||
@ -574,13 +575,13 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn bytes(&self) -> Bytes {
|
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.
|
/// An iterator over the characters of `self` and their byte offsets.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn char_indices(&self) -> CharIndices {
|
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
|
/// An iterator over substrings of `self`, separated by characters
|
||||||
@ -603,7 +604,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn split<P: CharEq>(&self, pat: P) -> Split<P> {
|
fn split<P: CharEq>(&self, pat: P) -> Split<P> {
|
||||||
core_str::StrExt::split(&self[], pat)
|
core_str::StrExt::split(&self[..], pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over substrings of `self`, separated by characters
|
/// An iterator over substrings of `self`, separated by characters
|
||||||
@ -630,7 +631,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn splitn<P: CharEq>(&self, count: usize, pat: P) -> SplitN<P> {
|
fn splitn<P: CharEq>(&self, count: usize, pat: P) -> SplitN<P> {
|
||||||
core_str::StrExt::splitn(&self[], count, pat)
|
core_str::StrExt::splitn(&self[..], count, pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over substrings of `self`, separated by characters
|
/// An iterator over substrings of `self`, separated by characters
|
||||||
@ -659,7 +660,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "collections", reason = "might get removed")]
|
#[unstable(feature = "collections", reason = "might get removed")]
|
||||||
fn split_terminator<P: CharEq>(&self, pat: P) -> SplitTerminator<P> {
|
fn split_terminator<P: CharEq>(&self, pat: P) -> SplitTerminator<P> {
|
||||||
core_str::StrExt::split_terminator(&self[], pat)
|
core_str::StrExt::split_terminator(&self[..], pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over substrings of `self`, separated by characters
|
/// An iterator over substrings of `self`, separated by characters
|
||||||
@ -680,7 +681,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn rsplitn<P: CharEq>(&self, count: usize, pat: P) -> RSplitN<P> {
|
fn rsplitn<P: CharEq>(&self, count: usize, pat: P) -> RSplitN<P> {
|
||||||
core_str::StrExt::rsplitn(&self[], count, pat)
|
core_str::StrExt::rsplitn(&self[..], count, pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An iterator over the start and end indices of the disjoint
|
/// An iterator over the start and end indices of the disjoint
|
||||||
@ -706,7 +707,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "might have its iterator type changed")]
|
reason = "might have its iterator type changed")]
|
||||||
fn match_indices<'a>(&'a self, pat: &'a str) -> MatchIndices<'a> {
|
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`.
|
/// An iterator over the substrings of `self` separated by the pattern `sep`.
|
||||||
@ -723,7 +724,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "might get removed in the future in favor of a more generic split()")]
|
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> {
|
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
|
/// An iterator over the lines of a string (subsequences separated
|
||||||
@ -739,7 +740,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn lines(&self) -> Lines {
|
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
|
/// An iterator over the lines of a string, separated by either
|
||||||
@ -755,7 +756,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn lines_any(&self) -> LinesAny {
|
fn lines_any(&self) -> LinesAny {
|
||||||
core_str::StrExt::lines_any(&self[])
|
core_str::StrExt::lines_any(&self[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deprecated: use `s[a .. b]` instead.
|
/// Deprecated: use `s[a .. b]` instead.
|
||||||
@ -802,7 +803,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "may have yet to prove its worth")]
|
reason = "may have yet to prove its worth")]
|
||||||
fn slice_chars(&self, begin: usize, end: usize) -> &str {
|
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.
|
/// Takes a bytewise (not UTF-8) slice from a string.
|
||||||
@ -813,7 +814,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// the entire slice as well.
|
/// the entire slice as well.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
unsafe fn slice_unchecked(&self, begin: usize, end: usize) -> &str {
|
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.
|
/// Returns true if the pattern `pat` is a prefix of the string.
|
||||||
@ -825,7 +826,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn starts_with(&self, pat: &str) -> bool {
|
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.
|
/// Returns true if the pattern `pat` is a suffix of the string.
|
||||||
@ -837,7 +838,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn ends_with(&self, pat: &str) -> bool {
|
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
|
/// Returns a string with all pre- and suffixes that match
|
||||||
@ -857,7 +858,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn trim_matches<P: CharEq>(&self, pat: P) -> &str {
|
fn trim_matches<P: CharEq>(&self, pat: P) -> &str {
|
||||||
core_str::StrExt::trim_matches(&self[], pat)
|
core_str::StrExt::trim_matches(&self[..], pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a string with all prefixes that match
|
/// Returns a string with all prefixes that match
|
||||||
@ -877,7 +878,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn trim_left_matches<P: CharEq>(&self, pat: P) -> &str {
|
fn trim_left_matches<P: CharEq>(&self, pat: P) -> &str {
|
||||||
core_str::StrExt::trim_left_matches(&self[], pat)
|
core_str::StrExt::trim_left_matches(&self[..], pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a string with all suffixes that match
|
/// Returns a string with all suffixes that match
|
||||||
@ -897,7 +898,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn trim_right_matches<P: CharEq>(&self, pat: P) -> &str {
|
fn trim_right_matches<P: CharEq>(&self, pat: P) -> &str {
|
||||||
core_str::StrExt::trim_right_matches(&self[], pat)
|
core_str::StrExt::trim_right_matches(&self[..], pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check that `index`-th byte lies at the start and/or end of a
|
/// Check that `index`-th byte lies at the start and/or end of a
|
||||||
@ -926,7 +927,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "naming is uncertain with container conventions")]
|
reason = "naming is uncertain with container conventions")]
|
||||||
fn is_char_boundary(&self, index: usize) -> bool {
|
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
|
/// Pluck a character out of a string and return the index of the next
|
||||||
@ -985,7 +986,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "naming is uncertain with container conventions")]
|
reason = "naming is uncertain with container conventions")]
|
||||||
fn char_range_at(&self, start: usize) -> CharRange {
|
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.
|
/// Given a byte position and a str, return the previous char and its position.
|
||||||
@ -1001,7 +1002,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "naming is uncertain with container conventions")]
|
reason = "naming is uncertain with container conventions")]
|
||||||
fn char_range_at_reverse(&self, start: usize) -> CharRange {
|
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.
|
/// Plucks the character starting at the `i`th byte of a string.
|
||||||
@ -1022,7 +1023,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "naming is uncertain with container conventions")]
|
reason = "naming is uncertain with container conventions")]
|
||||||
fn char_at(&self, i: usize) -> char {
|
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.
|
/// Plucks the character ending at the `i`th byte of a string.
|
||||||
@ -1034,7 +1035,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "naming is uncertain with container conventions")]
|
reason = "naming is uncertain with container conventions")]
|
||||||
fn char_at_reverse(&self, i: usize) -> char {
|
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.
|
/// Work with the byte buffer of a string as a byte slice.
|
||||||
@ -1046,7 +1047,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn as_bytes(&self) -> &[u8] {
|
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
|
/// Returns the byte index of the first character of `self` that
|
||||||
@ -1074,7 +1075,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn find<P: CharEq>(&self, pat: P) -> Option<usize> {
|
fn find<P: CharEq>(&self, pat: P) -> Option<usize> {
|
||||||
core_str::StrExt::find(&self[], pat)
|
core_str::StrExt::find(&self[..], pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the byte index of the last character of `self` that
|
/// Returns the byte index of the last character of `self` that
|
||||||
@ -1102,7 +1103,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn rfind<P: CharEq>(&self, pat: P) -> Option<usize> {
|
fn rfind<P: CharEq>(&self, pat: P) -> Option<usize> {
|
||||||
core_str::StrExt::rfind(&self[], pat)
|
core_str::StrExt::rfind(&self[..], pat)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the byte index of the first matching substring
|
/// Returns the byte index of the first matching substring
|
||||||
@ -1127,7 +1128,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "might get removed in favor of a more generic find in the future")]
|
reason = "might get removed in favor of a more generic find in the future")]
|
||||||
fn find_str(&self, needle: &str) -> Option<usize> {
|
fn find_str(&self, needle: &str) -> Option<usize> {
|
||||||
core_str::StrExt::find_str(&self[], needle)
|
core_str::StrExt::find_str(&self[..], needle)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the first character from a string slice and returns
|
/// Retrieves the first character from a string slice and returns
|
||||||
@ -1151,7 +1152,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "awaiting conventions about shifting and slices")]
|
reason = "awaiting conventions about shifting and slices")]
|
||||||
fn slice_shift_char(&self) -> Option<(char, &str)> {
|
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.
|
/// Returns the byte offset of an inner slice relative to an enclosing outer slice.
|
||||||
@ -1171,7 +1172,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "awaiting convention about comparability of arbitrary slices")]
|
reason = "awaiting convention about comparability of arbitrary slices")]
|
||||||
fn subslice_offset(&self, inner: &str) -> usize {
|
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.
|
/// Return an unsafe pointer to the strings buffer.
|
||||||
@ -1182,14 +1183,14 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_ptr(&self) -> *const u8 {
|
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.
|
/// Return an iterator of `u16` over the string encoded as UTF-16.
|
||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "this functionality may only be provided by libunicode")]
|
reason = "this functionality may only be provided by libunicode")]
|
||||||
fn utf16_units(&self) -> Utf16Units {
|
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
|
/// Return the number of bytes in this string
|
||||||
@ -1203,7 +1204,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
core_str::StrExt::len(&self[])
|
core_str::StrExt::len(&self[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this slice contains no bytes
|
/// Returns true if this slice contains no bytes
|
||||||
@ -1216,7 +1217,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn is_empty(&self) -> bool {
|
fn is_empty(&self) -> bool {
|
||||||
core_str::StrExt::is_empty(&self[])
|
core_str::StrExt::is_empty(&self[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse this string into the specified type.
|
/// Parse this string into the specified type.
|
||||||
@ -1230,7 +1231,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
|
fn parse<F: FromStr>(&self) -> Result<F, F::Err> {
|
||||||
core_str::StrExt::parse(&self[])
|
core_str::StrExt::parse(&self[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator over the
|
/// Returns an iterator over the
|
||||||
@ -1255,7 +1256,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "this functionality may only be provided by libunicode")]
|
reason = "this functionality may only be provided by libunicode")]
|
||||||
fn graphemes(&self, is_extended: bool) -> Graphemes {
|
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.
|
/// Returns an iterator over the grapheme clusters of self and their byte offsets.
|
||||||
@ -1271,7 +1272,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "this functionality may only be provided by libunicode")]
|
reason = "this functionality may only be provided by libunicode")]
|
||||||
fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices {
|
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
|
/// An iterator over the words of a string (subsequences separated
|
||||||
@ -1288,7 +1289,7 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "str_words",
|
#[unstable(feature = "str_words",
|
||||||
reason = "the precise algorithm to use is unclear")]
|
reason = "the precise algorithm to use is unclear")]
|
||||||
fn words(&self) -> Words {
|
fn words(&self) -> Words {
|
||||||
UnicodeStr::words(&self[])
|
UnicodeStr::words(&self[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a string's displayed width in columns, treating control
|
/// Returns a string's displayed width in columns, treating control
|
||||||
@ -1303,25 +1304,25 @@ pub trait StrExt: Index<RangeFull, Output = str> {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "this functionality may only be provided by libunicode")]
|
reason = "this functionality may only be provided by libunicode")]
|
||||||
fn width(&self, is_cjk: bool) -> usize {
|
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.
|
/// Returns a string with leading and trailing whitespace removed.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn trim(&self) -> &str {
|
fn trim(&self) -> &str {
|
||||||
UnicodeStr::trim(&self[])
|
UnicodeStr::trim(&self[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a string with leading whitespace removed.
|
/// Returns a string with leading whitespace removed.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn trim_left(&self) -> &str {
|
fn trim_left(&self) -> &str {
|
||||||
UnicodeStr::trim_left(&self[])
|
UnicodeStr::trim_left(&self[..])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a string with trailing whitespace removed.
|
/// Returns a string with trailing whitespace removed.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn trim_right(&self) -> &str {
|
fn trim_right(&self) -> &str {
|
||||||
UnicodeStr::trim_right(&self[])
|
UnicodeStr::trim_right(&self[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2704,7 +2705,7 @@ mod tests {
|
|||||||
&["\u{378}\u{308}\u{903}"], &["\u{378}\u{308}", "\u{903}"]),
|
&["\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
|
// test forward iterator
|
||||||
assert!(order::equals(s.graphemes(true), g.iter().cloned()));
|
assert!(order::equals(s.graphemes(true), g.iter().cloned()));
|
||||||
assert!(order::equals(s.graphemes(false), g.iter().cloned()));
|
assert!(order::equals(s.graphemes(false), g.iter().cloned()));
|
||||||
|
@ -16,12 +16,11 @@
|
|||||||
|
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
|
|
||||||
use core::borrow::{Cow, IntoCow};
|
|
||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
use core::error::Error;
|
use core::error::Error;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::hash;
|
use core::hash;
|
||||||
use core::iter::FromIterator;
|
use core::iter::{IntoIterator, FromIterator};
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core::ops::{self, Deref, Add, Index};
|
use core::ops::{self, Deref, Add, Index};
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
@ -29,6 +28,7 @@ use core::raw::Slice as RawSlice;
|
|||||||
use unicode::str as unicode_str;
|
use unicode::str as unicode_str;
|
||||||
use unicode::str::Utf16Item;
|
use unicode::str::Utf16Item;
|
||||||
|
|
||||||
|
use borrow::{Cow, IntoCow};
|
||||||
use str::{self, CharRange, FromStr, Utf8Error};
|
use str::{self, CharRange, FromStr, Utf8Error};
|
||||||
use vec::{DerefVec, Vec, as_vec};
|
use vec::{DerefVec, Vec, as_vec};
|
||||||
|
|
||||||
@ -142,7 +142,7 @@ impl String {
|
|||||||
/// assert_eq!(output.as_slice(), "Hello \u{FFFD}World");
|
/// assert_eq!(output.as_slice(), "Hello \u{FFFD}World");
|
||||||
/// ```
|
/// ```
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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;
|
let mut i = 0;
|
||||||
match str::from_utf8(v) {
|
match str::from_utf8(v) {
|
||||||
Ok(s) => return Cow::Borrowed(s),
|
Ok(s) => return Cow::Borrowed(s),
|
||||||
@ -709,18 +709,18 @@ impl Error for FromUtf16Error {
|
|||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl FromIterator<char> for String {
|
impl FromIterator<char> for String {
|
||||||
fn from_iter<I:Iterator<Item=char>>(iterator: I) -> String {
|
fn from_iter<I: IntoIterator<Item=char>>(iter: I) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
buf.extend(iterator);
|
buf.extend(iter);
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a> FromIterator<&'a str> for String {
|
impl<'a> FromIterator<&'a str> for String {
|
||||||
fn from_iter<I:Iterator<Item=&'a str>>(iterator: I) -> String {
|
fn from_iter<I: IntoIterator<Item=&'a str>>(iter: I) -> String {
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
buf.extend(iterator);
|
buf.extend(iter);
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -728,7 +728,8 @@ impl<'a> FromIterator<&'a str> for String {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "waiting on Extend stabilization")]
|
reason = "waiting on Extend stabilization")]
|
||||||
impl Extend<char> for String {
|
impl Extend<char> for String {
|
||||||
fn extend<I:Iterator<Item=char>>(&mut self, iterator: I) {
|
fn extend<I: IntoIterator<Item=char>>(&mut self, iterable: I) {
|
||||||
|
let iterator = iterable.into_iter();
|
||||||
let (lower_bound, _) = iterator.size_hint();
|
let (lower_bound, _) = iterator.size_hint();
|
||||||
self.reserve(lower_bound);
|
self.reserve(lower_bound);
|
||||||
for ch in iterator {
|
for ch in iterator {
|
||||||
@ -740,7 +741,8 @@ impl Extend<char> for String {
|
|||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "waiting on Extend stabilization")]
|
reason = "waiting on Extend stabilization")]
|
||||||
impl<'a> Extend<&'a str> for String {
|
impl<'a> Extend<&'a str> for String {
|
||||||
fn extend<I: Iterator<Item=&'a str>>(&mut self, iterator: I) {
|
fn extend<I: IntoIterator<Item=&'a str>>(&mut self, iterable: I) {
|
||||||
|
let iterator = iterable.into_iter();
|
||||||
// A guess that at least one byte per iterator element will be needed.
|
// A guess that at least one byte per iterator element will be needed.
|
||||||
let (lower_bound, _) = iterator.size_hint();
|
let (lower_bound, _) = iterator.size_hint();
|
||||||
self.reserve(lower_bound);
|
self.reserve(lower_bound);
|
||||||
@ -780,10 +782,10 @@ macro_rules! impl_eq {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl_eq! { String, &'a str }
|
impl_eq! { String, &'a str }
|
||||||
impl_eq! { CowString<'a>, String }
|
impl_eq! { Cow<'a, str>, String }
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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]
|
#[inline]
|
||||||
fn eq(&self, other: &&'b str) -> bool { PartialEq::eq(&**self, &**other) }
|
fn eq(&self, other: &&'b str) -> bool { PartialEq::eq(&**self, &**other) }
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -791,11 +793,11 @@ impl<'a, 'b> PartialEq<&'b str> for CowString<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a, 'b> PartialEq<CowString<'a>> for &'b str {
|
impl<'a, 'b> PartialEq<Cow<'a, str>> for &'b str {
|
||||||
#[inline]
|
#[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]
|
#[inline]
|
||||||
fn ne(&self, other: &CowString<'a>) -> bool { PartialEq::ne(&**self, &**other) }
|
fn ne(&self, other: &Cow<'a, str>) -> bool { PartialEq::ne(&**self, &**other) }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections", reason = "waiting on Str stabilization")]
|
#[unstable(feature = "collections", reason = "waiting on Str stabilization")]
|
||||||
@ -833,12 +835,21 @@ impl fmt::Debug for String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections", reason = "waiting on Hash stabilization")]
|
#[unstable(feature = "collections", reason = "waiting on Hash stabilization")]
|
||||||
|
#[cfg(stage0)]
|
||||||
impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for String {
|
impl<H: hash::Writer + hash::Hasher> hash::Hash<H> for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash(&self, hasher: &mut H) {
|
fn hash(&self, hasher: &mut H) {
|
||||||
(**self).hash(hasher)
|
(**self).hash(hasher)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
impl hash::Hash for String {
|
||||||
|
#[inline]
|
||||||
|
fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
|
||||||
|
(**self).hash(hasher)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "recent addition, needs more experience")]
|
reason = "recent addition, needs more experience")]
|
||||||
@ -857,7 +868,7 @@ impl ops::Index<ops::Range<usize>> for String {
|
|||||||
type Output = str;
|
type Output = str;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index(&self, index: &ops::Range<usize>) -> &str {
|
fn index(&self, index: &ops::Range<usize>) -> &str {
|
||||||
&self[][*index]
|
&self[..][*index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@ -865,7 +876,7 @@ impl ops::Index<ops::RangeTo<usize>> for String {
|
|||||||
type Output = str;
|
type Output = str;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index(&self, index: &ops::RangeTo<usize>) -> &str {
|
fn index(&self, index: &ops::RangeTo<usize>) -> &str {
|
||||||
&self[][*index]
|
&self[..][*index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@ -873,7 +884,7 @@ impl ops::Index<ops::RangeFrom<usize>> for String {
|
|||||||
type Output = str;
|
type Output = str;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn index(&self, index: &ops::RangeFrom<usize>) -> &str {
|
fn index(&self, index: &ops::RangeFrom<usize>) -> &str {
|
||||||
&self[][*index]
|
&self[..][*index]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@ -891,7 +902,7 @@ impl ops::Deref for String {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn deref(&self) -> &str {
|
fn deref(&self) -> &str {
|
||||||
unsafe { mem::transmute(&self.vec[]) }
|
unsafe { mem::transmute(&self.vec[..]) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -958,31 +969,34 @@ impl<T: fmt::Display + ?Sized> ToString for T {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IntoCow<'static, String, str> for String {
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl IntoCow<'static, str> for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn into_cow(self) -> CowString<'static> {
|
fn into_cow(self) -> Cow<'static, str> {
|
||||||
Cow::Owned(self)
|
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]
|
#[inline]
|
||||||
fn into_cow(self) -> CowString<'a> {
|
fn into_cow(self) -> Cow<'a, str> {
|
||||||
Cow::Borrowed(self)
|
Cow::Borrowed(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A clone-on-write string
|
impl<'a> Str for Cow<'a, str> {
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
pub type CowString<'a> = Cow<'a, String, str>;
|
|
||||||
|
|
||||||
impl<'a> Str for CowString<'a> {
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn as_slice<'b>(&'b self) -> &'b str {
|
fn as_slice<'b>(&'b self) -> &'b str {
|
||||||
&**self
|
&**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")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl fmt::Write for String {
|
impl fmt::Write for String {
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -1287,7 +1301,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_slicing() {
|
fn test_slicing() {
|
||||||
let s = "foobar".to_string();
|
let s = "foobar".to_string();
|
||||||
assert_eq!("foobar", &s[]);
|
assert_eq!("foobar", &s[..]);
|
||||||
assert_eq!("foo", &s[..3]);
|
assert_eq!("foo", &s[..3]);
|
||||||
assert_eq!("bar", &s[3..]);
|
assert_eq!("bar", &s[3..]);
|
||||||
assert_eq!("oob", &s[1..4]);
|
assert_eq!("oob", &s[1..4]);
|
||||||
|
@ -50,24 +50,26 @@ use core::prelude::*;
|
|||||||
|
|
||||||
use alloc::boxed::Box;
|
use alloc::boxed::Box;
|
||||||
use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
|
use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
|
||||||
use core::borrow::{Cow, IntoCow};
|
|
||||||
use core::cmp::max;
|
use core::cmp::max;
|
||||||
use core::cmp::{Ordering};
|
use core::cmp::{Ordering};
|
||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::hash::{self, Hash};
|
use core::hash::{self, Hash};
|
||||||
|
use core::intrinsics::assume;
|
||||||
use core::iter::{repeat, FromIterator, IntoIterator};
|
use core::iter::{repeat, FromIterator, IntoIterator};
|
||||||
use core::marker::{self, ContravariantLifetime, InvariantType};
|
use core::marker::PhantomData;
|
||||||
use core::mem;
|
use core::mem;
|
||||||
use core::nonzero::NonZero;
|
|
||||||
use core::num::{Int, UnsignedInt};
|
use core::num::{Int, UnsignedInt};
|
||||||
use core::ops::{Index, IndexMut, Deref, Add};
|
use core::ops::{Index, IndexMut, Deref, Add};
|
||||||
use core::ops;
|
use core::ops;
|
||||||
use core::ptr;
|
use core::ptr;
|
||||||
|
use core::ptr::Unique;
|
||||||
use core::raw::Slice as RawSlice;
|
use core::raw::Slice as RawSlice;
|
||||||
use core::slice;
|
use core::slice;
|
||||||
use core::usize;
|
use core::usize;
|
||||||
|
|
||||||
|
use borrow::{Cow, IntoCow};
|
||||||
|
|
||||||
/// A growable list type, written `Vec<T>` but pronounced 'vector.'
|
/// A growable list type, written `Vec<T>` but pronounced 'vector.'
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
@ -137,10 +139,9 @@ use core::usize;
|
|||||||
#[unsafe_no_drop_flag]
|
#[unsafe_no_drop_flag]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct Vec<T> {
|
pub struct Vec<T> {
|
||||||
ptr: NonZero<*mut T>,
|
ptr: Unique<T>,
|
||||||
len: usize,
|
len: usize,
|
||||||
cap: usize,
|
cap: usize,
|
||||||
_own: marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T: Send> Send for Vec<T> { }
|
unsafe impl<T: Send> Send for Vec<T> { }
|
||||||
@ -249,10 +250,9 @@ impl<T> Vec<T> {
|
|||||||
pub unsafe fn from_raw_parts(ptr: *mut T, length: usize,
|
pub unsafe fn from_raw_parts(ptr: *mut T, length: usize,
|
||||||
capacity: usize) -> Vec<T> {
|
capacity: usize) -> Vec<T> {
|
||||||
Vec {
|
Vec {
|
||||||
ptr: NonZero::new(ptr),
|
ptr: Unique::new(ptr),
|
||||||
len: length,
|
len: length,
|
||||||
cap: capacity,
|
cap: capacity,
|
||||||
_own: marker::PhantomData,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -373,7 +373,7 @@ impl<T> Vec<T> {
|
|||||||
self.len * mem::size_of::<T>(),
|
self.len * mem::size_of::<T>(),
|
||||||
mem::min_align_of::<T>()) as *mut T;
|
mem::min_align_of::<T>()) as *mut T;
|
||||||
if ptr.is_null() { ::alloc::oom() }
|
if ptr.is_null() { ::alloc::oom() }
|
||||||
self.ptr = NonZero::new(ptr);
|
self.ptr = Unique::new(ptr);
|
||||||
}
|
}
|
||||||
self.cap = self.len;
|
self.cap = self.len;
|
||||||
}
|
}
|
||||||
@ -655,7 +655,7 @@ impl<T> Vec<T> {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let ptr = alloc_or_realloc(*self.ptr, old_size, size);
|
let ptr = alloc_or_realloc(*self.ptr, old_size, size);
|
||||||
if ptr.is_null() { ::alloc::oom() }
|
if ptr.is_null() { ::alloc::oom() }
|
||||||
self.ptr = NonZero::new(ptr);
|
self.ptr = Unique::new(ptr);
|
||||||
}
|
}
|
||||||
self.cap = max(self.cap, 2) * 2;
|
self.cap = max(self.cap, 2) * 2;
|
||||||
}
|
}
|
||||||
@ -756,7 +756,7 @@ impl<T> Vec<T> {
|
|||||||
Drain {
|
Drain {
|
||||||
ptr: begin,
|
ptr: begin,
|
||||||
end: end,
|
end: end,
|
||||||
marker: ContravariantLifetime,
|
marker: PhantomData,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -871,6 +871,8 @@ impl<T> Vec<T> {
|
|||||||
end_t: unsafe { start.offset(offset) },
|
end_t: unsafe { start.offset(offset) },
|
||||||
start_u: start as *mut U,
|
start_u: start as *mut U,
|
||||||
end_u: start as *mut U,
|
end_u: start as *mut U,
|
||||||
|
|
||||||
|
_marker: PhantomData,
|
||||||
};
|
};
|
||||||
// start_t
|
// start_t
|
||||||
// start_u
|
// start_u
|
||||||
@ -967,8 +969,7 @@ impl<T> Vec<T> {
|
|||||||
let mut pv = PartialVecZeroSized::<T,U> {
|
let mut pv = PartialVecZeroSized::<T,U> {
|
||||||
num_t: vec.len(),
|
num_t: vec.len(),
|
||||||
num_u: 0,
|
num_u: 0,
|
||||||
marker_t: InvariantType,
|
marker: PhantomData,
|
||||||
marker_u: InvariantType,
|
|
||||||
};
|
};
|
||||||
unsafe { mem::forget(vec); }
|
unsafe { mem::forget(vec); }
|
||||||
|
|
||||||
@ -1226,7 +1227,7 @@ impl<T> Vec<T> {
|
|||||||
unsafe {
|
unsafe {
|
||||||
let ptr = alloc_or_realloc(*self.ptr, self.cap * mem::size_of::<T>(), size);
|
let ptr = alloc_or_realloc(*self.ptr, self.cap * mem::size_of::<T>(), size);
|
||||||
if ptr.is_null() { ::alloc::oom() }
|
if ptr.is_null() { ::alloc::oom() }
|
||||||
self.ptr = NonZero::new(ptr);
|
self.ptr = Unique::new(ptr);
|
||||||
}
|
}
|
||||||
self.cap = capacity;
|
self.cap = capacity;
|
||||||
}
|
}
|
||||||
@ -1302,12 +1303,21 @@ impl<T:Clone> Clone for Vec<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for Vec<T> {
|
impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for Vec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
Hash::hash(&**self, state)
|
Hash::hash(&**self, state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
impl<T: Hash> Hash for Vec<T> {
|
||||||
|
#[inline]
|
||||||
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
|
Hash::hash(&**self, state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> Index<usize> for Vec<T> {
|
impl<T> Index<usize> for Vec<T> {
|
||||||
@ -1407,7 +1417,8 @@ impl<T> ops::DerefMut for Vec<T> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T> FromIterator<T> for Vec<T> {
|
impl<T> FromIterator<T> for Vec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_iter<I:Iterator<Item=T>>(mut iterator: I) -> Vec<T> {
|
fn from_iter<I: IntoIterator<Item=T>>(iterable: I) -> Vec<T> {
|
||||||
|
let mut iterator = iterable.into_iter();
|
||||||
let (lower, _) = iterator.size_hint();
|
let (lower, _) = iterator.size_hint();
|
||||||
let mut vector = Vec::with_capacity(lower);
|
let mut vector = Vec::with_capacity(lower);
|
||||||
|
|
||||||
@ -1480,7 +1491,8 @@ impl<'a, T> IntoIterator for &'a mut Vec<T> {
|
|||||||
#[unstable(feature = "collections", reason = "waiting on Extend stability")]
|
#[unstable(feature = "collections", reason = "waiting on Extend stability")]
|
||||||
impl<T> Extend<T> for Vec<T> {
|
impl<T> Extend<T> for Vec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn extend<I: Iterator<Item=T>>(&mut self, iterator: I) {
|
fn extend<I: IntoIterator<Item=T>>(&mut self, iterable: I) {
|
||||||
|
let iterator = iterable.into_iter();
|
||||||
let (lower, _) = iterator.size_hint();
|
let (lower, _) = iterator.size_hint();
|
||||||
self.reserve(lower);
|
self.reserve(lower);
|
||||||
for element in iterator {
|
for element in iterator {
|
||||||
@ -1517,34 +1529,34 @@ macro_rules! impl_eq {
|
|||||||
impl_eq! { Vec<A>, &'b [B] }
|
impl_eq! { Vec<A>, &'b [B] }
|
||||||
impl_eq! { Vec<A>, &'b mut [B] }
|
impl_eq! { Vec<A>, &'b mut [B] }
|
||||||
|
|
||||||
impl<'a, A, B> PartialEq<Vec<B>> for CowVec<'a, A> where A: PartialEq<B> + Clone {
|
impl<'a, A, B> PartialEq<Vec<B>> for Cow<'a, [A]> where A: PartialEq<B> + Clone {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, other: &Vec<B>) -> bool { PartialEq::eq(&**self, &**other) }
|
fn eq(&self, other: &Vec<B>) -> bool { PartialEq::eq(&**self, &**other) }
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ne(&self, other: &Vec<B>) -> bool { PartialEq::ne(&**self, &**other) }
|
fn ne(&self, other: &Vec<B>) -> bool { PartialEq::ne(&**self, &**other) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, A, B> PartialEq<CowVec<'a, A>> for Vec<B> where A: Clone, B: PartialEq<A> {
|
impl<'a, A, B> PartialEq<Cow<'a, [A]>> for Vec<B> where A: Clone, B: PartialEq<A> {
|
||||||
#[inline]
|
#[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]
|
#[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 {
|
macro_rules! impl_eq_for_cowvec {
|
||||||
($rhs:ty) => {
|
($rhs:ty) => {
|
||||||
impl<'a, 'b, A, B> PartialEq<$rhs> for CowVec<'a, A> where A: PartialEq<B> + Clone {
|
impl<'a, 'b, A, B> PartialEq<$rhs> for Cow<'a, [A]> where A: PartialEq<B> + Clone {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
|
fn eq(&self, other: &$rhs) -> bool { PartialEq::eq(&**self, &**other) }
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
|
fn ne(&self, other: &$rhs) -> bool { PartialEq::ne(&**self, &**other) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'b, A, B> PartialEq<CowVec<'a, A>> for $rhs where A: Clone, B: PartialEq<A> {
|
impl<'a, 'b, A, B> PartialEq<Cow<'a, [A]>> for $rhs where A: Clone, B: PartialEq<A> {
|
||||||
#[inline]
|
#[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]
|
#[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 @@ macro_rules! impl_eq_for_cowvec {
|
|||||||
impl_eq_for_cowvec! { &'b [B] }
|
impl_eq_for_cowvec! { &'b [B] }
|
||||||
impl_eq_for_cowvec! { &'b mut [B] }
|
impl_eq_for_cowvec! { &'b mut [B] }
|
||||||
|
|
||||||
#[unstable(feature = "collections",
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
reason = "waiting on PartialOrd stability")]
|
|
||||||
impl<T: PartialOrd> PartialOrd for Vec<T> {
|
impl<T: PartialOrd> PartialOrd for Vec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Vec<T>) -> Option<Ordering> {
|
||||||
@ -1561,10 +1572,10 @@ impl<T: PartialOrd> PartialOrd for Vec<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections", reason = "waiting on Eq stability")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Eq> Eq for Vec<T> {}
|
impl<T: Eq> Eq for Vec<T> {}
|
||||||
|
|
||||||
#[unstable(feature = "collections", reason = "waiting on Ord stability")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Ord> Ord for Vec<T> {
|
impl<T: Ord> Ord for Vec<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn cmp(&self, other: &Vec<T>) -> Ordering {
|
fn cmp(&self, other: &Vec<T>) -> Ordering {
|
||||||
@ -1587,8 +1598,12 @@ impl<T> AsSlice<T> for Vec<T> {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn as_slice(&self) -> &[T] {
|
fn as_slice(&self) -> &[T] {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
let p = *self.ptr;
|
||||||
|
if cfg!(not(stage0)) { // NOTE remove cfg after next snapshot
|
||||||
|
assume(p != 0 as *mut T);
|
||||||
|
}
|
||||||
mem::transmute(RawSlice {
|
mem::transmute(RawSlice {
|
||||||
data: *self.ptr,
|
data: p,
|
||||||
len: self.len
|
len: self.len
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -1643,26 +1658,26 @@ impl<T: fmt::Debug> fmt::Debug for Vec<T> {
|
|||||||
// Clone-on-write
|
// Clone-on-write
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#[unstable(feature = "collections",
|
|
||||||
reason = "unclear how valuable this alias is")]
|
|
||||||
/// A clone-on-write vector
|
/// A clone-on-write vector
|
||||||
pub type CowVec<'a, T> = Cow<'a, Vec<T>, [T]>;
|
#[deprecated(since = "1.0.0", reason = "use Cow<'a, [T]> instead")]
|
||||||
|
#[unstable(feature = "collections")]
|
||||||
|
pub type CowVec<'a, T> = Cow<'a, [T]>;
|
||||||
|
|
||||||
#[unstable(feature = "collections")]
|
#[unstable(feature = "collections")]
|
||||||
impl<'a, T> FromIterator<T> for CowVec<'a, T> where T: Clone {
|
impl<'a, T> FromIterator<T> for Cow<'a, [T]> where T: Clone {
|
||||||
fn from_iter<I: Iterator<Item=T>>(it: I) -> CowVec<'a, T> {
|
fn from_iter<I: IntoIterator<Item=T>>(it: I) -> Cow<'a, [T]> {
|
||||||
Cow::Owned(FromIterator::from_iter(it))
|
Cow::Owned(FromIterator::from_iter(it))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: 'a> IntoCow<'a, Vec<T>, [T]> for Vec<T> where T: Clone {
|
impl<'a, T: 'a> IntoCow<'a, [T]> for Vec<T> where T: Clone {
|
||||||
fn into_cow(self) -> CowVec<'a, T> {
|
fn into_cow(self) -> Cow<'a, [T]> {
|
||||||
Cow::Owned(self)
|
Cow::Owned(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T> IntoCow<'a, Vec<T>, [T]> for &'a [T] where T: Clone {
|
impl<'a, T> IntoCow<'a, [T]> for &'a [T] where T: Clone {
|
||||||
fn into_cow(self) -> CowVec<'a, T> {
|
fn into_cow(self) -> Cow<'a, [T]> {
|
||||||
Cow::Borrowed(self)
|
Cow::Borrowed(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1779,10 +1794,10 @@ impl<T> Drop for IntoIter<T> {
|
|||||||
#[unsafe_no_drop_flag]
|
#[unsafe_no_drop_flag]
|
||||||
#[unstable(feature = "collections",
|
#[unstable(feature = "collections",
|
||||||
reason = "recently added as part of collections reform 2")]
|
reason = "recently added as part of collections reform 2")]
|
||||||
pub struct Drain<'a, T> {
|
pub struct Drain<'a, T:'a> {
|
||||||
ptr: *const T,
|
ptr: *const T,
|
||||||
end: *const T,
|
end: *const T,
|
||||||
marker: ContravariantLifetime<'a>,
|
marker: PhantomData<&'a T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@ -1867,9 +1882,9 @@ impl<'a, T> Drop for Drain<'a, T> {
|
|||||||
|
|
||||||
/// Wrapper type providing a `&Vec<T>` reference via `Deref`.
|
/// Wrapper type providing a `&Vec<T>` reference via `Deref`.
|
||||||
#[unstable(feature = "collections")]
|
#[unstable(feature = "collections")]
|
||||||
pub struct DerefVec<'a, T> {
|
pub struct DerefVec<'a, T:'a> {
|
||||||
x: Vec<T>,
|
x: Vec<T>,
|
||||||
l: ContravariantLifetime<'a>
|
l: PhantomData<&'a T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections")]
|
#[unstable(feature = "collections")]
|
||||||
@ -1897,7 +1912,7 @@ pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
|
|||||||
unsafe {
|
unsafe {
|
||||||
DerefVec {
|
DerefVec {
|
||||||
x: Vec::from_raw_parts(x.as_ptr() as *mut T, x.len(), x.len()),
|
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<T,U> {
|
|||||||
end_u: *mut U,
|
end_u: *mut U,
|
||||||
start_t: *mut T,
|
start_t: *mut T,
|
||||||
end_t: *mut T,
|
end_t: *mut T,
|
||||||
|
|
||||||
|
_marker: PhantomData<U>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An owned, partially type-converted vector of zero-sized elements.
|
/// An owned, partially type-converted vector of zero-sized elements.
|
||||||
@ -1930,8 +1947,7 @@ struct PartialVecNonZeroSized<T,U> {
|
|||||||
struct PartialVecZeroSized<T,U> {
|
struct PartialVecZeroSized<T,U> {
|
||||||
num_t: usize,
|
num_t: usize,
|
||||||
num_u: usize,
|
num_u: usize,
|
||||||
marker_t: InvariantType<T>,
|
marker: PhantomData<::core::cell::Cell<(T,U)>>,
|
||||||
marker_u: InvariantType<U>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unsafe_destructor]
|
#[unsafe_destructor]
|
||||||
@ -2589,7 +2605,7 @@ mod tests {
|
|||||||
b.bytes = src_len as u64;
|
b.bytes = src_len as u64;
|
||||||
|
|
||||||
b.iter(|| {
|
b.iter(|| {
|
||||||
let dst = src.clone()[].to_vec();
|
let dst = src.clone()[..].to_vec();
|
||||||
assert_eq!(dst.len(), src_len);
|
assert_eq!(dst.len(), src_len);
|
||||||
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
assert!(dst.iter().enumerate().all(|(i, x)| i == *x));
|
||||||
});
|
});
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -20,7 +20,8 @@ use core::prelude::*;
|
|||||||
use core::cmp::Ordering;
|
use core::cmp::Ordering;
|
||||||
use core::default::Default;
|
use core::default::Default;
|
||||||
use core::fmt;
|
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::{Enumerate, FilterMap, Map, FromIterator, IntoIterator};
|
||||||
use core::iter;
|
use core::iter;
|
||||||
use core::mem::replace;
|
use core::mem::replace;
|
||||||
@ -99,6 +100,7 @@ impl<V> Default for VecMap<V> {
|
|||||||
fn default() -> VecMap<V> { VecMap::new() }
|
fn default() -> VecMap<V> { VecMap::new() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<V:Clone> Clone for VecMap<V> {
|
impl<V:Clone> Clone for VecMap<V> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clone(&self) -> VecMap<V> {
|
fn clone(&self) -> VecMap<V> {
|
||||||
@ -111,6 +113,7 @@ impl<V:Clone> Clone for VecMap<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
impl<S: Writer + Hasher, V: Hash<S>> Hash<S> for VecMap<V> {
|
impl<S: Writer + Hasher, V: Hash<S>> Hash<S> for VecMap<V> {
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
// In order to not traverse the `VecMap` twice, count the elements
|
// In order to not traverse the `VecMap` twice, count the elements
|
||||||
@ -123,6 +126,20 @@ impl<S: Writer + Hasher, V: Hash<S>> Hash<S> for VecMap<V> {
|
|||||||
count.hash(state);
|
count.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
impl<V: Hash> Hash for VecMap<V> {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
// In order to not traverse the `VecMap` twice, count the elements
|
||||||
|
// during iteration.
|
||||||
|
let mut count: usize = 0;
|
||||||
|
for elt in self {
|
||||||
|
elt.hash(state);
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
count.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<V> VecMap<V> {
|
impl<V> VecMap<V> {
|
||||||
/// Creates an empty `VecMap`.
|
/// Creates an empty `VecMap`.
|
||||||
@ -661,7 +678,7 @@ impl<V: fmt::Debug> fmt::Debug for VecMap<V> {
|
|||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<V> FromIterator<(usize, V)> for VecMap<V> {
|
impl<V> FromIterator<(usize, V)> for VecMap<V> {
|
||||||
fn from_iter<Iter: Iterator<Item=(usize, V)>>(iter: Iter) -> VecMap<V> {
|
fn from_iter<I: IntoIterator<Item=(usize, V)>>(iter: I) -> VecMap<V> {
|
||||||
let mut map = VecMap::new();
|
let mut map = VecMap::new();
|
||||||
map.extend(iter);
|
map.extend(iter);
|
||||||
map
|
map
|
||||||
@ -700,7 +717,7 @@ impl<'a, T> IntoIterator for &'a mut VecMap<T> {
|
|||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<V> Extend<(usize, V)> for VecMap<V> {
|
impl<V> Extend<(usize, V)> for VecMap<V> {
|
||||||
fn extend<Iter: Iterator<Item=(usize, V)>>(&mut self, iter: Iter) {
|
fn extend<I: IntoIterator<Item=(usize, V)>>(&mut self, iter: I) {
|
||||||
for (k, v) in iter {
|
for (k, v) in iter {
|
||||||
self.insert(k, v);
|
self.insert(k, v);
|
||||||
}
|
}
|
||||||
@ -859,7 +876,7 @@ pub struct IntoIter<V> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "collections")]
|
#[unstable(feature = "collections")]
|
||||||
pub struct Drain<'a, V> {
|
pub struct Drain<'a, V:'a> {
|
||||||
iter: FilterMap<
|
iter: FilterMap<
|
||||||
Enumerate<vec::Drain<'a, Option<V>>>,
|
Enumerate<vec::Drain<'a, Option<V>>>,
|
||||||
fn((usize, Option<V>)) -> Option<(usize, V)>>
|
fn((usize, Option<V>)) -> Option<(usize, V)>>
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
|
use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
|
||||||
use fmt;
|
use fmt;
|
||||||
use hash::{Hash, Hasher, self};
|
use hash::{Hash, self};
|
||||||
use iter::IntoIterator;
|
use iter::IntoIterator;
|
||||||
use marker::Copy;
|
use marker::Copy;
|
||||||
use ops::Deref;
|
use ops::Deref;
|
||||||
@ -35,16 +35,24 @@ macro_rules! array_impls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S: hash::Writer + Hasher, T: Hash<S>> Hash<S> for [T; $N] {
|
#[cfg(stage0)]
|
||||||
|
impl<S: hash::Writer + hash::Hasher, T: Hash<S>> Hash<S> for [T; $N] {
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
Hash::hash(&self[], state)
|
Hash::hash(&self[..], state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T: Hash> Hash for [T; $N] {
|
||||||
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
|
Hash::hash(&self[..], state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: fmt::Debug> fmt::Debug for [T; $N] {
|
impl<T: fmt::Debug> fmt::Debug for [T; $N] {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
fmt::Debug::fmt(&&self[], f)
|
fmt::Debug::fmt(&&self[..], f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,11 +80,11 @@ macro_rules! array_impls {
|
|||||||
impl<A, B> PartialEq<[B; $N]> for [A; $N] where A: PartialEq<B> {
|
impl<A, B> PartialEq<[B; $N]> for [A; $N] where A: PartialEq<B> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn eq(&self, other: &[B; $N]) -> bool {
|
fn eq(&self, other: &[B; $N]) -> bool {
|
||||||
&self[] == &other[]
|
&self[..] == &other[..]
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ne(&self, other: &[B; $N]) -> bool {
|
fn ne(&self, other: &[B; $N]) -> bool {
|
||||||
&self[] != &other[]
|
&self[..] != &other[..]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,11 +95,11 @@ macro_rules! array_impls {
|
|||||||
{
|
{
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn eq(&self, other: &Rhs) -> bool {
|
fn eq(&self, other: &Rhs) -> bool {
|
||||||
PartialEq::eq(&self[], &**other)
|
PartialEq::eq(&self[..], &**other)
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn ne(&self, other: &Rhs) -> bool {
|
fn ne(&self, other: &Rhs) -> bool {
|
||||||
PartialEq::ne(&self[], &**other)
|
PartialEq::ne(&self[..], &**other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,11 +110,11 @@ macro_rules! array_impls {
|
|||||||
{
|
{
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn eq(&self, other: &[B; $N]) -> bool {
|
fn eq(&self, other: &[B; $N]) -> bool {
|
||||||
PartialEq::eq(&**self, &other[])
|
PartialEq::eq(&**self, &other[..])
|
||||||
}
|
}
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn ne(&self, other: &[B; $N]) -> bool {
|
fn ne(&self, other: &[B; $N]) -> bool {
|
||||||
PartialEq::ne(&**self, &other[])
|
PartialEq::ne(&**self, &other[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,23 +125,23 @@ macro_rules! array_impls {
|
|||||||
impl<T:PartialOrd> PartialOrd for [T; $N] {
|
impl<T:PartialOrd> PartialOrd for [T; $N] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &[T; $N]) -> Option<Ordering> {
|
||||||
PartialOrd::partial_cmp(&&self[], &&other[])
|
PartialOrd::partial_cmp(&&self[..], &&other[..])
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn lt(&self, other: &[T; $N]) -> bool {
|
fn lt(&self, other: &[T; $N]) -> bool {
|
||||||
PartialOrd::lt(&&self[], &&other[])
|
PartialOrd::lt(&&self[..], &&other[..])
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn le(&self, other: &[T; $N]) -> bool {
|
fn le(&self, other: &[T; $N]) -> bool {
|
||||||
PartialOrd::le(&&self[], &&other[])
|
PartialOrd::le(&&self[..], &&other[..])
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn ge(&self, other: &[T; $N]) -> bool {
|
fn ge(&self, other: &[T; $N]) -> bool {
|
||||||
PartialOrd::ge(&&self[], &&other[])
|
PartialOrd::ge(&&self[..], &&other[..])
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
fn gt(&self, other: &[T; $N]) -> bool {
|
fn gt(&self, other: &[T; $N]) -> bool {
|
||||||
PartialOrd::gt(&&self[], &&other[])
|
PartialOrd::gt(&&self[..], &&other[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -141,7 +149,7 @@ macro_rules! array_impls {
|
|||||||
impl<T:Ord> Ord for [T; $N] {
|
impl<T:Ord> Ord for [T; $N] {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn cmp(&self, other: &[T; $N]) -> Ordering {
|
fn cmp(&self, other: &[T; $N]) -> Ordering {
|
||||||
Ord::cmp(&&self[], &&other[])
|
Ord::cmp(&&self[..], &&other[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)+
|
)+
|
||||||
|
@ -76,6 +76,7 @@ use marker::Sync;
|
|||||||
|
|
||||||
use intrinsics;
|
use intrinsics;
|
||||||
use cell::UnsafeCell;
|
use cell::UnsafeCell;
|
||||||
|
use marker::PhantomData;
|
||||||
|
|
||||||
/// A boolean type which can be safely shared between threads.
|
/// A boolean type which can be safely shared between threads.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@ -105,6 +106,7 @@ unsafe impl Sync for AtomicUsize {}
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct AtomicPtr<T> {
|
pub struct AtomicPtr<T> {
|
||||||
p: UnsafeCell<usize>,
|
p: UnsafeCell<usize>,
|
||||||
|
_marker: PhantomData<*mut T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<T> Sync for AtomicPtr<T> {}
|
unsafe impl<T> Sync for AtomicPtr<T> {}
|
||||||
@ -791,7 +793,8 @@ impl<T> AtomicPtr<T> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn new(p: *mut T) -> AtomicPtr<T> {
|
pub fn new(p: *mut T) -> AtomicPtr<T> {
|
||||||
AtomicPtr { p: UnsafeCell::new(p as usize) }
|
AtomicPtr { p: UnsafeCell::new(p as usize),
|
||||||
|
_marker: PhantomData }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads a value from the pointer.
|
/// Loads a value from the pointer.
|
||||||
|
@ -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 <LICENSE-APACHE or
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
||||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
||||||
// option. This file may not be copied, modified, or distributed
|
|
||||||
// except according to those terms.
|
|
||||||
|
|
||||||
//! A module for working with borrowed data.
|
|
||||||
//!
|
|
||||||
//! # The `BorrowFrom` traits
|
|
||||||
//!
|
|
||||||
//! In general, there may be several ways to "borrow" a piece of data. The
|
|
||||||
//! typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
|
|
||||||
//! (a mutable borrow). But types like `Vec<T>` provide additional kinds of
|
|
||||||
//! borrows: the borrowed slices `&[T]` and `&mut [T]`.
|
|
||||||
//!
|
|
||||||
//! When writing generic code, it is often desirable to abstract over all ways
|
|
||||||
//! of borrowing data from a given type. That is the role of the `BorrowFrom`
|
|
||||||
//! trait: if `T: BorrowFrom<U>`, then `&T` can be borrowed from `&U`. A given
|
|
||||||
//! type can be borrowed as multiple different types. In particular, `Vec<T>:
|
|
||||||
//! BorrowFrom<Vec<T>>` and `[T]: BorrowFrom<Vec<T>>`.
|
|
||||||
//!
|
|
||||||
//! # The `ToOwned` trait
|
|
||||||
//!
|
|
||||||
//! Some types make it possible to go from borrowed to owned, usually by
|
|
||||||
//! implementing the `Clone` trait. But `Clone` works only for going from `&T`
|
|
||||||
//! to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
|
|
||||||
//! from any borrow of a given type.
|
|
||||||
//!
|
|
||||||
//! # The `Cow` (clone-on-write) type
|
|
||||||
//!
|
|
||||||
//! The type `Cow` is a smart pointer providing clone-on-write functionality: it
|
|
||||||
//! can enclose and provide immutable access to borrowed data, and clone the
|
|
||||||
//! data lazily when mutation or ownership is required. The type is designed to
|
|
||||||
//! work with general borrowed data via the `BorrowFrom` trait.
|
|
||||||
//!
|
|
||||||
//! `Cow` implements both `Deref`, which means that you can call
|
|
||||||
//! non-mutating methods directly on the data it encloses. If mutation
|
|
||||||
//! is desired, `to_mut` will obtain a mutable references to an owned
|
|
||||||
//! value, cloning if necessary.
|
|
||||||
|
|
||||||
#![unstable(feature = "core",
|
|
||||||
reason = "recently added as part of collections reform")]
|
|
||||||
|
|
||||||
use clone::Clone;
|
|
||||||
use cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd};
|
|
||||||
use fmt;
|
|
||||||
use marker::Sized;
|
|
||||||
use ops::Deref;
|
|
||||||
use option::Option;
|
|
||||||
use self::Cow::*;
|
|
||||||
|
|
||||||
/// A trait for borrowing data.
|
|
||||||
#[old_orphan_check]
|
|
||||||
pub trait BorrowFrom<Owned: ?Sized> {
|
|
||||||
/// Immutably borrow from an owned value.
|
|
||||||
fn borrow_from(owned: &Owned) -> &Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A trait for mutably borrowing data.
|
|
||||||
#[old_orphan_check]
|
|
||||||
pub trait BorrowFromMut<Owned: ?Sized> : BorrowFrom<Owned> {
|
|
||||||
/// Mutably borrow from an owned value.
|
|
||||||
fn borrow_from_mut(owned: &mut Owned) -> &mut Self;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ?Sized> BorrowFrom<T> for T {
|
|
||||||
fn borrow_from(owned: &T) -> &T { owned }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ?Sized> BorrowFromMut<T> for T {
|
|
||||||
fn borrow_from_mut(owned: &mut T) -> &mut T { owned }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: ?Sized> BorrowFrom<&'a T> for T {
|
|
||||||
fn borrow_from<'b>(owned: &'b &'a T) -> &'b T { &**owned }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: ?Sized> BorrowFrom<&'a mut T> for T {
|
|
||||||
fn borrow_from<'b>(owned: &'b &'a mut T) -> &'b T { &**owned }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T: ?Sized> BorrowFromMut<&'a mut T> for T {
|
|
||||||
fn borrow_from_mut<'b>(owned: &'b mut &'a mut T) -> &'b mut T { &mut **owned }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T, B: ?Sized> BorrowFrom<Cow<'a, T, B>> for B where B: ToOwned<T> {
|
|
||||||
fn borrow_from<'b>(owned: &'b Cow<'a, T, B>) -> &'b B {
|
|
||||||
&**owned
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Trait for moving into a `Cow`
|
|
||||||
#[old_orphan_check]
|
|
||||||
pub trait IntoCow<'a, T, B: ?Sized> {
|
|
||||||
/// Moves `self` into `Cow`
|
|
||||||
fn into_cow(self) -> Cow<'a, T, B>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T, B: ?Sized> IntoCow<'a, T, B> for Cow<'a, T, B> where B: ToOwned<T> {
|
|
||||||
fn into_cow(self) -> Cow<'a, T, B> {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A generalization of Clone to borrowed data.
|
|
||||||
#[old_orphan_check]
|
|
||||||
pub trait ToOwned<Owned>: BorrowFrom<Owned> {
|
|
||||||
/// Create owned data from borrowed data, usually by copying.
|
|
||||||
fn to_owned(&self) -> Owned;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> ToOwned<T> for T where T: Clone {
|
|
||||||
fn to_owned(&self) -> T { self.clone() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A clone-on-write smart pointer.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// ```rust
|
|
||||||
/// use std::borrow::Cow;
|
|
||||||
///
|
|
||||||
/// fn abs_all(input: &mut Cow<Vec<int>, [int]>) {
|
|
||||||
/// for i in 0..input.len() {
|
|
||||||
/// let v = input[i];
|
|
||||||
/// if v < 0 {
|
|
||||||
/// // clones into a vector the first time (if not already owned)
|
|
||||||
/// input.to_mut()[i] = -v;
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
pub enum Cow<'a, T, B: ?Sized + 'a> where B: ToOwned<T> {
|
|
||||||
/// Borrowed data.
|
|
||||||
Borrowed(&'a B),
|
|
||||||
|
|
||||||
/// Owned data.
|
|
||||||
Owned(T)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<'a, T, B: ?Sized> Clone for Cow<'a, T, B> where B: ToOwned<T> {
|
|
||||||
fn clone(&self) -> Cow<'a, T, B> {
|
|
||||||
match *self {
|
|
||||||
Borrowed(b) => Borrowed(b),
|
|
||||||
Owned(ref o) => {
|
|
||||||
let b: &B = BorrowFrom::borrow_from(o);
|
|
||||||
Owned(b.to_owned())
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, T, B: ?Sized> Cow<'a, T, B> where B: ToOwned<T> {
|
|
||||||
/// Acquire a mutable reference to the owned form of the data.
|
|
||||||
///
|
|
||||||
/// Copies the data if it is not already owned.
|
|
||||||
pub fn to_mut(&mut self) -> &mut T {
|
|
||||||
match *self {
|
|
||||||
Borrowed(borrowed) => {
|
|
||||||
*self = Owned(borrowed.to_owned());
|
|
||||||
self.to_mut()
|
|
||||||
}
|
|
||||||
Owned(ref mut owned) => owned
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extract the owned data.
|
|
||||||
///
|
|
||||||
/// Copies the data if it is not already owned.
|
|
||||||
pub fn into_owned(self) -> T {
|
|
||||||
match self {
|
|
||||||
Borrowed(borrowed) => borrowed.to_owned(),
|
|
||||||
Owned(owned) => owned
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if this `Cow` wraps a borrowed value
|
|
||||||
pub fn is_borrowed(&self) -> bool {
|
|
||||||
match *self {
|
|
||||||
Borrowed(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if this `Cow` wraps an owned value
|
|
||||||
pub fn is_owned(&self) -> bool {
|
|
||||||
match *self {
|
|
||||||
Owned(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<'a, T, B: ?Sized> Deref for Cow<'a, T, B> where B: ToOwned<T> {
|
|
||||||
type Target = B;
|
|
||||||
|
|
||||||
fn deref(&self) -> &B {
|
|
||||||
match *self {
|
|
||||||
Borrowed(borrowed) => borrowed,
|
|
||||||
Owned(ref owned) => BorrowFrom::borrow_from(owned)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<'a, T, B: ?Sized> Eq for Cow<'a, T, B> where B: Eq + ToOwned<T> {}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<'a, T, B: ?Sized> Ord for Cow<'a, T, B> where B: Ord + ToOwned<T> {
|
|
||||||
#[inline]
|
|
||||||
fn cmp(&self, other: &Cow<'a, T, B>) -> Ordering {
|
|
||||||
Ord::cmp(&**self, &**other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<'a, 'b, T, U, B: ?Sized, C: ?Sized> PartialEq<Cow<'b, U, C>> for Cow<'a, T, B> where
|
|
||||||
B: PartialEq<C> + ToOwned<T>,
|
|
||||||
C: ToOwned<U>,
|
|
||||||
{
|
|
||||||
#[inline]
|
|
||||||
fn eq(&self, other: &Cow<'b, U, C>) -> bool {
|
|
||||||
PartialEq::eq(&**self, &**other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<'a, T, B: ?Sized> PartialOrd for Cow<'a, T, B> where B: PartialOrd + ToOwned<T> {
|
|
||||||
#[inline]
|
|
||||||
fn partial_cmp(&self, other: &Cow<'a, T, B>) -> Option<Ordering> {
|
|
||||||
PartialOrd::partial_cmp(&**self, &**other)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<'a, T, B: ?Sized> fmt::Debug for Cow<'a, T, B> where
|
|
||||||
B: fmt::Debug + ToOwned<T>,
|
|
||||||
T: fmt::Debug,
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
match *self {
|
|
||||||
Borrowed(ref b) => fmt::Debug::fmt(b, f),
|
|
||||||
Owned(ref o) => fmt::Debug::fmt(o, f),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
|
||||||
impl<'a, T, B: ?Sized> fmt::Display for Cow<'a, T, B> where
|
|
||||||
B: fmt::Display + ToOwned<T>,
|
|
||||||
T: fmt::Display,
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
match *self {
|
|
||||||
Borrowed(ref b) => fmt::Display::fmt(b, f),
|
|
||||||
Owned(ref o) => fmt::Display::fmt(o, f),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -215,7 +215,7 @@ impl Ord for Ordering {
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn cmp(&self, other: &Ordering) -> Ordering {
|
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]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
|
||||||
(*self as int).partial_cmp(&(*other as int))
|
(*self as i32).partial_cmp(&(*other as i32))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -482,7 +482,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
|
|
||||||
partial_eq_impl! {
|
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 {
|
macro_rules! eq_impl {
|
||||||
@ -492,7 +492,7 @@ mod impls {
|
|||||||
)*)
|
)*)
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
macro_rules! partial_ord_impl {
|
||||||
($($t:ty)*) => ($(
|
($($t:ty)*) => ($(
|
||||||
@ -535,7 +535,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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 {
|
macro_rules! ord_impl {
|
||||||
($($t:ty)*) => ($(
|
($($t:ty)*) => ($(
|
||||||
@ -565,7 +565,7 @@ mod impls {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
// & pointers
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
//!
|
//!
|
||||||
//! ```
|
//! ```
|
||||||
//! struct SomeOptions {
|
//! struct SomeOptions {
|
||||||
//! foo: int,
|
//! foo: i32,
|
||||||
//! bar: f32,
|
//! bar: f32,
|
||||||
//! }
|
//! }
|
||||||
//! ```
|
//! ```
|
||||||
@ -28,7 +28,7 @@
|
|||||||
//!
|
//!
|
||||||
//! #[derive(Default)]
|
//! #[derive(Default)]
|
||||||
//! struct SomeOptions {
|
//! struct SomeOptions {
|
||||||
//! foo: int,
|
//! foo: i32,
|
||||||
//! bar: f32,
|
//! bar: f32,
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
@ -56,7 +56,7 @@
|
|||||||
//!
|
//!
|
||||||
//! #[derive(Default)]
|
//! #[derive(Default)]
|
||||||
//! struct SomeOptions {
|
//! struct SomeOptions {
|
||||||
//! foo: int,
|
//! foo: i32,
|
||||||
//! bar: f32,
|
//! bar: f32,
|
||||||
//! baz: Kind,
|
//! baz: Kind,
|
||||||
//! }
|
//! }
|
||||||
@ -73,7 +73,7 @@
|
|||||||
//! # use std::default::Default;
|
//! # use std::default::Default;
|
||||||
//! # #[derive(Default)]
|
//! # #[derive(Default)]
|
||||||
//! # struct SomeOptions {
|
//! # struct SomeOptions {
|
||||||
//! # foo: int,
|
//! # foo: i32,
|
||||||
//! # bar: f32,
|
//! # bar: f32,
|
||||||
//! # }
|
//! # }
|
||||||
//! fn main() {
|
//! fn main() {
|
||||||
@ -93,7 +93,7 @@
|
|||||||
/// ```
|
/// ```
|
||||||
/// #[derive(Default)]
|
/// #[derive(Default)]
|
||||||
/// struct SomeOptions {
|
/// struct SomeOptions {
|
||||||
/// foo: int,
|
/// foo: i32,
|
||||||
/// bar: f32,
|
/// bar: f32,
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
@ -113,7 +113,7 @@ pub trait Default {
|
|||||||
///
|
///
|
||||||
/// let i: i8 = Default::default();
|
/// let i: i8 = Default::default();
|
||||||
/// let (x, y): (Option<String>, f64) = Default::default();
|
/// let (x, y): (Option<String>, f64) = Default::default();
|
||||||
/// let (a, b, (c, d)): (int, uint, (bool, bool)) = Default::default();
|
/// let (a, b, (c, d)): (i32, u32, (bool, bool)) = Default::default();
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
/// Making your own:
|
/// Making your own:
|
||||||
@ -150,13 +150,13 @@ default_impl! { (), () }
|
|||||||
default_impl! { bool, false }
|
default_impl! { bool, false }
|
||||||
default_impl! { char, '\x00' }
|
default_impl! { char, '\x00' }
|
||||||
|
|
||||||
default_impl! { uint, 0 }
|
default_impl! { usize, 0 }
|
||||||
default_impl! { u8, 0 }
|
default_impl! { u8, 0 }
|
||||||
default_impl! { u16, 0 }
|
default_impl! { u16, 0 }
|
||||||
default_impl! { u32, 0 }
|
default_impl! { u32, 0 }
|
||||||
default_impl! { u64, 0 }
|
default_impl! { u64, 0 }
|
||||||
|
|
||||||
default_impl! { int, 0 }
|
default_impl! { isize, 0 }
|
||||||
default_impl! { i8, 0 }
|
default_impl! { i8, 0 }
|
||||||
default_impl! { i16, 0 }
|
default_impl! { i16, 0 }
|
||||||
default_impl! { i32, 0 }
|
default_impl! { i32, 0 }
|
||||||
|
@ -16,7 +16,7 @@ use any;
|
|||||||
use cell::{Cell, RefCell, Ref, RefMut, BorrowState};
|
use cell::{Cell, RefCell, Ref, RefMut, BorrowState};
|
||||||
use char::CharExt;
|
use char::CharExt;
|
||||||
use iter::{Iterator, IteratorExt};
|
use iter::{Iterator, IteratorExt};
|
||||||
use marker::{Copy, Sized};
|
use marker::{Copy, PhantomData, Sized};
|
||||||
use mem;
|
use mem;
|
||||||
use option::Option;
|
use option::Option;
|
||||||
use option::Option::{Some, None};
|
use option::Option::{Some, None};
|
||||||
@ -914,6 +914,11 @@ impl Debug for () {
|
|||||||
f.pad("()")
|
f.pad("()")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<T> Debug for PhantomData<T> {
|
||||||
|
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||||
|
f.pad("PhantomData")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<T: Copy + Debug> Debug for Cell<T> {
|
impl<T: Copy + Debug> Debug for Cell<T> {
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
//! the trait `Hash`:
|
//! the trait `Hash`:
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
//! ```rust
|
||||||
//! use std::hash::{hash, Hash, Hasher, Writer, SipHasher};
|
//! use std::hash::{hash, Hash, Hasher, SipHasher};
|
||||||
//!
|
//!
|
||||||
//! struct Person {
|
//! struct Person {
|
||||||
//! id: uint,
|
//! id: uint,
|
||||||
@ -43,8 +43,8 @@
|
|||||||
//! phone: u64,
|
//! phone: u64,
|
||||||
//! }
|
//! }
|
||||||
//!
|
//!
|
||||||
//! impl<H: Hasher + Writer> Hash<H> for Person {
|
//! impl Hash for Person {
|
||||||
//! fn hash(&self, state: &mut H) {
|
//! fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
//! self.id.hash(state);
|
//! self.id.hash(state);
|
||||||
//! self.phone.hash(state);
|
//! self.phone.hash(state);
|
||||||
//! }
|
//! }
|
||||||
@ -56,15 +56,12 @@
|
|||||||
//! assert_eq!(hash::<_, SipHasher>(&person1), hash::<_, SipHasher>(&person2));
|
//! assert_eq!(hash::<_, SipHasher>(&person1), hash::<_, SipHasher>(&person2));
|
||||||
//! ```
|
//! ```
|
||||||
|
|
||||||
#![unstable(feature = "hash",
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
reason = "module was recently redesigned")]
|
|
||||||
|
|
||||||
use prelude::*;
|
use prelude::*;
|
||||||
|
|
||||||
use borrow::{Cow, ToOwned};
|
|
||||||
use default::Default;
|
use default::Default;
|
||||||
use mem;
|
use mem;
|
||||||
use num::Int;
|
|
||||||
|
|
||||||
pub use self::sip::SipHasher;
|
pub use self::sip::SipHasher;
|
||||||
|
|
||||||
@ -76,22 +73,123 @@ mod sip;
|
|||||||
/// to compute the hash. Specific implementations of this trait may specialize
|
/// to compute the hash. Specific implementations of this trait may specialize
|
||||||
/// for particular instances of `H` in order to be able to optimize the hashing
|
/// for particular instances of `H` in order to be able to optimize the hashing
|
||||||
/// behavior.
|
/// behavior.
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub trait Hash {
|
||||||
|
/// Feeds this value into the state given, updating the hasher as necessary.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H);
|
||||||
|
|
||||||
|
/// Feeds a slice of this type into the state provided.
|
||||||
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
|
fn hash_slice<H: Hasher>(data: &[Self], state: &mut H) where Self: Sized {
|
||||||
|
for piece in data {
|
||||||
|
piece.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A hashable type.
|
||||||
|
///
|
||||||
|
/// The `H` type parameter is an abstract hash state that is used by the `Hash`
|
||||||
|
/// to compute the hash. Specific implementations of this trait may specialize
|
||||||
|
/// for particular instances of `H` in order to be able to optimize the hashing
|
||||||
|
/// behavior.
|
||||||
|
#[cfg(stage0)]
|
||||||
pub trait Hash<H: Hasher> {
|
pub trait Hash<H: Hasher> {
|
||||||
/// Feeds this value into the state given, updating the hasher as necessary.
|
/// Feeds this value into the state given, updating the hasher as necessary.
|
||||||
fn hash(&self, state: &mut H);
|
fn hash(&self, state: &mut H);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A trait which represents the ability to hash an arbitrary stream of bytes.
|
/// A trait which represents the ability to hash an arbitrary stream of bytes.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub trait Hasher {
|
pub trait Hasher {
|
||||||
/// Result type of one run of hashing generated by this hasher.
|
/// Result type of one run of hashing generated by this hasher.
|
||||||
|
#[cfg(stage0)]
|
||||||
type Output;
|
type Output;
|
||||||
|
|
||||||
/// Resets this hasher back to its initial state (as if it were just
|
/// Resets this hasher back to its initial state (as if it were just
|
||||||
/// created).
|
/// created).
|
||||||
|
#[cfg(stage0)]
|
||||||
fn reset(&mut self);
|
fn reset(&mut self);
|
||||||
|
|
||||||
/// Completes a round of hashing, producing the output hash generated.
|
/// Completes a round of hashing, producing the output hash generated.
|
||||||
|
#[cfg(stage0)]
|
||||||
fn finish(&self) -> Self::Output;
|
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
|
/// A common bound on the `Hasher` parameter to `Hash` implementations in order
|
||||||
@ -99,6 +197,7 @@ pub trait Hasher {
|
|||||||
#[unstable(feature = "hash",
|
#[unstable(feature = "hash",
|
||||||
reason = "this trait will likely be replaced by io::Writer")]
|
reason = "this trait will likely be replaced by io::Writer")]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
|
#[cfg(stage0)]
|
||||||
pub trait Writer {
|
pub trait Writer {
|
||||||
fn write(&mut self, bytes: &[u8]);
|
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
|
/// The specified value will be hashed with this hasher and then the resulting
|
||||||
/// hash will be returned.
|
/// hash will be returned.
|
||||||
|
#[cfg(stage0)]
|
||||||
pub fn hash<T: Hash<H>, H: Hasher + Default>(value: &T) -> H::Output {
|
pub fn hash<T: Hash<H>, H: Hasher + Default>(value: &T) -> H::Output {
|
||||||
let mut h: H = Default::default();
|
let mut h: H = Default::default();
|
||||||
value.hash(&mut h);
|
value.hash(&mut h);
|
||||||
h.finish()
|
h.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Hash a value with the default SipHasher algorithm (two initial keys of 0).
|
||||||
|
///
|
||||||
|
/// The specified value will be hashed with this hasher and then the resulting
|
||||||
|
/// hash will be returned.
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
#[unstable(feature = "hash", reason = "module was recently redesigned")]
|
||||||
|
pub fn hash<T: Hash, H: Hasher + Default>(value: &T) -> u64 {
|
||||||
|
let mut h: H = Default::default();
|
||||||
|
value.hash(&mut h);
|
||||||
|
h.finish()
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
macro_rules! impl_hash {
|
#[cfg(stage0)]
|
||||||
($ty:ident, $uty:ident) => {
|
mod impls {
|
||||||
impl<S: Writer + Hasher> Hash<S> for $ty {
|
use prelude::*;
|
||||||
#[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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_hash! { u8, u8 }
|
use mem;
|
||||||
impl_hash! { u16, u16 }
|
use num::Int;
|
||||||
impl_hash! { u32, u32 }
|
use super::*;
|
||||||
impl_hash! { u64, u64 }
|
|
||||||
impl_hash! { uint, uint }
|
|
||||||
impl_hash! { i8, u8 }
|
|
||||||
impl_hash! { i16, u16 }
|
|
||||||
impl_hash! { i32, u32 }
|
|
||||||
impl_hash! { i64, u64 }
|
|
||||||
impl_hash! { int, uint }
|
|
||||||
|
|
||||||
impl<S: Writer + Hasher> Hash<S> for bool {
|
macro_rules! impl_hash {
|
||||||
#[inline]
|
($ty:ident, $uty:ident) => {
|
||||||
fn hash(&self, state: &mut S) {
|
impl<S: Writer + Hasher> Hash<S> for $ty {
|
||||||
(*self as u8).hash(state);
|
#[inline]
|
||||||
}
|
fn hash(&self, state: &mut S) {
|
||||||
}
|
let a: [u8; ::$ty::BYTES] = unsafe {
|
||||||
|
mem::transmute(*self)
|
||||||
impl<S: Writer + Hasher> Hash<S> for char {
|
};
|
||||||
#[inline]
|
state.write(&a)
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
(*self as u32).hash(state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<S: Writer + Hasher> Hash<S> for str {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
state.write(self.as_bytes());
|
|
||||||
0xffu8.hash(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_hash_tuple {
|
|
||||||
() => (
|
|
||||||
impl<S: Hasher> Hash<S> for () {
|
|
||||||
#[inline]
|
|
||||||
fn hash(&self, _state: &mut S) {}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
( $($name:ident)+) => (
|
|
||||||
impl<S: Hasher, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
|
|
||||||
#[inline]
|
|
||||||
#[allow(non_snake_case)]
|
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
match *self {
|
|
||||||
($(ref $name,)*) => {
|
|
||||||
$(
|
|
||||||
$name.hash(state);
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl_hash_tuple! {}
|
impl_hash! { u8, u8 }
|
||||||
impl_hash_tuple! { A }
|
impl_hash! { u16, u16 }
|
||||||
impl_hash_tuple! { A B }
|
impl_hash! { u32, u32 }
|
||||||
impl_hash_tuple! { A B C }
|
impl_hash! { u64, u64 }
|
||||||
impl_hash_tuple! { A B C D }
|
impl_hash! { uint, uint }
|
||||||
impl_hash_tuple! { A B C D E }
|
impl_hash! { i8, u8 }
|
||||||
impl_hash_tuple! { A B C D E F }
|
impl_hash! { i16, u16 }
|
||||||
impl_hash_tuple! { A B C D E F G }
|
impl_hash! { i32, u32 }
|
||||||
impl_hash_tuple! { A B C D E F G H }
|
impl_hash! { i64, u64 }
|
||||||
impl_hash_tuple! { A B C D E F G H I }
|
impl_hash! { int, uint }
|
||||||
impl_hash_tuple! { A B C D E F G H I J }
|
|
||||||
impl_hash_tuple! { A B C D E F G H I J K }
|
|
||||||
impl_hash_tuple! { A B C D E F G H I J K L }
|
|
||||||
|
|
||||||
impl<S: Writer + Hasher, T: Hash<S>> Hash<S> for [T] {
|
impl<S: Writer + Hasher> Hash<S> for bool {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
self.len().hash(state);
|
(*self as u8).hash(state);
|
||||||
for elt in self {
|
}
|
||||||
elt.hash(state);
|
}
|
||||||
|
|
||||||
|
impl<S: Writer + Hasher> Hash<S> for char {
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, state: &mut S) {
|
||||||
|
(*self as u32).hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: Writer + Hasher> Hash<S> for str {
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, state: &mut S) {
|
||||||
|
state.write(self.as_bytes());
|
||||||
|
0xffu8.hash(state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_hash_tuple {
|
||||||
|
() => (
|
||||||
|
impl<S: Hasher> Hash<S> for () {
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, _state: &mut S) {}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
( $($name:ident)+) => (
|
||||||
|
impl<S: Hasher, $($name: Hash<S>),*> Hash<S> for ($($name,)*) {
|
||||||
|
#[inline]
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn hash(&self, state: &mut S) {
|
||||||
|
match *self {
|
||||||
|
($(ref $name,)*) => {
|
||||||
|
$(
|
||||||
|
$name.hash(state);
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_hash_tuple! {}
|
||||||
|
impl_hash_tuple! { A }
|
||||||
|
impl_hash_tuple! { A B }
|
||||||
|
impl_hash_tuple! { A B C }
|
||||||
|
impl_hash_tuple! { A B C D }
|
||||||
|
impl_hash_tuple! { A B C D E }
|
||||||
|
impl_hash_tuple! { A B C D E F }
|
||||||
|
impl_hash_tuple! { A B C D E F G }
|
||||||
|
impl_hash_tuple! { A B C D E F G H }
|
||||||
|
impl_hash_tuple! { A B C D E F G H I }
|
||||||
|
impl_hash_tuple! { A B C D E F G H I J }
|
||||||
|
impl_hash_tuple! { A B C D E F G H I J K }
|
||||||
|
impl_hash_tuple! { A B C D E F G H I J K L }
|
||||||
|
|
||||||
|
impl<S: Writer + Hasher, T: Hash<S>> Hash<S> for [T] {
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, state: &mut S) {
|
||||||
|
self.len().hash(state);
|
||||||
|
for elt in self {
|
||||||
|
elt.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a T {
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, state: &mut S) {
|
||||||
|
(**self).hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, state: &mut S) {
|
||||||
|
(**self).hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: Writer + Hasher, T> Hash<S> for *const T {
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, state: &mut S) {
|
||||||
|
// NB: raw-pointer Hash does _not_ dereference
|
||||||
|
// to the target; it just gives you the pointer-bytes.
|
||||||
|
(*self as uint).hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<S: Writer + Hasher, T> Hash<S> for *mut T {
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, state: &mut S) {
|
||||||
|
// NB: raw-pointer Hash does _not_ dereference
|
||||||
|
// to the target; it just gives you the pointer-bytes.
|
||||||
|
(*self as uint).hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
mod impls {
|
||||||
|
use prelude::*;
|
||||||
|
|
||||||
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a T {
|
use slice;
|
||||||
#[inline]
|
use super::*;
|
||||||
fn hash(&self, state: &mut S) {
|
|
||||||
(**self).hash(state);
|
macro_rules! impl_write {
|
||||||
}
|
($(($ty:ident, $meth:ident),)*) => {$(
|
||||||
}
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl Hash for $ty {
|
||||||
impl<'a, S: Hasher, T: ?Sized + Hash<S>> Hash<S> for &'a mut T {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
#[inline]
|
state.$meth(*self)
|
||||||
fn hash(&self, state: &mut S) {
|
}
|
||||||
(**self).hash(state);
|
|
||||||
}
|
fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
|
||||||
}
|
let newlen = data.len() * ::$ty::BYTES;
|
||||||
|
let ptr = data.as_ptr() as *const u8;
|
||||||
impl<S: Writer + Hasher, T> Hash<S> for *const T {
|
state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
|
||||||
#[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),
|
||||||
impl<S: Writer + Hasher, T> Hash<S> for *mut T {
|
(u32, write_u32),
|
||||||
#[inline]
|
(u64, write_u64),
|
||||||
fn hash(&self, state: &mut S) {
|
(usize, write_usize),
|
||||||
// NB: raw-pointer Hash does _not_ dereference
|
(i8, write_i8),
|
||||||
// to the target; it just gives you the pointer-bytes.
|
(i16, write_i16),
|
||||||
(*self as uint).hash(state);
|
(i32, write_i32),
|
||||||
}
|
(i64, write_i64),
|
||||||
}
|
(isize, write_isize),
|
||||||
|
}
|
||||||
impl<'a, T, B: ?Sized, S: Hasher> Hash<S> for Cow<'a, T, B>
|
|
||||||
where B: Hash<S> + ToOwned<T>
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
{
|
impl Hash for bool {
|
||||||
#[inline]
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
fn hash(&self, state: &mut S) {
|
state.write_u8(*self as u8)
|
||||||
Hash::hash(&**self, state)
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl Hash for char {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
state.write_u32(*self as u32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl Hash for str {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
state.write(self.as_bytes());
|
||||||
|
state.write_u8(0xff)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_hash_tuple {
|
||||||
|
() => (
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl Hash for () {
|
||||||
|
fn hash<H: Hasher>(&self, _state: &mut H) {}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
( $($name:ident)+) => (
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<$($name: Hash),*> Hash for ($($name,)*) {
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
fn hash<S: Hasher>(&self, state: &mut S) {
|
||||||
|
let ($(ref $name,)*) = *self;
|
||||||
|
$($name.hash(state);)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_hash_tuple! {}
|
||||||
|
impl_hash_tuple! { A }
|
||||||
|
impl_hash_tuple! { A B }
|
||||||
|
impl_hash_tuple! { A B C }
|
||||||
|
impl_hash_tuple! { A B C D }
|
||||||
|
impl_hash_tuple! { A B C D E }
|
||||||
|
impl_hash_tuple! { A B C D E F }
|
||||||
|
impl_hash_tuple! { A B C D E F G }
|
||||||
|
impl_hash_tuple! { A B C D E F G H }
|
||||||
|
impl_hash_tuple! { A B C D E F G H I }
|
||||||
|
impl_hash_tuple! { A B C D E F G H I J }
|
||||||
|
impl_hash_tuple! { A B C D E F G H I J K }
|
||||||
|
impl_hash_tuple! { A B C D E F G H I J K L }
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T: Hash> Hash for [T] {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
self.len().hash(state);
|
||||||
|
Hash::hash_slice(self, state)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, T: ?Sized + Hash> Hash for &'a T {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
(**self).hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<'a, T: ?Sized + Hash> Hash for &'a mut T {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
(**self).hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T> Hash for *const T {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
state.write_usize(*self as usize)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
impl<T> Hash for *mut T {
|
||||||
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
|
state.write_usize(*self as usize)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,9 @@
|
|||||||
use prelude::*;
|
use prelude::*;
|
||||||
use default::Default;
|
use default::Default;
|
||||||
|
|
||||||
use super::{Hasher, Writer};
|
use super::Hasher;
|
||||||
|
#[cfg(stage0)]
|
||||||
|
use super::Writer;
|
||||||
|
|
||||||
/// An implementation of SipHash 2-4.
|
/// An implementation of SipHash 2-4.
|
||||||
///
|
///
|
||||||
@ -30,6 +32,7 @@ use super::{Hasher, Writer};
|
|||||||
/// strong, this implementation has not been reviewed for such purposes.
|
/// strong, this implementation has not been reviewed for such purposes.
|
||||||
/// As such, all cryptographic uses of this implementation are strongly
|
/// As such, all cryptographic uses of this implementation are strongly
|
||||||
/// discouraged.
|
/// discouraged.
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub struct SipHasher {
|
pub struct SipHasher {
|
||||||
k0: u64,
|
k0: u64,
|
||||||
k1: u64,
|
k1: u64,
|
||||||
@ -88,12 +91,14 @@ macro_rules! compress {
|
|||||||
impl SipHasher {
|
impl SipHasher {
|
||||||
/// Creates a new `SipHasher` with the two initial keys set to 0.
|
/// Creates a new `SipHasher` with the two initial keys set to 0.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn new() -> SipHasher {
|
pub fn new() -> SipHasher {
|
||||||
SipHasher::new_with_keys(0, 0)
|
SipHasher::new_with_keys(0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a `SipHasher` that is keyed off the provided keys.
|
/// Creates a `SipHasher` that is keyed off the provided keys.
|
||||||
#[inline]
|
#[inline]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
|
pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
|
||||||
let mut state = SipHasher {
|
let mut state = SipHasher {
|
||||||
k0: key0,
|
k0: key0,
|
||||||
@ -114,10 +119,16 @@ impl SipHasher {
|
|||||||
#[unstable(feature = "hash")]
|
#[unstable(feature = "hash")]
|
||||||
#[deprecated(since = "1.0.0", reason = "renamed to finish")]
|
#[deprecated(since = "1.0.0", reason = "renamed to finish")]
|
||||||
pub fn result(&self) -> u64 { self.finish() }
|
pub fn result(&self) -> u64 { self.finish() }
|
||||||
}
|
|
||||||
|
|
||||||
impl Writer for SipHasher {
|
fn reset(&mut self) {
|
||||||
#[inline]
|
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]) {
|
fn write(&mut self, msg: &[u8]) {
|
||||||
let length = msg.len();
|
let length = msg.len();
|
||||||
self.length += length;
|
self.length += length;
|
||||||
@ -164,16 +175,28 @@ impl Writer for SipHasher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[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 {
|
impl Hasher for SipHasher {
|
||||||
|
#[cfg(stage0)]
|
||||||
type Output = u64;
|
type Output = u64;
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
fn reset(&mut self) {
|
fn reset(&mut self) {
|
||||||
self.length = 0;
|
self.reset();
|
||||||
self.v0 = self.k0 ^ 0x736f6d6570736575;
|
}
|
||||||
self.v1 = self.k1 ^ 0x646f72616e646f6d;
|
|
||||||
self.v2 = self.k0 ^ 0x6c7967656e657261;
|
#[inline]
|
||||||
self.v3 = self.k1 ^ 0x7465646279746573;
|
#[cfg(not(stage0))]
|
||||||
self.ntail = 0;
|
fn write(&mut self, msg: &[u8]) {
|
||||||
|
self.write(msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(&self) -> u64 {
|
fn finish(&self) -> u64 {
|
||||||
@ -199,6 +222,7 @@ impl Hasher for SipHasher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl Clone for SipHasher {
|
impl Clone for SipHasher {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clone(&self) -> SipHasher {
|
fn clone(&self) -> SipHasher {
|
||||||
@ -216,6 +240,7 @@ impl Clone for SipHasher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl Default for SipHasher {
|
impl Default for SipHasher {
|
||||||
fn default() -> SipHasher {
|
fn default() -> SipHasher {
|
||||||
SipHasher::new()
|
SipHasher::new()
|
||||||
|
@ -50,10 +50,10 @@ pub type GlueFn = extern "Rust" fn(*const i8);
|
|||||||
#[derive(Copy)]
|
#[derive(Copy)]
|
||||||
pub struct TyDesc {
|
pub struct TyDesc {
|
||||||
// sizeof(T)
|
// sizeof(T)
|
||||||
pub size: uint,
|
pub size: usize,
|
||||||
|
|
||||||
// alignof(T)
|
// alignof(T)
|
||||||
pub align: uint,
|
pub align: usize,
|
||||||
|
|
||||||
// Called when a value of type `T` is no longer needed
|
// Called when a value of type `T` is no longer needed
|
||||||
pub drop_glue: GlueFn,
|
pub drop_glue: GlueFn,
|
||||||
@ -186,15 +186,15 @@ extern "rust-intrinsic" {
|
|||||||
/// would *exactly* overwrite a value. When laid out in vectors
|
/// would *exactly* overwrite a value. When laid out in vectors
|
||||||
/// and structures there may be additional padding between
|
/// and structures there may be additional padding between
|
||||||
/// elements.
|
/// elements.
|
||||||
pub fn size_of<T>() -> uint;
|
pub fn size_of<T>() -> usize;
|
||||||
|
|
||||||
/// Move a value to an uninitialized memory location.
|
/// Move a value to an uninitialized memory location.
|
||||||
///
|
///
|
||||||
/// Drop glue is not run on the destination.
|
/// Drop glue is not run on the destination.
|
||||||
pub fn move_val_init<T>(dst: &mut T, src: T);
|
pub fn move_val_init<T>(dst: &mut T, src: T);
|
||||||
|
|
||||||
pub fn min_align_of<T>() -> uint;
|
pub fn min_align_of<T>() -> usize;
|
||||||
pub fn pref_align_of<T>() -> uint;
|
pub fn pref_align_of<T>() -> usize;
|
||||||
|
|
||||||
/// Get a static pointer to a type descriptor.
|
/// Get a static pointer to a type descriptor.
|
||||||
pub fn get_tydesc<T: ?Sized>() -> *const TyDesc;
|
pub fn get_tydesc<T: ?Sized>() -> *const TyDesc;
|
||||||
@ -253,7 +253,7 @@ extern "rust-intrinsic" {
|
|||||||
///
|
///
|
||||||
/// This is implemented as an intrinsic to avoid converting to and from an
|
/// This is implemented as an intrinsic to avoid converting to and from an
|
||||||
/// integer, since the conversion would throw away aliasing information.
|
/// integer, since the conversion would throw away aliasing information.
|
||||||
pub fn offset<T>(dst: *const T, offset: int) -> *const T;
|
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
|
||||||
|
|
||||||
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
|
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
|
||||||
/// and destination may *not* overlap.
|
/// and destination may *not* overlap.
|
||||||
@ -294,7 +294,7 @@ extern "rust-intrinsic" {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[unstable(feature = "core")]
|
#[unstable(feature = "core")]
|
||||||
pub fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: uint);
|
pub fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
|
||||||
|
|
||||||
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
|
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
|
||||||
/// and destination may overlap.
|
/// and destination may overlap.
|
||||||
@ -324,13 +324,13 @@ extern "rust-intrinsic" {
|
|||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
#[unstable(feature = "core")]
|
#[unstable(feature = "core")]
|
||||||
pub fn copy_memory<T>(dst: *mut T, src: *const T, count: uint);
|
pub fn copy_memory<T>(dst: *mut T, src: *const T, count: usize);
|
||||||
|
|
||||||
/// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
|
/// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
|
||||||
/// bytes of memory starting at `dst` to `c`.
|
/// bytes of memory starting at `dst` to `c`.
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "uncertain about naming and semantics")]
|
reason = "uncertain about naming and semantics")]
|
||||||
pub fn set_memory<T>(dst: *mut T, val: u8, count: uint);
|
pub fn set_memory<T>(dst: *mut T, val: u8, count: usize);
|
||||||
|
|
||||||
/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
|
/// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
|
||||||
/// a size of `count` * `size_of::<T>()` and an alignment of
|
/// a size of `count` * `size_of::<T>()` and an alignment of
|
||||||
@ -338,19 +338,19 @@ extern "rust-intrinsic" {
|
|||||||
///
|
///
|
||||||
/// The volatile parameter parameter is set to `true`, so it will not be optimized out.
|
/// The volatile parameter parameter is set to `true`, so it will not be optimized out.
|
||||||
pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
|
pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
|
||||||
count: uint);
|
count: usize);
|
||||||
/// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with
|
/// Equivalent to the appropriate `llvm.memmove.p0i8.0i8.*` intrinsic, with
|
||||||
/// a size of `count` * `size_of::<T>()` and an alignment of
|
/// a size of `count` * `size_of::<T>()` and an alignment of
|
||||||
/// `min_align_of::<T>()`
|
/// `min_align_of::<T>()`
|
||||||
///
|
///
|
||||||
/// The volatile parameter parameter is set to `true`, so it will not be optimized out.
|
/// The volatile parameter parameter is set to `true`, so it will not be optimized out.
|
||||||
pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: uint);
|
pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize);
|
||||||
/// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
|
/// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a
|
||||||
/// size of `count` * `size_of::<T>()` and an alignment of
|
/// size of `count` * `size_of::<T>()` and an alignment of
|
||||||
/// `min_align_of::<T>()`.
|
/// `min_align_of::<T>()`.
|
||||||
///
|
///
|
||||||
/// The volatile parameter parameter is set to `true`, so it will not be optimized out.
|
/// The volatile parameter parameter is set to `true`, so it will not be optimized out.
|
||||||
pub fn volatile_set_memory<T>(dst: *mut T, val: u8, count: uint);
|
pub fn volatile_set_memory<T>(dst: *mut T, val: u8, count: usize);
|
||||||
|
|
||||||
/// Perform a volatile load from the `src` pointer.
|
/// Perform a volatile load from the `src` pointer.
|
||||||
pub fn volatile_load<T>(src: *const T) -> T;
|
pub fn volatile_load<T>(src: *const T) -> T;
|
||||||
|
@ -62,6 +62,7 @@ use clone::Clone;
|
|||||||
use cmp;
|
use cmp;
|
||||||
use cmp::Ord;
|
use cmp::Ord;
|
||||||
use default::Default;
|
use default::Default;
|
||||||
|
use marker;
|
||||||
use mem;
|
use mem;
|
||||||
use num::{ToPrimitive, Int};
|
use num::{ToPrimitive, Int};
|
||||||
use ops::{Add, Deref, FnMut};
|
use ops::{Add, Deref, FnMut};
|
||||||
@ -113,9 +114,9 @@ impl<'a, I: Iterator + ?Sized> Iterator for &'a mut I {
|
|||||||
#[rustc_on_unimplemented="a collection of type `{Self}` cannot be \
|
#[rustc_on_unimplemented="a collection of type `{Self}` cannot be \
|
||||||
built from an iterator over elements of type `{A}`"]
|
built from an iterator over elements of type `{A}`"]
|
||||||
pub trait FromIterator<A> {
|
pub trait FromIterator<A> {
|
||||||
/// Build a container with elements from an external iterator.
|
/// Build a container with elements from something iterable.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
|
fn from_iter<T: IntoIterator<Item=A>>(iterator: T) -> Self;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Conversion into an `Iterator`
|
/// Conversion into an `Iterator`
|
||||||
@ -147,7 +148,7 @@ impl<I: Iterator> IntoIterator for I {
|
|||||||
pub trait Extend<A> {
|
pub trait Extend<A> {
|
||||||
/// Extend a container with the elements yielded by an arbitrary iterator
|
/// Extend a container with the elements yielded by an arbitrary iterator
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn extend<T: Iterator<Item=A>>(&mut self, iterator: T);
|
fn extend<T: IntoIterator<Item=A>>(&mut self, iterable: T);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An extension trait providing numerous methods applicable to all iterators.
|
/// An extension trait providing numerous methods applicable to all iterators.
|
||||||
@ -332,7 +333,7 @@ pub trait IteratorExt: Iterator + Sized {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let xs = [100, 200, 300];
|
/// 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.peek().unwrap(), 100);
|
||||||
/// assert_eq!(it.next().unwrap(), 100);
|
/// assert_eq!(it.next().unwrap(), 100);
|
||||||
/// assert_eq!(it.next().unwrap(), 200);
|
/// assert_eq!(it.next().unwrap(), 200);
|
||||||
@ -522,11 +523,11 @@ pub trait IteratorExt: Iterator + Sized {
|
|||||||
///
|
///
|
||||||
/// let a = [1, 4, 2, 3, 8, 9, 6];
|
/// let a = [1, 4, 2, 3, 8, 9, 6];
|
||||||
/// let sum = a.iter()
|
/// let sum = a.iter()
|
||||||
/// .map(|&x| x)
|
/// .map(|x| *x)
|
||||||
/// .inspect(|&x| println!("filtering {}", x))
|
/// .inspect(|&x| println!("filtering {}", x))
|
||||||
/// .filter(|&x| x % 2 == 0)
|
/// .filter(|&x| x % 2 == 0)
|
||||||
/// .inspect(|&x| println!("{} made it through", x))
|
/// .inspect(|&x| println!("{} made it through", x))
|
||||||
/// .sum();
|
/// .sum();
|
||||||
/// println!("{}", sum);
|
/// println!("{}", sum);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -561,7 +562,7 @@ pub trait IteratorExt: Iterator + Sized {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let a = [1, 2, 3, 4, 5];
|
/// 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);
|
/// assert_eq!(a, b);
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -937,7 +938,7 @@ pub trait IteratorExt: Iterator + Sized {
|
|||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// let a = [(1, 2), (3, 4)];
|
/// 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!([1, 3], left);
|
||||||
/// assert_eq!([2, 4], right);
|
/// assert_eq!([2, 4], right);
|
||||||
/// ```
|
/// ```
|
||||||
@ -947,7 +948,7 @@ pub trait IteratorExt: Iterator + Sized {
|
|||||||
FromB: Default + Extend<B>,
|
FromB: Default + Extend<B>,
|
||||||
Self: Iterator<Item=(A, B)>,
|
Self: Iterator<Item=(A, B)>,
|
||||||
{
|
{
|
||||||
struct SizeHint<A>(usize, Option<usize>);
|
struct SizeHint<A>(usize, Option<usize>, marker::PhantomData<A>);
|
||||||
impl<A> Iterator for SizeHint<A> {
|
impl<A> Iterator for SizeHint<A> {
|
||||||
type Item = A;
|
type Item = A;
|
||||||
|
|
||||||
@ -961,8 +962,8 @@ pub trait IteratorExt: Iterator + Sized {
|
|||||||
let mut ts: FromA = Default::default();
|
let mut ts: FromA = Default::default();
|
||||||
let mut us: FromB = Default::default();
|
let mut us: FromB = Default::default();
|
||||||
|
|
||||||
ts.extend(SizeHint(lo, hi));
|
ts.extend(SizeHint(lo, hi, marker::PhantomData));
|
||||||
us.extend(SizeHint(lo, hi));
|
us.extend(SizeHint(lo, hi, marker::PhantomData));
|
||||||
|
|
||||||
for (t, u) in self {
|
for (t, u) in self {
|
||||||
ts.extend(Some(t).into_iter());
|
ts.extend(Some(t).into_iter());
|
||||||
@ -1142,7 +1143,7 @@ pub trait AdditiveIterator<A> {
|
|||||||
/// use std::iter::AdditiveIterator;
|
/// use std::iter::AdditiveIterator;
|
||||||
///
|
///
|
||||||
/// let a = [1i32, 2, 3, 4, 5];
|
/// 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);
|
/// assert!(it.sum() == 15);
|
||||||
/// ```
|
/// ```
|
||||||
fn sum(self) -> A;
|
fn sum(self) -> A;
|
||||||
@ -1305,6 +1306,23 @@ impl<T, D, I> ExactSizeIterator for Cloned<I> where
|
|||||||
I: ExactSizeIterator<Item=D>,
|
I: ExactSizeIterator<Item=D>,
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
#[unstable(feature = "core", reason = "trait is experimental")]
|
||||||
|
impl<T, D, I> RandomAccessIterator for Cloned<I> where
|
||||||
|
T: Clone,
|
||||||
|
D: Deref<Target=T>,
|
||||||
|
I: RandomAccessIterator<Item=D>
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn indexable(&self) -> usize {
|
||||||
|
self.it.indexable()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn idx(&mut self, index: usize) -> Option<T> {
|
||||||
|
self.it.idx(index).cloned()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// An iterator that repeats endlessly
|
/// An iterator that repeats endlessly
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||||
@ -2047,8 +2065,8 @@ pub struct Scan<I, St, F> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<B, I: Iterator, St, F> Iterator for Scan<I, St, F> where
|
impl<A, B, I: Iterator<Item=A>, St, F> Iterator for Scan<I, St, F> where
|
||||||
F: FnMut(&mut St, I::Item) -> Option<B>,
|
F: FnMut(&mut St, A) -> Option<B>,
|
||||||
{
|
{
|
||||||
type Item = B;
|
type Item = B;
|
||||||
|
|
||||||
|
@ -126,7 +126,6 @@ pub mod default;
|
|||||||
|
|
||||||
pub mod any;
|
pub mod any;
|
||||||
pub mod atomic;
|
pub mod atomic;
|
||||||
pub mod borrow;
|
|
||||||
pub mod cell;
|
pub mod cell;
|
||||||
pub mod char;
|
pub mod char;
|
||||||
pub mod panicking;
|
pub mod panicking;
|
||||||
|
@ -26,6 +26,10 @@
|
|||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
|
use cmp;
|
||||||
|
use option::Option;
|
||||||
|
use hash::Hash;
|
||||||
|
use hash::Hasher;
|
||||||
|
|
||||||
/// Types able to be transferred across thread boundaries.
|
/// Types able to be transferred across thread boundaries.
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
@ -37,12 +41,11 @@ pub unsafe trait Send: 'static {
|
|||||||
// empty.
|
// empty.
|
||||||
}
|
}
|
||||||
/// Types able to be transferred across thread boundaries.
|
/// Types able to be transferred across thread boundaries.
|
||||||
#[unstable(feature = "core",
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
reason = "will be overhauled with new lifetime rules; see RFC 458")]
|
|
||||||
#[lang="send"]
|
#[lang="send"]
|
||||||
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
|
||||||
#[cfg(not(stage0))]
|
#[cfg(not(stage0))]
|
||||||
pub unsafe trait Send {
|
pub unsafe trait Send : MarkerTrait {
|
||||||
// empty.
|
// empty.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,7 +53,7 @@ pub unsafe trait Send {
|
|||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[lang="sized"]
|
#[lang="sized"]
|
||||||
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
|
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
|
||||||
pub trait Sized {
|
pub trait Sized : MarkerTrait {
|
||||||
// Empty.
|
// Empty.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,7 +158,7 @@ pub trait Sized {
|
|||||||
/// change: that second example would fail to compile if we made `Foo` non-`Copy`.
|
/// change: that second example would fail to compile if we made `Foo` non-`Copy`.
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[lang="copy"]
|
#[lang="copy"]
|
||||||
pub trait Copy {
|
pub trait Copy : MarkerTrait {
|
||||||
// Empty.
|
// Empty.
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,220 +207,13 @@ pub trait Copy {
|
|||||||
/// around the value(s) which can be mutated when behind a `&`
|
/// around the value(s) which can be mutated when behind a `&`
|
||||||
/// reference; not doing this is undefined behaviour (for example,
|
/// reference; not doing this is undefined behaviour (for example,
|
||||||
/// `transmute`-ing from `&T` to `&mut T` is illegal).
|
/// `transmute`-ing from `&T` to `&mut T` is illegal).
|
||||||
#[unstable(feature = "core",
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
reason = "will be overhauled with new lifetime rules; see RFC 458")]
|
|
||||||
#[lang="sync"]
|
#[lang="sync"]
|
||||||
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
|
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
|
||||||
pub unsafe trait Sync {
|
pub unsafe trait Sync : MarkerTrait {
|
||||||
// Empty
|
// 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.
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "Newly added to deal with scoping and destructor changes")]
|
|
||||||
#[lang="phantom_data"]
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct PhantomData<T: ?Sized>;
|
|
||||||
|
|
||||||
impl<T: ?Sized> Copy for PhantomData<T> {}
|
|
||||||
impl<T: ?Sized> Clone for PhantomData<T> {
|
|
||||||
fn clone(&self) -> PhantomData<T> { *self }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A marker type whose type parameter `T` is considered to be
|
|
||||||
/// covariant with respect to the type itself. This is (typically)
|
|
||||||
/// used to indicate that an instance of the type `T` is being stored
|
|
||||||
/// into memory and read from, even though that may not be apparent.
|
|
||||||
///
|
|
||||||
/// For more information about variance, refer to this Wikipedia
|
|
||||||
/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
|
|
||||||
///
|
|
||||||
/// *Note:* It is very unusual to have to add a covariant constraint.
|
|
||||||
/// If you are not sure, you probably want to use `InvariantType`.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// Given a struct `S` that includes a type parameter `T`
|
|
||||||
/// but does not actually *reference* that type parameter:
|
|
||||||
///
|
|
||||||
/// ```ignore
|
|
||||||
/// use std::mem;
|
|
||||||
///
|
|
||||||
/// struct S<T> { x: *() }
|
|
||||||
/// fn get<T>(s: &S<T>) -> T {
|
|
||||||
/// unsafe {
|
|
||||||
/// let x: *T = mem::transmute(s.x);
|
|
||||||
/// *x
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// The type system would currently infer that the value of
|
|
||||||
/// the type parameter `T` is irrelevant, and hence a `S<int>` is
|
|
||||||
/// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
|
|
||||||
/// any `U`). But this is incorrect because `get()` converts the
|
|
||||||
/// `*()` into a `*T` and reads from it. Therefore, we should include the
|
|
||||||
/// a marker field `CovariantType<T>` to inform the type checker that
|
|
||||||
/// `S<T>` is a subtype of `S<U>` if `T` is a subtype of `U`
|
|
||||||
/// (for example, `S<&'static int>` is a subtype of `S<&'a int>`
|
|
||||||
/// for some lifetime `'a`, but not the other way around).
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "likely to change with new variance strategy")]
|
|
||||||
#[lang="covariant_type"]
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct CovariantType<T: ?Sized>;
|
|
||||||
|
|
||||||
impl<T: ?Sized> Copy for CovariantType<T> {}
|
|
||||||
impl<T: ?Sized> Clone for CovariantType<T> {
|
|
||||||
fn clone(&self) -> CovariantType<T> { *self }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A marker type whose type parameter `T` is considered to be
|
|
||||||
/// contravariant with respect to the type itself. This is (typically)
|
|
||||||
/// used to indicate that an instance of the type `T` will be consumed
|
|
||||||
/// (but not read from), even though that may not be apparent.
|
|
||||||
///
|
|
||||||
/// For more information about variance, refer to this Wikipedia
|
|
||||||
/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
|
|
||||||
///
|
|
||||||
/// *Note:* It is very unusual to have to add a contravariant constraint.
|
|
||||||
/// If you are not sure, you probably want to use `InvariantType`.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// Given a struct `S` that includes a type parameter `T`
|
|
||||||
/// but does not actually *reference* that type parameter:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// use std::mem;
|
|
||||||
///
|
|
||||||
/// struct S<T> { x: *const () }
|
|
||||||
/// fn get<T>(s: &S<T>, v: T) {
|
|
||||||
/// unsafe {
|
|
||||||
/// let x: fn(T) = mem::transmute(s.x);
|
|
||||||
/// x(v)
|
|
||||||
/// }
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// The type system would currently infer that the value of
|
|
||||||
/// the type parameter `T` is irrelevant, and hence a `S<int>` is
|
|
||||||
/// a subtype of `S<Box<int>>` (or, for that matter, `S<U>` for
|
|
||||||
/// any `U`). But this is incorrect because `get()` converts the
|
|
||||||
/// `*()` into a `fn(T)` and then passes a value of type `T` to it.
|
|
||||||
///
|
|
||||||
/// Supplying a `ContravariantType` marker would correct the
|
|
||||||
/// problem, because it would mark `S` so that `S<T>` is only a
|
|
||||||
/// subtype of `S<U>` if `U` is a subtype of `T`; given that the
|
|
||||||
/// function requires arguments of type `T`, it must also accept
|
|
||||||
/// arguments of type `U`, hence such a conversion is safe.
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "likely to change with new variance strategy")]
|
|
||||||
#[lang="contravariant_type"]
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct ContravariantType<T: ?Sized>;
|
|
||||||
|
|
||||||
impl<T: ?Sized> Copy for ContravariantType<T> {}
|
|
||||||
impl<T: ?Sized> Clone for ContravariantType<T> {
|
|
||||||
fn clone(&self) -> ContravariantType<T> { *self }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A marker type whose type parameter `T` is considered to be
|
|
||||||
/// invariant with respect to the type itself. This is (typically)
|
|
||||||
/// used to indicate that instances of the type `T` may be read or
|
|
||||||
/// written, even though that may not be apparent.
|
|
||||||
///
|
|
||||||
/// For more information about variance, refer to this Wikipedia
|
|
||||||
/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
|
|
||||||
///
|
|
||||||
/// # Example
|
|
||||||
///
|
|
||||||
/// The Cell type is an example of an `InvariantType` which uses unsafe
|
|
||||||
/// code to achieve "interior" mutability:
|
|
||||||
///
|
|
||||||
/// ```
|
|
||||||
/// struct Cell<T> { value: T }
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// The type system would infer that `value` is only read here
|
|
||||||
/// and never written, but in fact `Cell` uses unsafe code to achieve
|
|
||||||
/// interior mutability. In order to get correct behavior, the
|
|
||||||
/// `InvariantType` marker must be applied.
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "likely to change with new variance strategy")]
|
|
||||||
#[lang="invariant_type"]
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct InvariantType<T: ?Sized>;
|
|
||||||
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "likely to change with new variance strategy")]
|
|
||||||
impl<T: ?Sized> Copy for InvariantType<T> {}
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "likely to change with new variance strategy")]
|
|
||||||
impl<T: ?Sized> Clone for InvariantType<T> {
|
|
||||||
fn clone(&self) -> InvariantType<T> { *self }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// As `CovariantType`, but for lifetime parameters. Using
|
|
||||||
/// `CovariantLifetime<'a>` indicates that it is ok to substitute
|
|
||||||
/// a *longer* lifetime for `'a` than the one you originally
|
|
||||||
/// started with (e.g., you could convert any lifetime `'foo` to
|
|
||||||
/// `'static`). You almost certainly want `ContravariantLifetime`
|
|
||||||
/// instead, or possibly `InvariantLifetime`. The only case where
|
|
||||||
/// it would be appropriate is that you have a (type-casted, and
|
|
||||||
/// hence hidden from the type system) function pointer with a
|
|
||||||
/// signature like `fn(&'a T)` (and no other uses of `'a`). In
|
|
||||||
/// this case, it is ok to substitute a larger lifetime for `'a`
|
|
||||||
/// (e.g., `fn(&'static T)`), because the function is only
|
|
||||||
/// becoming more selective in terms of what it accepts as
|
|
||||||
/// argument.
|
|
||||||
///
|
|
||||||
/// For more information about variance, refer to this Wikipedia
|
|
||||||
/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "likely to change with new variance strategy")]
|
|
||||||
#[lang="covariant_lifetime"]
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct CovariantLifetime<'a>;
|
|
||||||
|
|
||||||
/// As `ContravariantType`, but for lifetime parameters. Using
|
|
||||||
/// `ContravariantLifetime<'a>` indicates that it is ok to
|
|
||||||
/// substitute a *shorter* lifetime for `'a` than the one you
|
|
||||||
/// originally started with (e.g., you could convert `'static` to
|
|
||||||
/// any lifetime `'foo`). This is appropriate for cases where you
|
|
||||||
/// have an unsafe pointer that is actually a pointer into some
|
|
||||||
/// memory with lifetime `'a`, and thus you want to limit the
|
|
||||||
/// lifetime of your data structure to `'a`. An example of where
|
|
||||||
/// this is used is the iterator for vectors.
|
|
||||||
///
|
|
||||||
/// For more information about variance, refer to this Wikipedia
|
|
||||||
/// article <http://en.wikipedia.org/wiki/Variance_%28computer_science%29>.
|
|
||||||
#[unstable(feature = "core",
|
|
||||||
reason = "likely to change with new variance strategy")]
|
|
||||||
#[lang="contravariant_lifetime"]
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
|
||||||
pub struct ContravariantLifetime<'a>;
|
|
||||||
|
|
||||||
/// 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>;
|
|
||||||
|
|
||||||
/// A type which is considered "not POD", meaning that it is not
|
/// A type which is considered "not POD", meaning that it is not
|
||||||
/// implicitly copyable. This is typically embedded in other types to
|
/// implicitly copyable. This is typically embedded in other types to
|
||||||
/// ensure that they are never copied, even if they lack a destructor.
|
/// ensure that they are never copied, even if they lack a destructor.
|
||||||
@ -435,6 +231,156 @@ pub struct NoCopy;
|
|||||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
pub struct Managed;
|
pub struct Managed;
|
||||||
|
|
||||||
|
macro_rules! impls{
|
||||||
|
($t: ident) => (
|
||||||
|
#[cfg(stage0)]
|
||||||
|
impl<T:?Sized, S: Hasher> Hash<S> for $t<T> {
|
||||||
|
#[inline]
|
||||||
|
fn hash(&self, _: &mut S) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
impl<T:?Sized> Hash for $t<T> {
|
||||||
|
#[inline]
|
||||||
|
fn hash<H: Hasher>(&self, _: &mut H) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:?Sized> cmp::PartialEq for $t<T> {
|
||||||
|
fn eq(&self, _other: &$t<T>) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:?Sized> cmp::Eq for $t<T> {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:?Sized> cmp::PartialOrd for $t<T> {
|
||||||
|
fn partial_cmp(&self, _other: &$t<T>) -> Option<cmp::Ordering> {
|
||||||
|
Option::Some(cmp::Ordering::Equal)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:?Sized> cmp::Ord for $t<T> {
|
||||||
|
fn cmp(&self, _other: &$t<T>) -> cmp::Ordering {
|
||||||
|
cmp::Ordering::Equal
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T:?Sized> Copy for $t<T> { }
|
||||||
|
|
||||||
|
impl<T:?Sized> Clone for $t<T> {
|
||||||
|
fn clone(&self) -> $t<T> {
|
||||||
|
$t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// `MarkerTrait` is intended to be used as the supertrait for traits
|
||||||
|
/// that don't have any methods but instead serve just to designate
|
||||||
|
/// categories of types. An example would be the `Send` trait, which
|
||||||
|
/// indicates types that are sendable: `Send` does not itself offer
|
||||||
|
/// any methods, but instead is used to gate access to data.
|
||||||
|
///
|
||||||
|
/// FIXME. Better documentation needed here!
|
||||||
|
pub trait MarkerTrait : PhantomFn<Self> { }
|
||||||
|
impl<T:?Sized> MarkerTrait for T { }
|
||||||
|
|
||||||
|
/// `PhantomFn` is a marker trait for use with traits that contain
|
||||||
|
/// type or lifetime parameters that do not appear in any of their
|
||||||
|
/// methods. In that case, you can either remove those parameters, or
|
||||||
|
/// add a `PhantomFn` supertrait that reflects the signature of
|
||||||
|
/// methods that compiler should "pretend" exists. This most commonly
|
||||||
|
/// occurs for traits with no methods: in that particular case, you
|
||||||
|
/// can extend `MarkerTrait`, which is equivalent to
|
||||||
|
/// `PhantomFn<Self>`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
///
|
||||||
|
/// As an example, consider a trait with no methods like `Even`, meant
|
||||||
|
/// to represent types that are "even":
|
||||||
|
///
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// trait Even { }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// 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:
|
||||||
|
///
|
||||||
|
/// ```rust,ignore
|
||||||
|
/// trait Even {
|
||||||
|
/// fn is_even(self) -> bool { true }
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Therefore, we can model a method like this as follows:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use std::marker::PhantomFn;
|
||||||
|
/// trait Even : PhantomFn<Self> { }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Another equivalent, but clearer, option would be to use
|
||||||
|
/// `MarkerTrait`:
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// use std::marker::MarkerTrait;
|
||||||
|
/// trait Even : MarkerTrait { }
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// # Parameters
|
||||||
|
///
|
||||||
|
/// - `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.
|
||||||
|
///
|
||||||
|
/// # Additional reading
|
||||||
|
///
|
||||||
|
/// More details and background can be found in [RFC 738][738].
|
||||||
|
///
|
||||||
|
/// [738]: https://github.com/rust-lang/rfcs/blob/master/text/0738-variance.md
|
||||||
|
#[lang="phantom_fn"]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub trait PhantomFn<A:?Sized,R:?Sized=()> { }
|
||||||
|
|
||||||
|
#[cfg(stage0)] // built into the trait matching system after stage0
|
||||||
|
impl<A:?Sized, R:?Sized, U:?Sized> PhantomFn<A,R> for U { }
|
||||||
|
|
||||||
|
/// Specific to stage0. You should not be seeing these docs!
|
||||||
|
#[cfg(stage0)]
|
||||||
|
#[lang="covariant_type"] // only relevant to stage0
|
||||||
|
pub struct PhantomData<T:?Sized>;
|
||||||
|
|
||||||
|
/// `PhantomData` is a way to tell the compiler about fake fields.
|
||||||
|
/// Phantom data is required whenever type parameters are not used.
|
||||||
|
/// The idea is that if the compiler encounters a `PhantomData<T>`
|
||||||
|
/// instance, it will behave *as if* an instance of the type `T` were
|
||||||
|
/// present for the purpose of various automatic analyses.
|
||||||
|
///
|
||||||
|
/// For example, embedding a `PhantomData<T>` will inform the compiler
|
||||||
|
/// that one or more instances of the type `T` could be dropped when
|
||||||
|
/// instances of the type itself is dropped, though that may not be
|
||||||
|
/// apparent from the other structure of the type itself. This is
|
||||||
|
/// commonly necessary if the structure is using an unsafe pointer
|
||||||
|
/// like `*mut T` whose referent may be dropped when the type is
|
||||||
|
/// dropped, as a `*mut T` is otherwise not treated as owned.
|
||||||
|
///
|
||||||
|
/// FIXME. Better documentation and examples of common patterns needed
|
||||||
|
/// here! For now, please see [RFC 738][738] for more information.
|
||||||
|
///
|
||||||
|
/// [738]: https://github.com/rust-lang/rfcs/blob/master/text/0738-variance.md
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
#[lang="phantom_data"]
|
||||||
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
pub struct PhantomData<T:?Sized>;
|
||||||
|
|
||||||
|
impls! { PhantomData }
|
||||||
|
|
||||||
#[cfg(not(stage0))]
|
#[cfg(not(stage0))]
|
||||||
mod impls {
|
mod impls {
|
||||||
use super::{Send, Sync, Sized};
|
use super::{Send, Sync, Sized};
|
||||||
@ -442,3 +388,40 @@ mod impls {
|
|||||||
unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {}
|
unsafe impl<'a, T: Sync + ?Sized> Send for &'a T {}
|
||||||
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
|
unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Old-style marker trait. Deprecated.
|
||||||
|
#[unstable(feature = "core", reason = "deprecated")]
|
||||||
|
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<&'a ()>`")]
|
||||||
|
#[lang="contravariant_lifetime"]
|
||||||
|
pub struct ContravariantLifetime<'a>;
|
||||||
|
|
||||||
|
/// Old-style marker trait. Deprecated.
|
||||||
|
#[unstable(feature = "core", reason = "deprecated")]
|
||||||
|
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<fn(&'a ())>`")]
|
||||||
|
#[lang="covariant_lifetime"]
|
||||||
|
pub struct CovariantLifetime<'a>;
|
||||||
|
|
||||||
|
/// Old-style marker trait. Deprecated.
|
||||||
|
#[unstable(feature = "core", reason = "deprecated")]
|
||||||
|
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<Cell<&'a ()>>`")]
|
||||||
|
#[lang="invariant_lifetime"]
|
||||||
|
pub struct InvariantLifetime<'a>;
|
||||||
|
|
||||||
|
/// Old-style marker trait. Deprecated.
|
||||||
|
#[unstable(feature = "core", reason = "deprecated")]
|
||||||
|
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<fn(T)>`")]
|
||||||
|
#[lang="contravariant_type"]
|
||||||
|
pub struct ContravariantType<T>;
|
||||||
|
|
||||||
|
/// Old-style marker trait. Deprecated.
|
||||||
|
#[unstable(feature = "core", reason = "deprecated")]
|
||||||
|
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<T>`")]
|
||||||
|
#[lang="covariant_type"]
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
pub struct CovariantType<T>;
|
||||||
|
|
||||||
|
/// Old-style marker trait. Deprecated.
|
||||||
|
#[unstable(feature = "core", reason = "deprecated")]
|
||||||
|
#[deprecated(since = "1.0.0", reason = "Replace with `PhantomData<Cell<T>>`")]
|
||||||
|
#[lang="invariant_type"]
|
||||||
|
pub struct InvariantType<T>;
|
||||||
|
@ -10,15 +10,14 @@
|
|||||||
|
|
||||||
//! Exposes the NonZero lang item which provides optimization hints.
|
//! Exposes the NonZero lang item which provides optimization hints.
|
||||||
|
|
||||||
|
use marker::{Sized, MarkerTrait};
|
||||||
use ops::Deref;
|
use ops::Deref;
|
||||||
use ptr::Unique;
|
|
||||||
|
|
||||||
/// Unsafe trait to indicate what types are usable with the NonZero struct
|
/// Unsafe trait to indicate what types are usable with the NonZero struct
|
||||||
pub unsafe trait Zeroable {}
|
pub unsafe trait Zeroable : MarkerTrait {}
|
||||||
|
|
||||||
unsafe impl<T> Zeroable for *const T {}
|
unsafe impl<T:?Sized> Zeroable for *const T {}
|
||||||
unsafe impl<T> Zeroable for *mut T {}
|
unsafe impl<T:?Sized> Zeroable for *mut T {}
|
||||||
unsafe impl<T> Zeroable for Unique<T> { }
|
|
||||||
unsafe impl Zeroable for isize {}
|
unsafe impl Zeroable for isize {}
|
||||||
unsafe impl Zeroable for usize {}
|
unsafe impl Zeroable for usize {}
|
||||||
unsafe impl Zeroable for i8 {}
|
unsafe impl Zeroable for i8 {}
|
||||||
|
@ -149,7 +149,7 @@ use clone::Clone;
|
|||||||
use cmp::{Eq, Ord};
|
use cmp::{Eq, Ord};
|
||||||
use default::Default;
|
use default::Default;
|
||||||
use iter::{ExactSizeIterator};
|
use iter::{ExactSizeIterator};
|
||||||
use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator};
|
use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, IntoIterator};
|
||||||
use mem;
|
use mem;
|
||||||
use ops::{Deref, FnOnce};
|
use ops::{Deref, FnOnce};
|
||||||
use result::Result::{Ok, Err};
|
use result::Result::{Ok, Err};
|
||||||
@ -909,7 +909,7 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
|
|||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
fn from_iter<I: Iterator<Item=Option<A>>>(iter: I) -> Option<V> {
|
fn from_iter<I: IntoIterator<Item=Option<A>>>(iter: I) -> Option<V> {
|
||||||
// FIXME(#11084): This could be replaced with Iterator::scan when this
|
// FIXME(#11084): This could be replaced with Iterator::scan when this
|
||||||
// performance bug is closed.
|
// performance bug is closed.
|
||||||
|
|
||||||
@ -934,7 +934,7 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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());
|
let v: V = FromIterator::from_iter(adapter.by_ref());
|
||||||
|
|
||||||
if adapter.found_none {
|
if adapter.found_none {
|
||||||
|
@ -91,8 +91,10 @@
|
|||||||
use mem;
|
use mem;
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use intrinsics;
|
use intrinsics;
|
||||||
|
use ops::Deref;
|
||||||
use option::Option::{self, Some, None};
|
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::{PartialEq, Eq, Ord, PartialOrd};
|
||||||
use cmp::Ordering::{self, Less, Equal, Greater};
|
use cmp::Ordering::{self, Less, Equal, Greater};
|
||||||
@ -303,7 +305,7 @@ impl<T> PtrExt for *const T {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@ -330,7 +332,7 @@ impl<T> PtrExt for *mut T {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[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]
|
#[inline]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
@ -517,15 +519,16 @@ impl<T> PartialOrd for *mut T {
|
|||||||
|
|
||||||
/// A wrapper around a raw `*mut T` that indicates that the possessor
|
/// A wrapper around a raw `*mut T` that indicates that the possessor
|
||||||
/// of this wrapper owns the referent. This in turn implies that the
|
/// of this wrapper owns the referent. This in turn implies that the
|
||||||
/// `Unique<T>` is `Send`/`Sync` if `T` is `Send`/`Sync`, unlike a
|
/// `Unique<T>` is `Send`/`Sync` if `T` is `Send`/`Sync`, unlike a raw
|
||||||
/// raw `*mut T` (which conveys no particular ownership semantics).
|
/// `*mut T` (which conveys no particular ownership semantics). It
|
||||||
/// Useful for building abstractions like `Vec<T>` or `Box<T>`, which
|
/// also implies that the referent of the pointer should not be
|
||||||
|
/// modified without a unique path to the `Unique` reference. Useful
|
||||||
|
/// for building abstractions like `Vec<T>` or `Box<T>`, which
|
||||||
/// internally use raw pointers to manage the memory that they own.
|
/// internally use raw pointers to manage the memory that they own.
|
||||||
#[unstable(feature = "core", reason = "recently added to this module")]
|
#[unstable(feature = "core", reason = "recently added to this module")]
|
||||||
pub struct Unique<T: ?Sized> {
|
pub struct Unique<T:?Sized> {
|
||||||
/// The wrapped `*mut T`.
|
pointer: NonZero<*const T>,
|
||||||
pub ptr: *mut T,
|
_marker: PhantomData<T>,
|
||||||
_own: marker::PhantomData<T>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// `Unique` pointers are `Send` if `T` is `Send` because the data they
|
/// `Unique` pointers are `Send` if `T` is `Send` because the data they
|
||||||
@ -542,25 +545,34 @@ unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
|
|||||||
#[unstable(feature = "core", reason = "recently added to this module")]
|
#[unstable(feature = "core", reason = "recently added to this module")]
|
||||||
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
|
unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
|
||||||
|
|
||||||
impl<T> Unique<T> {
|
impl<T:?Sized> Unique<T> {
|
||||||
/// Returns a null Unique.
|
/// Create a new `Unique`.
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "recently added to this module")]
|
reason = "recently added to this module")]
|
||||||
pub fn null() -> Unique<T> {
|
pub unsafe fn new(ptr: *mut T) -> Unique<T> {
|
||||||
Unique(null_mut())
|
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",
|
#[unstable(feature = "core",
|
||||||
reason = "recently added to this module")]
|
reason = "recently added to this module")]
|
||||||
pub unsafe fn offset(self, offset: isize) -> *mut T {
|
pub unsafe fn get(&self) -> &T {
|
||||||
self.ptr.offset(offset)
|
&**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
|
impl<T:?Sized> Deref for Unique<T> {
|
||||||
/// data referenced by `ptr`.
|
type Target = *mut T;
|
||||||
#[allow(non_snake_case)]
|
|
||||||
pub fn Unique<T: ?Sized>(ptr: *mut T) -> Unique<T> {
|
#[inline]
|
||||||
Unique { ptr: ptr, _own: marker::PhantomData }
|
fn deref<'a>(&'a self) -> &'a *mut T {
|
||||||
|
unsafe { mem::transmute(&*self.pointer) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -230,7 +230,8 @@ use self::Result::{Ok, Err};
|
|||||||
|
|
||||||
use clone::Clone;
|
use clone::Clone;
|
||||||
use fmt;
|
use fmt;
|
||||||
use iter::{Iterator, IteratorExt, DoubleEndedIterator, FromIterator, ExactSizeIterator};
|
use iter::{Iterator, IteratorExt, DoubleEndedIterator,
|
||||||
|
FromIterator, ExactSizeIterator, IntoIterator};
|
||||||
use ops::{FnMut, FnOnce};
|
use ops::{FnMut, FnOnce};
|
||||||
use option::Option::{self, None, Some};
|
use option::Option::{self, None, Some};
|
||||||
use slice::AsSlice;
|
use slice::AsSlice;
|
||||||
@ -906,7 +907,7 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
|
|||||||
/// assert!(res == Ok(vec!(2, 3)));
|
/// assert!(res == Ok(vec!(2, 3)));
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_iter<I: Iterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
|
fn from_iter<I: IntoIterator<Item=Result<A, E>>>(iter: I) -> Result<V, E> {
|
||||||
// FIXME(#11084): This could be replaced with Iterator::scan when this
|
// FIXME(#11084): This could be replaced with Iterator::scan when this
|
||||||
// performance bug is closed.
|
// performance bug is closed.
|
||||||
|
|
||||||
@ -931,7 +932,7 @@ impl<A, E, V: FromIterator<A>> FromIterator<Result<A, E>> for Result<V, E> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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());
|
let v: V = FromIterator::from_iter(adapter.by_ref());
|
||||||
|
|
||||||
match adapter.err {
|
match adapter.err {
|
||||||
|
@ -140,11 +140,11 @@ impl<T> SliceExt for [T] {
|
|||||||
if mem::size_of::<T>() == 0 {
|
if mem::size_of::<T>() == 0 {
|
||||||
Iter {ptr: p,
|
Iter {ptr: p,
|
||||||
end: (p as usize + self.len()) as *const T,
|
end: (p as usize + self.len()) as *const T,
|
||||||
marker: marker::ContravariantLifetime::<'a>}
|
_marker: marker::PhantomData}
|
||||||
} else {
|
} else {
|
||||||
Iter {ptr: p,
|
Iter {ptr: p,
|
||||||
end: p.offset(self.len() as isize),
|
end: p.offset(self.len() as isize),
|
||||||
marker: marker::ContravariantLifetime::<'a>}
|
_marker: marker::PhantomData}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -279,11 +279,11 @@ impl<T> SliceExt for [T] {
|
|||||||
if mem::size_of::<T>() == 0 {
|
if mem::size_of::<T>() == 0 {
|
||||||
IterMut {ptr: p,
|
IterMut {ptr: p,
|
||||||
end: (p as usize + self.len()) as *mut T,
|
end: (p as usize + self.len()) as *mut T,
|
||||||
marker: marker::ContravariantLifetime::<'a>}
|
_marker: marker::PhantomData}
|
||||||
} else {
|
} else {
|
||||||
IterMut {ptr: p,
|
IterMut {ptr: p,
|
||||||
end: p.offset(self.len() as isize),
|
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> {
|
pub struct Iter<'a, T: 'a> {
|
||||||
ptr: *const T,
|
ptr: *const T,
|
||||||
end: *const T,
|
end: *const T,
|
||||||
marker: marker::ContravariantLifetime<'a>
|
_marker: marker::PhantomData<&'a T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[unstable(feature = "core")]
|
#[unstable(feature = "core")]
|
||||||
@ -790,7 +790,7 @@ impl<'a, T> ExactSizeIterator for Iter<'a, T> {}
|
|||||||
|
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
impl<'a, T> Clone for Iter<'a, T> {
|
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")]
|
#[unstable(feature = "core", reason = "trait is experimental")]
|
||||||
@ -823,7 +823,7 @@ impl<'a, T> RandomAccessIterator for Iter<'a, T> {
|
|||||||
pub struct IterMut<'a, T: 'a> {
|
pub struct IterMut<'a, T: 'a> {
|
||||||
ptr: *mut T,
|
ptr: *mut T,
|
||||||
end: *mut T,
|
end: *mut T,
|
||||||
marker: marker::ContravariantLifetime<'a>,
|
_marker: marker::PhantomData<&'a mut T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1280,7 +1280,7 @@ mod traits {
|
|||||||
/// Any string that can be represented as a slice
|
/// Any string that can be represented as a slice
|
||||||
#[unstable(feature = "core",
|
#[unstable(feature = "core",
|
||||||
reason = "Instead of taking this bound generically, this trait will be \
|
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")]
|
a more generic conversion trait")]
|
||||||
pub trait Str {
|
pub trait Str {
|
||||||
/// Work with `self` as a slice.
|
/// Work with `self` as a slice.
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::hash::{Hash, Hasher, Writer};
|
use std::hash::{Hash, Hasher};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
|
||||||
struct MyHasher {
|
struct MyHasher {
|
||||||
@ -22,25 +22,19 @@ impl Default for MyHasher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Writer for MyHasher {
|
impl Hasher for MyHasher {
|
||||||
// Most things we'll just add up the bytes.
|
|
||||||
fn write(&mut self, buf: &[u8]) {
|
fn write(&mut self, buf: &[u8]) {
|
||||||
for byte in buf {
|
for byte in buf {
|
||||||
self.hash += *byte as u64;
|
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 }
|
fn finish(&self) -> u64 { self.hash }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_writer_hasher() {
|
fn test_writer_hasher() {
|
||||||
fn hash<T: Hash<MyHasher>>(t: &T) -> u64 {
|
fn hash<T: Hash>(t: &T) -> u64 {
|
||||||
::std::hash::hash::<_, MyHasher>(t)
|
::std::hash::hash::<_, MyHasher>(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,9 +84,9 @@ struct Custom { hash: u64 }
|
|||||||
struct CustomHasher { output: u64 }
|
struct CustomHasher { output: u64 }
|
||||||
|
|
||||||
impl Hasher for CustomHasher {
|
impl Hasher for CustomHasher {
|
||||||
type Output = u64;
|
|
||||||
fn reset(&mut self) { self.output = 0; }
|
|
||||||
fn finish(&self) -> u64 { self.output }
|
fn finish(&self) -> u64 { self.output }
|
||||||
|
fn write(&mut self, data: &[u8]) { panic!() }
|
||||||
|
fn write_u64(&mut self, data: u64) { self.output = data; }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for CustomHasher {
|
impl Default for CustomHasher {
|
||||||
@ -101,15 +95,15 @@ impl Default for CustomHasher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hash<CustomHasher> for Custom {
|
impl Hash for Custom {
|
||||||
fn hash(&self, state: &mut CustomHasher) {
|
fn hash<H: Hasher>(&self, state: &mut H) {
|
||||||
state.output = self.hash;
|
state.write_u64(self.hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_custom_state() {
|
fn test_custom_state() {
|
||||||
fn hash<T: Hash<CustomHasher>>(t: &T) -> u64 {
|
fn hash<T: Hash>(t: &T) -> u64 {
|
||||||
::std::hash::hash::<_, CustomHasher>(t)
|
::std::hash::hash::<_, CustomHasher>(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ fn test_iterator_chain() {
|
|||||||
assert_eq!(i, expected.len());
|
assert_eq!(i, expected.len());
|
||||||
|
|
||||||
let ys = count(30, 10).take(4);
|
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;
|
let mut i = 0;
|
||||||
for x in it {
|
for x in it {
|
||||||
assert_eq!(x, expected[i]);
|
assert_eq!(x, expected[i]);
|
||||||
@ -119,7 +119,7 @@ fn test_iterator_enumerate() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_iterator_peekable() {
|
fn test_iterator_peekable() {
|
||||||
let xs = vec![0, 1, 2, 3, 4, 5];
|
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.len(), 6);
|
||||||
assert_eq!(it.peek().unwrap(), &0);
|
assert_eq!(it.peek().unwrap(), &0);
|
||||||
@ -259,12 +259,12 @@ fn test_inspect() {
|
|||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
|
|
||||||
let ys = xs.iter()
|
let ys = xs.iter()
|
||||||
.map(|&x| x)
|
.cloned()
|
||||||
.inspect(|_| n += 1)
|
.inspect(|_| n += 1)
|
||||||
.collect::<Vec<uint>>();
|
.collect::<Vec<uint>>();
|
||||||
|
|
||||||
assert_eq!(n, xs.len());
|
assert_eq!(n, xs.len());
|
||||||
assert_eq!(&xs[], &ys[]);
|
assert_eq!(&xs[..], &ys[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -329,33 +329,33 @@ fn test_iterator_len() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_iterator_sum() {
|
fn test_iterator_sum() {
|
||||||
let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
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[..4].iter().cloned().sum(), 6);
|
||||||
assert_eq!(v.iter().map(|&x| x).sum(), 55);
|
assert_eq!(v.iter().cloned().sum(), 55);
|
||||||
assert_eq!(v[..0].iter().map(|&x| x).sum(), 0);
|
assert_eq!(v[..0].iter().cloned().sum(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iterator_product() {
|
fn test_iterator_product() {
|
||||||
let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
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[..4].iter().cloned().product(), 0);
|
||||||
assert_eq!(v[1..5].iter().map(|&x| x).product(), 24);
|
assert_eq!(v[1..5].iter().cloned().product(), 24);
|
||||||
assert_eq!(v[..0].iter().map(|&x| x).product(), 1);
|
assert_eq!(v[..0].iter().cloned().product(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iterator_max() {
|
fn test_iterator_max() {
|
||||||
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
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[..4].iter().cloned().max(), Some(3));
|
||||||
assert_eq!(v.iter().map(|&x| x).max(), Some(10));
|
assert_eq!(v.iter().cloned().max(), Some(10));
|
||||||
assert_eq!(v[..0].iter().map(|&x| x).max(), None);
|
assert_eq!(v[..0].iter().cloned().max(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_iterator_min() {
|
fn test_iterator_min() {
|
||||||
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
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[..4].iter().cloned().min(), Some(0));
|
||||||
assert_eq!(v.iter().map(|&x| x).min(), Some(0));
|
assert_eq!(v.iter().cloned().min(), Some(0));
|
||||||
assert_eq!(v[..0].iter().map(|&x| x).min(), None);
|
assert_eq!(v[..0].iter().cloned().min(), None);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[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().take_while(|_| false).size_hint(), (0, None));
|
||||||
assert_eq!(c.clone().skip_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().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().zip(vi.clone()).size_hint(), (10, Some(10)));
|
||||||
assert_eq!(c.clone().scan(0, |_,_| Some(0)).size_hint(), (0, None));
|
assert_eq!(c.clone().scan(0, |_,_| Some(0)).size_hint(), (0, None));
|
||||||
assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None));
|
assert_eq!(c.clone().filter(|_| false).size_hint(), (0, None));
|
||||||
@ -398,7 +398,7 @@ fn test_iterator_size_hint() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_collect() {
|
fn test_collect() {
|
||||||
let a = vec![1, 2, 3, 4, 5];
|
let a = vec![1, 2, 3, 4, 5];
|
||||||
let b: Vec<int> = a.iter().map(|&x| x).collect();
|
let b: Vec<int> = a.iter().cloned().collect();
|
||||||
assert!(a == b);
|
assert!(a == b);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,7 +471,7 @@ fn test_rev() {
|
|||||||
let mut it = xs.iter();
|
let mut it = xs.iter();
|
||||||
it.next();
|
it.next();
|
||||||
it.next();
|
it.next();
|
||||||
assert!(it.rev().map(|&x| x).collect::<Vec<int>>() ==
|
assert!(it.rev().cloned().collect::<Vec<int>>() ==
|
||||||
vec![16, 14, 12, 10, 8, 6]);
|
vec![16, 14, 12, 10, 8, 6]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -508,7 +508,7 @@ fn test_double_ended_map() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_double_ended_enumerate() {
|
fn test_double_ended_enumerate() {
|
||||||
let xs = [1, 2, 3, 4, 5, 6];
|
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((0, 1)));
|
||||||
assert_eq!(it.next(), Some((1, 2)));
|
assert_eq!(it.next(), Some((1, 2)));
|
||||||
assert_eq!(it.next_back(), Some((5, 6)));
|
assert_eq!(it.next_back(), Some((5, 6)));
|
||||||
@ -522,8 +522,8 @@ fn test_double_ended_enumerate() {
|
|||||||
fn test_double_ended_zip() {
|
fn test_double_ended_zip() {
|
||||||
let xs = [1, 2, 3, 4, 5, 6];
|
let xs = [1, 2, 3, 4, 5, 6];
|
||||||
let ys = [1, 2, 3, 7];
|
let ys = [1, 2, 3, 7];
|
||||||
let a = xs.iter().map(|&x| x);
|
let a = xs.iter().cloned();
|
||||||
let b = ys.iter().map(|&x| x);
|
let b = ys.iter().cloned();
|
||||||
let mut it = a.zip(b);
|
let mut it = a.zip(b);
|
||||||
assert_eq!(it.next(), Some((1, 1)));
|
assert_eq!(it.next(), Some((1, 1)));
|
||||||
assert_eq!(it.next(), Some((2, 2)));
|
assert_eq!(it.next(), Some((2, 2)));
|
||||||
@ -713,7 +713,7 @@ fn test_random_access_inspect() {
|
|||||||
fn test_random_access_map() {
|
fn test_random_access_map() {
|
||||||
let xs = [1, 2, 3, 4, 5];
|
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());
|
assert_eq!(xs.len(), it.indexable());
|
||||||
for (i, elt) in xs.iter().enumerate() {
|
for (i, elt) in xs.iter().enumerate() {
|
||||||
assert_eq!(Some(*elt), it.idx(i));
|
assert_eq!(Some(*elt), it.idx(i));
|
||||||
|
@ -92,7 +92,7 @@ fn test_transmute_copy() {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_transmute() {
|
fn test_transmute() {
|
||||||
trait Foo {}
|
trait Foo { fn dummy(&self) { } }
|
||||||
impl Foo for int {}
|
impl Foo for int {}
|
||||||
|
|
||||||
let a = box 100 as Box<Foo>;
|
let a = box 100 as Box<Foo>;
|
||||||
|
@ -171,8 +171,8 @@ fn test_set_memory() {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_unsized_unique() {
|
fn test_unsized_unique() {
|
||||||
let xs: &mut [_] = &mut [1, 2, 3];
|
let xs: &mut [_] = &mut [1, 2, 3];
|
||||||
let ptr = Unique(xs as *mut [_]);
|
let ptr = unsafe { Unique::new(xs as *mut [_]) };
|
||||||
let ys = unsafe { &mut *ptr.ptr };
|
let ys = unsafe { &mut **ptr };
|
||||||
let zs: &mut [_] = &mut [1, 2, 3];
|
let zs: &mut [_] = &mut [1, 2, 3];
|
||||||
assert!(ys == zs);
|
assert!(ys == zs);
|
||||||
}
|
}
|
||||||
|
@ -43,13 +43,13 @@ fn iterator_to_slice() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
let mut iter = data.iter();
|
let mut iter = data.iter();
|
||||||
assert_eq!(&iter[], &other_data[]);
|
assert_eq!(&iter[..], &other_data[..]);
|
||||||
|
|
||||||
iter.next();
|
iter.next();
|
||||||
assert_eq!(&iter[], &other_data[1..]);
|
assert_eq!(&iter[..], &other_data[1..]);
|
||||||
|
|
||||||
iter.next_back();
|
iter.next_back();
|
||||||
assert_eq!(&iter[], &other_data[1..2]);
|
assert_eq!(&iter[..], &other_data[1..2]);
|
||||||
|
|
||||||
let s = iter.as_slice();
|
let s = iter.as_slice();
|
||||||
iter.next();
|
iter.next();
|
||||||
@ -57,17 +57,17 @@ fn iterator_to_slice() {
|
|||||||
}
|
}
|
||||||
{
|
{
|
||||||
let mut iter = data.iter_mut();
|
let mut iter = data.iter_mut();
|
||||||
assert_eq!(&iter[], &other_data[]);
|
assert_eq!(&iter[..], &other_data[..]);
|
||||||
// mutability:
|
// mutability:
|
||||||
assert!(&mut iter[] == other_data);
|
assert!(&mut iter[] == other_data);
|
||||||
|
|
||||||
iter.next();
|
iter.next();
|
||||||
assert_eq!(&iter[], &other_data[1..]);
|
assert_eq!(&iter[..], &other_data[1..]);
|
||||||
assert!(&mut iter[] == &mut other_data[1..]);
|
assert!(&mut iter[] == &mut other_data[1..]);
|
||||||
|
|
||||||
iter.next_back();
|
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]);
|
assert!(&mut iter[] == &mut other_data[1..2]);
|
||||||
|
|
||||||
let s = iter.into_slice();
|
let s = iter.into_slice();
|
||||||
|
@ -45,13 +45,13 @@ pub struct Bytes {
|
|||||||
impl Deref for Bytes {
|
impl Deref for Bytes {
|
||||||
type Target = [u8];
|
type Target = [u8];
|
||||||
fn deref(&self) -> &[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 {
|
impl Drop for Bytes {
|
||||||
fn drop(&mut self) {
|
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<Bytes> {
|
|||||||
&mut outsz,
|
&mut outsz,
|
||||||
flags);
|
flags);
|
||||||
if !res.is_null() {
|
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 })
|
Some(Bytes { ptr: res, len: outsz as uint })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -110,7 +110,7 @@ fn inflate_bytes_internal(bytes: &[u8], flags: c_int) -> Option<Bytes> {
|
|||||||
&mut outsz,
|
&mut outsz,
|
||||||
flags);
|
flags);
|
||||||
if !res.is_null() {
|
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 })
|
Some(Bytes { ptr: res, len: outsz as uint })
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -215,11 +215,11 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
Some((_, other)) => {
|
Some((_, other)) => {
|
||||||
self.err(&format!("expected `{:?}`, found `{:?}`", c,
|
self.err(&format!("expected `{:?}`, found `{:?}`", c,
|
||||||
other)[]);
|
other));
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
self.err(&format!("expected `{:?}` but string was terminated",
|
self.err(&format!("expected `{:?}` but string was terminated",
|
||||||
c)[]);
|
c));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,7 +287,7 @@ impl OptGroup {
|
|||||||
|
|
||||||
impl Matches {
|
impl Matches {
|
||||||
fn opt_vals(&self, nm: &str) -> Vec<Optval> {
|
fn opt_vals(&self, nm: &str) -> Vec<Optval> {
|
||||||
match find_opt(&self.opts[], Name::from_str(nm)) {
|
match find_opt(&self.opts[..], Name::from_str(nm)) {
|
||||||
Some(id) => self.vals[id].clone(),
|
Some(id) => self.vals[id].clone(),
|
||||||
None => panic!("No option '{}' defined", nm)
|
None => panic!("No option '{}' defined", nm)
|
||||||
}
|
}
|
||||||
@ -326,7 +326,7 @@ impl Matches {
|
|||||||
/// Returns the string argument supplied to one of several matching options or `None`.
|
/// Returns the string argument supplied to one of several matching options or `None`.
|
||||||
pub fn opts_str(&self, names: &[String]) -> Option<String> {
|
pub fn opts_str(&self, names: &[String]) -> Option<String> {
|
||||||
for nm in names {
|
for nm in names {
|
||||||
match self.opt_val(&nm[]) {
|
match self.opt_val(&nm[..]) {
|
||||||
Some(Val(ref s)) => return Some(s.clone()),
|
Some(Val(ref s)) => return Some(s.clone()),
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
@ -593,7 +593,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result {
|
|||||||
while i < l {
|
while i < l {
|
||||||
let cur = args[i].clone();
|
let cur = args[i].clone();
|
||||||
let curlen = cur.len();
|
let curlen = cur.len();
|
||||||
if !is_arg(&cur[]) {
|
if !is_arg(&cur[..]) {
|
||||||
free.push(cur);
|
free.push(cur);
|
||||||
} else if cur == "--" {
|
} else if cur == "--" {
|
||||||
let mut j = i + 1;
|
let mut j = i + 1;
|
||||||
@ -667,7 +667,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result {
|
|||||||
v.push(Val((i_arg.clone())
|
v.push(Val((i_arg.clone())
|
||||||
.unwrap()));
|
.unwrap()));
|
||||||
} else if name_pos < names.len() || i + 1 == l ||
|
} else if name_pos < names.len() || i + 1 == l ||
|
||||||
is_arg(&args[i + 1][]) {
|
is_arg(&args[i + 1][..]) {
|
||||||
let v = &mut vals[optid];
|
let v = &mut vals[optid];
|
||||||
v.push(Given);
|
v.push(Given);
|
||||||
} else {
|
} else {
|
||||||
@ -730,7 +730,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String {
|
|||||||
0 => {}
|
0 => {}
|
||||||
1 => {
|
1 => {
|
||||||
row.push('-');
|
row.push('-');
|
||||||
row.push_str(&short_name[]);
|
row.push_str(&short_name[..]);
|
||||||
row.push(' ');
|
row.push(' ');
|
||||||
}
|
}
|
||||||
_ => panic!("the short name should only be 1 ascii char long"),
|
_ => panic!("the short name should only be 1 ascii char long"),
|
||||||
@ -741,7 +741,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String {
|
|||||||
0 => {}
|
0 => {}
|
||||||
_ => {
|
_ => {
|
||||||
row.push_str("--");
|
row.push_str("--");
|
||||||
row.push_str(&long_name[]);
|
row.push_str(&long_name[..]);
|
||||||
row.push(' ');
|
row.push(' ');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -749,10 +749,10 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String {
|
|||||||
// arg
|
// arg
|
||||||
match hasarg {
|
match hasarg {
|
||||||
No => {}
|
No => {}
|
||||||
Yes => row.push_str(&hint[]),
|
Yes => row.push_str(&hint[..]),
|
||||||
Maybe => {
|
Maybe => {
|
||||||
row.push('[');
|
row.push('[');
|
||||||
row.push_str(&hint[]);
|
row.push_str(&hint[..]);
|
||||||
row.push(']');
|
row.push(']');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -765,7 +765,7 @@ pub fn usage(brief: &str, opts: &[OptGroup]) -> String {
|
|||||||
row.push(' ');
|
row.push(' ');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
row.push_str(&desc_sep[]);
|
row.push_str(&desc_sep[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize desc to contain words separated by one space character
|
// 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
|
// FIXME: #5516 should be graphemes not codepoints
|
||||||
let mut desc_rows = Vec::new();
|
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());
|
desc_rows.push(substr.to_string());
|
||||||
true
|
true
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIXME: #5516 should be graphemes not codepoints
|
// FIXME: #5516 should be graphemes not codepoints
|
||||||
// wrapped description
|
// wrapped description
|
||||||
row.push_str(&desc_rows.connect(&desc_sep[])[]);
|
row.push_str(&desc_rows.connect(&desc_sep[..])[]);
|
||||||
|
|
||||||
row
|
row
|
||||||
});
|
});
|
||||||
@ -803,10 +803,10 @@ fn format_option(opt: &OptGroup) -> String {
|
|||||||
// Use short_name is possible, but fallback to long_name.
|
// Use short_name is possible, but fallback to long_name.
|
||||||
if opt.short_name.len() > 0 {
|
if opt.short_name.len() > 0 {
|
||||||
line.push('-');
|
line.push('-');
|
||||||
line.push_str(&opt.short_name[]);
|
line.push_str(&opt.short_name[..]);
|
||||||
} else {
|
} else {
|
||||||
line.push_str("--");
|
line.push_str("--");
|
||||||
line.push_str(&opt.long_name[]);
|
line.push_str(&opt.long_name[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if opt.hasarg != No {
|
if opt.hasarg != No {
|
||||||
@ -814,7 +814,7 @@ fn format_option(opt: &OptGroup) -> String {
|
|||||||
if opt.hasarg == Maybe {
|
if opt.hasarg == Maybe {
|
||||||
line.push('[');
|
line.push('[');
|
||||||
}
|
}
|
||||||
line.push_str(&opt.hint[]);
|
line.push_str(&opt.hint[..]);
|
||||||
if opt.hasarg == Maybe {
|
if opt.hasarg == Maybe {
|
||||||
line.push(']');
|
line.push(']');
|
||||||
}
|
}
|
||||||
@ -836,7 +836,7 @@ pub fn short_usage(program_name: &str, opts: &[OptGroup]) -> String {
|
|||||||
line.push_str(&opts.iter()
|
line.push_str(&opts.iter()
|
||||||
.map(format_option)
|
.map(format_option)
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.connect(" ")[]);
|
.connect(" ")[..]);
|
||||||
line
|
line
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,15 +275,12 @@
|
|||||||
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
||||||
#![feature(int_uint)]
|
#![feature(int_uint)]
|
||||||
#![feature(collections)]
|
#![feature(collections)]
|
||||||
#![feature(core)]
|
|
||||||
#![feature(old_io)]
|
#![feature(old_io)]
|
||||||
|
|
||||||
use self::LabelText::*;
|
use self::LabelText::*;
|
||||||
|
|
||||||
use std::borrow::IntoCow;
|
use std::borrow::{IntoCow, Cow};
|
||||||
use std::old_io;
|
use std::old_io;
|
||||||
use std::string::CowString;
|
|
||||||
use std::vec::CowVec;
|
|
||||||
|
|
||||||
/// The text for a graphviz label on a node or edge.
|
/// The text for a graphviz label on a node or edge.
|
||||||
pub enum LabelText<'a> {
|
pub enum LabelText<'a> {
|
||||||
@ -291,7 +288,7 @@ pub enum LabelText<'a> {
|
|||||||
///
|
///
|
||||||
/// Occurrences of backslashes (`\`) are escaped, and thus appear
|
/// Occurrences of backslashes (`\`) are escaped, and thus appear
|
||||||
/// as backslashes in the rendered label.
|
/// as backslashes in the rendered label.
|
||||||
LabelStr(CowString<'a>),
|
LabelStr(Cow<'a, str>),
|
||||||
|
|
||||||
/// This kind of label uses the graphviz label escString type:
|
/// This kind of label uses the graphviz label escString type:
|
||||||
/// http://www.graphviz.org/content/attrs#kescString
|
/// 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
|
/// to break a line (centering the line preceding the `\n`), there
|
||||||
/// are also the escape sequences `\l` which left-justifies the
|
/// are also the escape sequences `\l` which left-justifies the
|
||||||
/// preceding line and `\r` which right-justifies it.
|
/// 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.
|
// There is a tension in the design of the labelling API.
|
||||||
@ -340,7 +337,7 @@ pub enum LabelText<'a> {
|
|||||||
|
|
||||||
/// `Id` is a Graphviz `ID`.
|
/// `Id` is a Graphviz `ID`.
|
||||||
pub struct Id<'a> {
|
pub struct Id<'a> {
|
||||||
name: CowString<'a>,
|
name: Cow<'a, str>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Id<'a> {
|
impl<'a> Id<'a> {
|
||||||
@ -358,7 +355,7 @@ impl<'a> Id<'a> {
|
|||||||
///
|
///
|
||||||
/// Passing an invalid string (containing spaces, brackets,
|
/// Passing an invalid string (containing spaces, brackets,
|
||||||
/// quotes, ...) will return an empty `Err` value.
|
/// quotes, ...) will return an empty `Err` value.
|
||||||
pub fn new<Name: IntoCow<'a, String, str>>(name: Name) -> Result<Id<'a>, ()> {
|
pub fn new<Name: IntoCow<'a, str>>(name: Name) -> Result<Id<'a>, ()> {
|
||||||
let name = name.into_cow();
|
let name = name.into_cow();
|
||||||
{
|
{
|
||||||
let mut chars = name.chars();
|
let mut chars = name.chars();
|
||||||
@ -387,7 +384,7 @@ impl<'a> Id<'a> {
|
|||||||
&*self.name
|
&*self.name
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn name(self) -> CowString<'a> {
|
pub fn name(self) -> Cow<'a, str> {
|
||||||
self.name
|
self.name
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -427,11 +424,11 @@ pub trait Labeller<'a,N,E> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LabelText<'a> {
|
impl<'a> LabelText<'a> {
|
||||||
pub fn label<S:IntoCow<'a, String, str>>(s: S) -> LabelText<'a> {
|
pub fn label<S:IntoCow<'a, str>>(s: S) -> LabelText<'a> {
|
||||||
LabelStr(s.into_cow())
|
LabelStr(s.into_cow())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn escaped<S:IntoCow<'a, String, str>>(s: S) -> LabelText<'a> {
|
pub fn escaped<S:IntoCow<'a, str>>(s: S) -> LabelText<'a> {
|
||||||
EscStr(s.into_cow())
|
EscStr(s.into_cow())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -455,7 +452,7 @@ impl<'a> LabelText<'a> {
|
|||||||
pub fn escape(&self) -> String {
|
pub fn escape(&self) -> String {
|
||||||
match self {
|
match self {
|
||||||
&LabelStr(ref s) => s.escape_default(),
|
&LabelStr(ref s) => s.escape_default(),
|
||||||
&EscStr(ref s) => LabelText::escape_str(&s[]),
|
&EscStr(ref s) => LabelText::escape_str(&s[..]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,7 +460,7 @@ impl<'a> LabelText<'a> {
|
|||||||
/// yields same content as self. The result obeys the law
|
/// yields same content as self. The result obeys the law
|
||||||
/// render(`lt`) == render(`EscStr(lt.pre_escaped_content())`) for
|
/// render(`lt`) == render(`EscStr(lt.pre_escaped_content())`) for
|
||||||
/// all `lt: LabelText`.
|
/// all `lt: LabelText`.
|
||||||
fn pre_escaped_content(self) -> CowString<'a> {
|
fn pre_escaped_content(self) -> Cow<'a, str> {
|
||||||
match self {
|
match self {
|
||||||
EscStr(s) => s,
|
EscStr(s) => s,
|
||||||
LabelStr(s) => if s.contains_char('\\') {
|
LabelStr(s) => if s.contains_char('\\') {
|
||||||
@ -484,13 +481,13 @@ impl<'a> LabelText<'a> {
|
|||||||
let mut prefix = self.pre_escaped_content().into_owned();
|
let mut prefix = self.pre_escaped_content().into_owned();
|
||||||
let suffix = suffix.pre_escaped_content();
|
let suffix = suffix.pre_escaped_content();
|
||||||
prefix.push_str(r"\n\n");
|
prefix.push_str(r"\n\n");
|
||||||
prefix.push_str(&suffix[]);
|
prefix.push_str(&suffix[..]);
|
||||||
EscStr(prefix.into_cow())
|
EscStr(prefix.into_cow())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type Nodes<'a,N> = CowVec<'a,N>;
|
pub type Nodes<'a,N> = Cow<'a,[N]>;
|
||||||
pub type Edges<'a,E> = CowVec<'a,E>;
|
pub type Edges<'a,E> = Cow<'a,[E]>;
|
||||||
|
|
||||||
// (The type parameters in GraphWalk should be associated items,
|
// (The type parameters in GraphWalk should be associated items,
|
||||||
// when/if Rust supports such.)
|
// when/if Rust supports such.)
|
||||||
@ -678,7 +675,7 @@ mod tests {
|
|||||||
|
|
||||||
impl<'a> Labeller<'a, Node, &'a Edge> for LabelledGraph {
|
impl<'a> Labeller<'a, Node, &'a Edge> for LabelledGraph {
|
||||||
fn graph_id(&'a self) -> Id<'a> {
|
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> {
|
fn node_id(&'a self, n: &Node) -> Id<'a> {
|
||||||
id_name(n)
|
id_name(n)
|
||||||
|
@ -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
|
// Test the literal string from args against the current filter, if there
|
||||||
// is one.
|
// is one.
|
||||||
match unsafe { FILTER.as_ref() } {
|
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.
|
// Search for the longest match, the vector is assumed to be pre-sorted.
|
||||||
for directive in iter.rev() {
|
for directive in iter.rev() {
|
||||||
match directive.name {
|
match directive.name {
|
||||||
Some(ref name) if !module.starts_with(&name[]) => {},
|
Some(ref name) if !module.starts_with(&name[..]) => {},
|
||||||
Some(..) | None => {
|
Some(..) | None => {
|
||||||
return level <= directive.level
|
return level <= directive.level
|
||||||
}
|
}
|
||||||
@ -397,7 +397,7 @@ fn enabled(level: u32,
|
|||||||
/// `Once` primitive (and this function is called from that primitive).
|
/// `Once` primitive (and this function is called from that primitive).
|
||||||
fn init() {
|
fn init() {
|
||||||
let (mut directives, filter) = match env::var("RUST_LOG") {
|
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),
|
Err(..) => (Vec::new(), None),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
use core::num::{Float, Int};
|
use core::num::{Float, Int};
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
use {Rng, Rand};
|
use {Rng, Rand};
|
||||||
|
|
||||||
@ -56,7 +57,13 @@ pub trait IndependentSample<Support>: Sample<Support> {
|
|||||||
|
|
||||||
/// A wrapper for generating types that implement `Rand` via the
|
/// A wrapper for generating types that implement `Rand` via the
|
||||||
/// `Sample` & `IndependentSample` traits.
|
/// `Sample` & `IndependentSample` traits.
|
||||||
pub struct RandSample<Sup>;
|
pub struct RandSample<Sup> { _marker: PhantomData<Sup> }
|
||||||
|
|
||||||
|
impl<Sup> RandSample<Sup> {
|
||||||
|
pub fn new() -> RandSample<Sup> {
|
||||||
|
RandSample { _marker: PhantomData }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<Sup: Rand> Sample<Sup> for RandSample<Sup> {
|
impl<Sup: Rand> Sample<Sup> for RandSample<Sup> {
|
||||||
fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
|
fn sample<R: Rng>(&mut self, rng: &mut R) -> Sup { self.ind_sample(rng) }
|
||||||
@ -285,7 +292,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rand_sample() {
|
fn test_rand_sample() {
|
||||||
let mut rand_sample = RandSample::<ConstRand>;
|
let mut rand_sample = RandSample::<ConstRand>::new();
|
||||||
|
|
||||||
assert_eq!(rand_sample.sample(&mut ::test::rng()), ConstRand(0));
|
assert_eq!(rand_sample.sample(&mut ::test::rng()), ConstRand(0));
|
||||||
assert_eq!(rand_sample.ind_sample(&mut ::test::rng()), ConstRand(0));
|
assert_eq!(rand_sample.ind_sample(&mut ::test::rng()), ConstRand(0));
|
||||||
|
@ -215,7 +215,7 @@ impl<'a> SeedableRng<&'a [u32]> for IsaacRng {
|
|||||||
fn reseed(&mut self, seed: &'a [u32]) {
|
fn reseed(&mut self, seed: &'a [u32]) {
|
||||||
// make the seed into [seed[0], seed[1], ..., seed[seed.len()
|
// make the seed into [seed[0], seed[1], ..., seed[seed.len()
|
||||||
// - 1], 0, 0, ...], to fill rng.rsl.
|
// - 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) {
|
for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
|
||||||
*rsl_elem = seed_elem;
|
*rsl_elem = seed_elem;
|
||||||
@ -458,7 +458,7 @@ impl<'a> SeedableRng<&'a [u64]> for Isaac64Rng {
|
|||||||
fn reseed(&mut self, seed: &'a [u64]) {
|
fn reseed(&mut self, seed: &'a [u64]) {
|
||||||
// make the seed into [seed[0], seed[1], ..., seed[seed.len()
|
// make the seed into [seed[0], seed[1], ..., seed[seed.len()
|
||||||
// - 1], 0, 0, ...], to fill rng.rsl.
|
// - 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) {
|
for (rsl_elem, seed_elem) in self.rsl.iter_mut().zip(seed_iter) {
|
||||||
*rsl_elem = seed_elem;
|
*rsl_elem = seed_elem;
|
||||||
|
@ -41,6 +41,7 @@ extern crate core;
|
|||||||
#[cfg(test)] #[macro_use] extern crate log;
|
#[cfg(test)] #[macro_use] extern crate log;
|
||||||
|
|
||||||
use core::prelude::*;
|
use core::prelude::*;
|
||||||
|
use core::marker::PhantomData;
|
||||||
|
|
||||||
pub use isaac::{IsaacRng, Isaac64Rng};
|
pub use isaac::{IsaacRng, Isaac64Rng};
|
||||||
pub use chacha::ChaChaRng;
|
pub use chacha::ChaChaRng;
|
||||||
@ -206,7 +207,7 @@ pub trait Rng : Sized {
|
|||||||
/// .collect::<Vec<(f64, bool)>>());
|
/// .collect::<Vec<(f64, bool)>>());
|
||||||
/// ```
|
/// ```
|
||||||
fn gen_iter<'a, T: Rand>(&'a mut self) -> Generator<'a, T, Self> {
|
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`).
|
/// Generate a random value in the range [`low`, `high`).
|
||||||
@ -317,6 +318,7 @@ pub trait Rng : Sized {
|
|||||||
/// This iterator is created via the `gen_iter` method on `Rng`.
|
/// This iterator is created via the `gen_iter` method on `Rng`.
|
||||||
pub struct Generator<'a, T, R:'a> {
|
pub struct Generator<'a, T, R:'a> {
|
||||||
rng: &'a mut R,
|
rng: &'a mut R,
|
||||||
|
_marker: PhantomData<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> {
|
impl<'a, T: Rand, R: Rng> Iterator for Generator<'a, T, R> {
|
||||||
|
@ -37,7 +37,7 @@ use util::ppaux::{ty_to_string};
|
|||||||
use util::nodemap::{FnvHashMap, NodeSet};
|
use util::nodemap::{FnvHashMap, NodeSet};
|
||||||
use lint::{Level, Context, LintPass, LintArray, Lint};
|
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::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
use std::num::SignedInt;
|
use std::num::SignedInt;
|
||||||
use std::{cmp, slice};
|
use std::{cmp, slice};
|
||||||
@ -508,7 +508,7 @@ impl BoxPointers {
|
|||||||
if n_uniq > 0 {
|
if n_uniq > 0 {
|
||||||
let s = ty_to_string(cx.tcx, ty);
|
let s = ty_to_string(cx.tcx, ty);
|
||||||
let m = format!("type uses owned (Box type) pointers: {}", s);
|
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 @@ impl LintPass for UnusedResults {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let attrs = csearch::get_item_attrs(&cx.sess().cstore, did);
|
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 @@ impl NonCamelCaseTypes {
|
|||||||
} else {
|
} else {
|
||||||
format!("{} `{}` should have a camel case name such as `{}`", sort, s, c)
|
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 @@ impl NonSnakeCase {
|
|||||||
|
|
||||||
if !is_snake_case(ident) {
|
if !is_snake_case(ident) {
|
||||||
let sc = NonSnakeCase::to_snake_case(&s);
|
let sc = NonSnakeCase::to_snake_case(&s);
|
||||||
if sc != &s[] {
|
if sc != &s[..] {
|
||||||
cx.span_lint(NON_SNAKE_CASE, span,
|
cx.span_lint(NON_SNAKE_CASE, span,
|
||||||
&*format!("{} `{}` should have a snake case name such as `{}`",
|
&*format!("{} `{}` should have a snake case name such as `{}`",
|
||||||
sort, s, sc));
|
sort, s, sc));
|
||||||
@ -1033,7 +1033,7 @@ impl NonUpperCaseGlobals {
|
|||||||
if s.chars().any(|c| c.is_lowercase()) {
|
if s.chars().any(|c| c.is_lowercase()) {
|
||||||
let uc: String = NonSnakeCase::to_snake_case(&s).chars()
|
let uc: String = NonSnakeCase::to_snake_case(&s).chars()
|
||||||
.map(|c| c.to_uppercase()).collect();
|
.map(|c| c.to_uppercase()).collect();
|
||||||
if uc != &s[] {
|
if uc != &s[..] {
|
||||||
cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
|
cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
|
||||||
&format!("{} `{}` should have an upper case name such as `{}`",
|
&format!("{} `{}` should have an upper case name such as `{}`",
|
||||||
sort, s, uc));
|
sort, s, uc));
|
||||||
@ -1196,7 +1196,7 @@ impl LintPass for UnusedImportBraces {
|
|||||||
let m = format!("braces around {} is unnecessary",
|
let m = format!("braces around {} is unnecessary",
|
||||||
&token::get_ident(*name));
|
&token::get_ident(*name));
|
||||||
cx.span_lint(UNUSED_IMPORT_BRACES, item.span,
|
cx.span_lint(UNUSED_IMPORT_BRACES, item.span,
|
||||||
&m[]);
|
&m[..]);
|
||||||
},
|
},
|
||||||
_ => ()
|
_ => ()
|
||||||
}
|
}
|
||||||
@ -1474,7 +1474,7 @@ impl LintPass for MissingDoc {
|
|||||||
let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| {
|
let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| {
|
||||||
attr.check_name("doc") && match attr.meta_item_list() {
|
attr.check_name("doc") && match attr.meta_item_list() {
|
||||||
None => false,
|
None => false,
|
||||||
Some(l) => attr::contains_name(&l[], "hidden"),
|
Some(l) => attr::contains_name(&l[..], "hidden"),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
self.doc_hidden_stack.push(doc_hidden);
|
self.doc_hidden_stack.push(doc_hidden);
|
||||||
@ -1702,7 +1702,7 @@ impl Stability {
|
|||||||
_ => format!("use of {} item", label)
|
_ => format!("use of {} item", label)
|
||||||
};
|
};
|
||||||
|
|
||||||
cx.span_lint(lint, span, &msg[]);
|
cx.span_lint(lint, span, &msg[..]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1791,7 +1791,7 @@ impl LintPass for UnconditionalRecursion {
|
|||||||
let mut work_queue = vec![cfg.entry];
|
let mut work_queue = vec![cfg.entry];
|
||||||
let mut reached_exit_without_self_call = false;
|
let mut reached_exit_without_self_call = false;
|
||||||
let mut self_call_spans = vec![];
|
let mut self_call_spans = vec![];
|
||||||
let mut visited = BitvSet::new();
|
let mut visited = BitSet::new();
|
||||||
|
|
||||||
while let Some(idx) = work_queue.pop() {
|
while let Some(idx) = work_queue.pop() {
|
||||||
let cfg_id = idx.node_id();
|
let cfg_id = idx.node_id();
|
||||||
|
@ -125,11 +125,11 @@ impl LintStore {
|
|||||||
match (sess, from_plugin) {
|
match (sess, from_plugin) {
|
||||||
// We load builtin lints first, so a duplicate is a compiler bug.
|
// We load builtin lints first, so a duplicate is a compiler bug.
|
||||||
// Use early_error when handling -W help with no crate.
|
// Use early_error when handling -W help with no crate.
|
||||||
(None, _) => early_error(&msg[]),
|
(None, _) => early_error(&msg[..]),
|
||||||
(Some(sess), false) => sess.bug(&msg[]),
|
(Some(sess), false) => sess.bug(&msg[..]),
|
||||||
|
|
||||||
// A duplicate name from a plugin is a user error.
|
// 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 @@ impl LintStore {
|
|||||||
match (sess, from_plugin) {
|
match (sess, from_plugin) {
|
||||||
// We load builtin lints first, so a duplicate is a compiler bug.
|
// We load builtin lints first, so a duplicate is a compiler bug.
|
||||||
// Use early_error when handling -W help with no crate.
|
// Use early_error when handling -W help with no crate.
|
||||||
(None, _) => early_error(&msg[]),
|
(None, _) => early_error(&msg[..]),
|
||||||
(Some(sess), false) => sess.bug(&msg[]),
|
(Some(sess), false) => sess.bug(&msg[..]),
|
||||||
|
|
||||||
// A duplicate name from a plugin is a user error.
|
// 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 @@ impl LintStore {
|
|||||||
let warning = format!("lint {} has been renamed to {}",
|
let warning = format!("lint {} has been renamed to {}",
|
||||||
lint_name, new_name);
|
lint_name, new_name);
|
||||||
match span {
|
match span {
|
||||||
Some(span) => sess.span_warn(span, &warning[]),
|
Some(span) => sess.span_warn(span, &warning[..]),
|
||||||
None => sess.warn(&warning[]),
|
None => sess.warn(&warning[..]),
|
||||||
};
|
};
|
||||||
Some(lint_id)
|
Some(lint_id)
|
||||||
}
|
}
|
||||||
@ -262,13 +262,13 @@ impl LintStore {
|
|||||||
|
|
||||||
pub fn process_command_line(&mut self, sess: &Session) {
|
pub fn process_command_line(&mut self, sess: &Session) {
|
||||||
for &(ref lint_name, level) in &sess.opts.lint_opts {
|
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)),
|
Some(lint_id) => self.set_level(lint_id, (level, CommandLine)),
|
||||||
None => {
|
None => {
|
||||||
match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone()))
|
match self.lint_groups.iter().map(|(&x, pair)| (x, pair.0.clone()))
|
||||||
.collect::<FnvHashMap<&'static str,
|
.collect::<FnvHashMap<&'static str,
|
||||||
Vec<LintId>>>()
|
Vec<LintId>>>()
|
||||||
.get(&lint_name[]) {
|
.get(&lint_name[..]) {
|
||||||
Some(v) => {
|
Some(v) => {
|
||||||
v.iter()
|
v.iter()
|
||||||
.map(|lint_id: &LintId|
|
.map(|lint_id: &LintId|
|
||||||
@ -411,15 +411,15 @@ pub fn raw_emit_lint(sess: &Session, lint: &'static Lint,
|
|||||||
if level == Forbid { level = Deny; }
|
if level == Forbid { level = Deny; }
|
||||||
|
|
||||||
match (level, span) {
|
match (level, span) {
|
||||||
(Warn, Some(sp)) => sess.span_warn(sp, &msg[]),
|
(Warn, Some(sp)) => sess.span_warn(sp, &msg[..]),
|
||||||
(Warn, None) => sess.warn(&msg[]),
|
(Warn, None) => sess.warn(&msg[..]),
|
||||||
(Deny, Some(sp)) => sess.span_err(sp, &msg[]),
|
(Deny, Some(sp)) => sess.span_err(sp, &msg[..]),
|
||||||
(Deny, None) => sess.err(&msg[]),
|
(Deny, None) => sess.err(&msg[..]),
|
||||||
_ => sess.bug("impossible level in raw_emit_lint"),
|
_ => sess.bug("impossible level in raw_emit_lint"),
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(note) = note {
|
if let Some(note) = note {
|
||||||
sess.note(¬e[]);
|
sess.note(¬e[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(span) = def {
|
if let Some(span) = def {
|
||||||
@ -503,7 +503,7 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
|
|||||||
match self.lints.find_lint(&lint_name, &self.tcx.sess, Some(span)) {
|
match self.lints.find_lint(&lint_name, &self.tcx.sess, Some(span)) {
|
||||||
Some(lint_id) => vec![(lint_id, level, span)],
|
Some(lint_id) => vec![(lint_id, level, span)],
|
||||||
None => {
|
None => {
|
||||||
match self.lints.lint_groups.get(&lint_name[]) {
|
match self.lints.lint_groups.get(&lint_name[..]) {
|
||||||
Some(&(ref v, _)) => v.iter()
|
Some(&(ref v, _)) => v.iter()
|
||||||
.map(|lint_id: &LintId|
|
.map(|lint_id: &LintId|
|
||||||
(*lint_id, level, span))
|
(*lint_id, level, span))
|
||||||
@ -729,7 +729,7 @@ impl<'a, 'tcx> IdVisitingOperation for Context<'a, 'tcx> {
|
|||||||
None => {}
|
None => {}
|
||||||
Some(lints) => {
|
Some(lints) => {
|
||||||
for (lint_id, span, msg) in lints {
|
for (lint_id, span, msg) in lints {
|
||||||
self.span_lint(lint_id.lint, span, &msg[])
|
self.span_lint(lint_id.lint, span, &msg[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -185,12 +185,20 @@ impl PartialEq for LintId {
|
|||||||
|
|
||||||
impl Eq for LintId { }
|
impl Eq for LintId { }
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for LintId {
|
impl<S: hash::Writer + hash::Hasher> hash::Hash<S> for LintId {
|
||||||
fn hash(&self, state: &mut S) {
|
fn hash(&self, state: &mut S) {
|
||||||
let ptr = self.lint as *const Lint;
|
let ptr = self.lint as *const Lint;
|
||||||
ptr.hash(state);
|
ptr.hash(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
impl hash::Hash for LintId {
|
||||||
|
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||||
|
let ptr = self.lint as *const Lint;
|
||||||
|
ptr.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl LintId {
|
impl LintId {
|
||||||
/// Get the `LintId` for a `Lint`.
|
/// Get the `LintId` for a `Lint`.
|
||||||
|
@ -183,7 +183,7 @@ impl<'a> CrateReader<'a> {
|
|||||||
let name = match *path_opt {
|
let name = match *path_opt {
|
||||||
Some((ref path_str, _)) => {
|
Some((ref path_str, _)) => {
|
||||||
let name = path_str.to_string();
|
let name = path_str.to_string();
|
||||||
validate_crate_name(Some(self.sess), &name[],
|
validate_crate_name(Some(self.sess), &name[..],
|
||||||
Some(i.span));
|
Some(i.span));
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
@ -321,7 +321,7 @@ impl<'a> CrateReader<'a> {
|
|||||||
let source = self.sess.cstore.get_used_crate_source(cnum).unwrap();
|
let source = self.sess.cstore.get_used_crate_source(cnum).unwrap();
|
||||||
if let Some(locs) = self.sess.opts.externs.get(name) {
|
if let Some(locs) = self.sess.opts.externs.get(name) {
|
||||||
let found = locs.iter().any(|l| {
|
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.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
|
||||||
source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
|
source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
|
||||||
});
|
});
|
||||||
@ -459,8 +459,8 @@ impl<'a> CrateReader<'a> {
|
|||||||
let mut load_ctxt = loader::Context {
|
let mut load_ctxt = loader::Context {
|
||||||
sess: self.sess,
|
sess: self.sess,
|
||||||
span: span,
|
span: span,
|
||||||
ident: &ident[],
|
ident: &ident[..],
|
||||||
crate_name: &name[],
|
crate_name: &name[..],
|
||||||
hash: None,
|
hash: None,
|
||||||
filesearch: self.sess.host_filesearch(PathKind::Crate),
|
filesearch: self.sess.host_filesearch(PathKind::Crate),
|
||||||
target: &self.sess.host,
|
target: &self.sess.host,
|
||||||
@ -562,7 +562,7 @@ impl<'a> CrateReader<'a> {
|
|||||||
name,
|
name,
|
||||||
config::host_triple(),
|
config::host_triple(),
|
||||||
self.sess.opts.target_triple);
|
self.sess.opts.target_triple);
|
||||||
self.sess.span_err(span, &message[]);
|
self.sess.span_err(span, &message[..]);
|
||||||
self.sess.abort_if_errors();
|
self.sess.abort_if_errors();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -575,7 +575,7 @@ impl<'a> CrateReader<'a> {
|
|||||||
let message = format!("plugin `{}` only found in rlib format, \
|
let message = format!("plugin `{}` only found in rlib format, \
|
||||||
but must be available in dylib format",
|
but must be available in dylib format",
|
||||||
name);
|
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
|
// No need to abort because the loading code will just ignore this
|
||||||
// empty dylib.
|
// empty dylib.
|
||||||
None
|
None
|
||||||
|
@ -139,8 +139,7 @@ impl CStore {
|
|||||||
pub fn get_used_crate_source(&self, cnum: ast::CrateNum)
|
pub fn get_used_crate_source(&self, cnum: ast::CrateNum)
|
||||||
-> Option<CrateSource> {
|
-> Option<CrateSource> {
|
||||||
self.used_crate_sources.borrow_mut()
|
self.used_crate_sources.borrow_mut()
|
||||||
.iter().find(|source| source.cnum == cnum)
|
.iter().find(|source| source.cnum == cnum).cloned()
|
||||||
.map(|source| source.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reset(&self) {
|
pub fn reset(&self) {
|
||||||
@ -218,7 +217,7 @@ impl CStore {
|
|||||||
|
|
||||||
pub fn find_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId)
|
pub fn find_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId)
|
||||||
-> Option<ast::CrateNum> {
|
-> Option<ast::CrateNum> {
|
||||||
self.extern_mod_crate_map.borrow().get(&emod_id).map(|x| *x)
|
self.extern_mod_crate_map.borrow().get(&emod_id).cloned()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ fn encode_variant_id(rbml_w: &mut Encoder, vid: DefId) {
|
|||||||
rbml_w.end_tag();
|
rbml_w.end_tag();
|
||||||
|
|
||||||
rbml_w.start_tag(tag_mod_child);
|
rbml_w.start_tag(tag_mod_child);
|
||||||
rbml_w.wr_str(&s[]);
|
rbml_w.wr_str(&s[..]);
|
||||||
rbml_w.end_tag();
|
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 fields = ty::lookup_struct_fields(ecx.tcx, def_id);
|
||||||
let idx = encode_info_for_struct(ecx,
|
let idx = encode_info_for_struct(ecx,
|
||||||
rbml_w,
|
rbml_w,
|
||||||
&fields[],
|
&fields[..],
|
||||||
index);
|
index);
|
||||||
encode_struct_fields(rbml_w, &fields[], def_id);
|
encode_struct_fields(rbml_w, &fields[..], def_id);
|
||||||
encode_index(rbml_w, idx, write_i64);
|
encode_index(rbml_w, idx, write_i64);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1158,7 +1158,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
|||||||
class itself */
|
class itself */
|
||||||
let idx = encode_info_for_struct(ecx,
|
let idx = encode_info_for_struct(ecx,
|
||||||
rbml_w,
|
rbml_w,
|
||||||
&fields[],
|
&fields[..],
|
||||||
index);
|
index);
|
||||||
|
|
||||||
/* Index the class*/
|
/* Index the class*/
|
||||||
@ -1181,7 +1181,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
|
|||||||
/* Encode def_ids for each field and method
|
/* Encode def_ids for each field and method
|
||||||
for methods, write all the stuff get_trait_method
|
for methods, write all the stuff get_trait_method
|
||||||
needs to know*/
|
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));
|
encode_inlined_item(ecx, rbml_w, IIItemRef(item));
|
||||||
|
|
||||||
@ -1588,6 +1588,7 @@ fn encode_info_for_items(ecx: &EncodeContext,
|
|||||||
|
|
||||||
// Path and definition ID indexing
|
// Path and definition ID indexing
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
|
fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
|
||||||
F: FnMut(&mut SeekableMemWriter, &T),
|
F: FnMut(&mut SeekableMemWriter, &T),
|
||||||
T: Hash<SipHasher>,
|
T: Hash<SipHasher>,
|
||||||
@ -1628,6 +1629,47 @@ fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn:
|
|||||||
rbml_w.end_tag();
|
rbml_w.end_tag();
|
||||||
rbml_w.end_tag();
|
rbml_w.end_tag();
|
||||||
}
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
fn encode_index<T, F>(rbml_w: &mut Encoder, index: Vec<entry<T>>, mut write_fn: F) where
|
||||||
|
F: FnMut(&mut SeekableMemWriter, &T),
|
||||||
|
T: Hash,
|
||||||
|
{
|
||||||
|
let mut buckets: Vec<Vec<entry<T>>> = (0..256u16).map(|_| Vec::new()).collect();
|
||||||
|
for elt in index {
|
||||||
|
let mut s = SipHasher::new();
|
||||||
|
elt.val.hash(&mut s);
|
||||||
|
let h = s.finish() as uint;
|
||||||
|
(&mut buckets[h % 256]).push(elt);
|
||||||
|
}
|
||||||
|
|
||||||
|
rbml_w.start_tag(tag_index);
|
||||||
|
let mut bucket_locs = Vec::new();
|
||||||
|
rbml_w.start_tag(tag_index_buckets);
|
||||||
|
for bucket in &buckets {
|
||||||
|
bucket_locs.push(rbml_w.writer.tell().unwrap());
|
||||||
|
rbml_w.start_tag(tag_index_buckets_bucket);
|
||||||
|
for elt in bucket {
|
||||||
|
rbml_w.start_tag(tag_index_buckets_bucket_elt);
|
||||||
|
assert!(elt.pos < 0xffff_ffff);
|
||||||
|
{
|
||||||
|
let wr: &mut SeekableMemWriter = rbml_w.writer;
|
||||||
|
wr.write_be_u32(elt.pos as u32);
|
||||||
|
}
|
||||||
|
write_fn(rbml_w.writer, &elt.val);
|
||||||
|
rbml_w.end_tag();
|
||||||
|
}
|
||||||
|
rbml_w.end_tag();
|
||||||
|
}
|
||||||
|
rbml_w.end_tag();
|
||||||
|
rbml_w.start_tag(tag_index_table);
|
||||||
|
for pos in &bucket_locs {
|
||||||
|
assert!(*pos < 0xffff_ffff);
|
||||||
|
let wr: &mut SeekableMemWriter = rbml_w.writer;
|
||||||
|
wr.write_be_u32(*pos as u32);
|
||||||
|
}
|
||||||
|
rbml_w.end_tag();
|
||||||
|
rbml_w.end_tag();
|
||||||
|
}
|
||||||
|
|
||||||
fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
|
fn write_i64(writer: &mut SeekableMemWriter, &n: &i64) {
|
||||||
let wr: &mut SeekableMemWriter = writer;
|
let wr: &mut SeekableMemWriter = writer;
|
||||||
|
@ -322,7 +322,7 @@ impl<'a> Context<'a> {
|
|||||||
&Some(ref r) => format!("{} which `{}` depends on",
|
&Some(ref r) => format!("{} which `{}` depends on",
|
||||||
message, r.ident)
|
message, r.ident)
|
||||||
};
|
};
|
||||||
self.sess.span_err(self.span, &message[]);
|
self.sess.span_err(self.span, &message[..]);
|
||||||
|
|
||||||
if self.rejected_via_triple.len() > 0 {
|
if self.rejected_via_triple.len() > 0 {
|
||||||
let mismatches = self.rejected_via_triple.iter();
|
let mismatches = self.rejected_via_triple.iter();
|
||||||
@ -404,7 +404,7 @@ impl<'a> Context<'a> {
|
|||||||
None => return FileDoesntMatch,
|
None => return FileDoesntMatch,
|
||||||
Some(file) => file,
|
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.ends_with(".rlib") {
|
||||||
(&file[(rlib_prefix.len()) .. (file.len() - ".rlib".len())],
|
(&file[(rlib_prefix.len()) .. (file.len() - ".rlib".len())],
|
||||||
true)
|
true)
|
||||||
@ -413,7 +413,7 @@ impl<'a> Context<'a> {
|
|||||||
(&file[(dylib_prefix.len()) .. (file.len() - dypair.1.len())],
|
(&file[(dylib_prefix.len()) .. (file.len() - dypair.1.len())],
|
||||||
false)
|
false)
|
||||||
} else {
|
} else {
|
||||||
if file.starts_with(&staticlib_prefix[]) &&
|
if file.starts_with(&staticlib_prefix[..]) &&
|
||||||
file.ends_with(".a") {
|
file.ends_with(".a") {
|
||||||
staticlibs.push(CrateMismatch {
|
staticlibs.push(CrateMismatch {
|
||||||
path: path.clone(),
|
path: path.clone(),
|
||||||
@ -627,7 +627,7 @@ impl<'a> Context<'a> {
|
|||||||
let mut rlibs = HashMap::new();
|
let mut rlibs = HashMap::new();
|
||||||
let mut dylibs = 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() {
|
if !loc.exists() {
|
||||||
sess.err(&format!("extern location for {} does not exist: {}",
|
sess.err(&format!("extern location for {} does not exist: {}",
|
||||||
self.crate_name, loc.display())[]);
|
self.crate_name, loc.display())[]);
|
||||||
@ -645,8 +645,8 @@ impl<'a> Context<'a> {
|
|||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
let (ref prefix, ref suffix) = dylibname;
|
let (ref prefix, ref suffix) = dylibname;
|
||||||
if file.starts_with(&prefix[]) &&
|
if file.starts_with(&prefix[..]) &&
|
||||||
file.ends_with(&suffix[]) {
|
file.ends_with(&suffix[..]) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -744,7 +744,7 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
let buf = CString::from_slice(filename.as_vec());
|
let buf = CString::new(filename.as_vec()).unwrap();
|
||||||
let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
|
let mb = llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf.as_ptr());
|
||||||
if mb as int == 0 {
|
if mb as int == 0 {
|
||||||
return Err(format!("error reading library: '{}'",
|
return Err(format!("error reading library: '{}'",
|
||||||
|
@ -641,7 +641,7 @@ fn parse_abi_set(st: &mut PState) -> abi::Abi {
|
|||||||
assert_eq!(next(st), '[');
|
assert_eq!(next(st), '[');
|
||||||
scan(st, |c| c == ']', |bytes| {
|
scan(st, |c| c == ']', |bytes| {
|
||||||
let abi_str = str::from_utf8(bytes).unwrap();
|
let abi_str = str::from_utf8(bytes).unwrap();
|
||||||
abi::lookup(&abi_str[]).expect(abi_str)
|
abi::lookup(&abi_str[..]).expect(abi_str)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.
|
// Do an Option dance to use the path after it is moved below.
|
||||||
let s = ast_map::path_to_string(path.iter().cloned());
|
let s = ast_map::path_to_string(path.iter().cloned());
|
||||||
path_as_str = Some(s);
|
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 mut ast_dsr = reader::Decoder::new(ast_doc);
|
||||||
let from_id_range = Decodable::decode(&mut ast_dsr).unwrap();
|
let from_id_range = Decodable::decode(&mut ast_dsr).unwrap();
|
||||||
|
@ -92,7 +92,7 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
|
|||||||
let s = replace_newline_with_backslash_l(s);
|
let s = replace_newline_with_backslash_l(s);
|
||||||
label.push_str(&format!("exiting scope_{} {}",
|
label.push_str(&format!("exiting scope_{} {}",
|
||||||
i,
|
i,
|
||||||
&s[])[]);
|
&s[..])[]);
|
||||||
}
|
}
|
||||||
dot::LabelText::EscStr(label.into_cow())
|
dot::LabelText::EscStr(label.into_cow())
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ use middle::ty::*;
|
|||||||
use middle::ty;
|
use middle::ty;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::fmt;
|
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::num::Float;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat};
|
use syntax::ast::{self, DUMMY_NODE_ID, NodeId, Pat};
|
||||||
@ -76,7 +76,7 @@ impl<'a> fmt::Debug for Matrix<'a> {
|
|||||||
pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0)
|
pretty_printed_matrix.iter().map(|row| row[col].len()).max().unwrap_or(0)
|
||||||
}).collect();
|
}).collect();
|
||||||
|
|
||||||
let total_width = column_widths.iter().map(|n| *n).sum() + column_count * 3 + 1;
|
let total_width = column_widths.iter().cloned().sum() + column_count * 3 + 1;
|
||||||
let br = repeat('+').take(total_width).collect::<String>();
|
let br = repeat('+').take(total_width).collect::<String>();
|
||||||
try!(write!(f, "{}\n", br));
|
try!(write!(f, "{}\n", br));
|
||||||
for row in pretty_printed_matrix {
|
for row in pretty_printed_matrix {
|
||||||
@ -94,8 +94,8 @@ impl<'a> fmt::Debug for Matrix<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FromIterator<Vec<&'a Pat>> for Matrix<'a> {
|
impl<'a> FromIterator<Vec<&'a Pat>> for Matrix<'a> {
|
||||||
fn from_iter<T: Iterator<Item=Vec<&'a Pat>>>(iterator: T) -> Matrix<'a> {
|
fn from_iter<T: IntoIterator<Item=Vec<&'a Pat>>>(iter: T) -> Matrix<'a> {
|
||||||
Matrix(iterator.collect())
|
Matrix(iter.into_iter().collect())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +200,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Fourth, check for unreachable arms.
|
// 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.
|
// Finally, check if the whole match expression is exhaustive.
|
||||||
// Check for empty enum, because is_useful only works on inhabited types.
|
// 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 {
|
for pat in pats {
|
||||||
let v = vec![&**pat];
|
let v = vec![&**pat];
|
||||||
|
|
||||||
match is_useful(cx, &seen, &v[], LeaveOutWitness) {
|
match is_useful(cx, &seen, &v[..], LeaveOutWitness) {
|
||||||
NotUseful => {
|
NotUseful => {
|
||||||
match source {
|
match source {
|
||||||
ast::MatchSource::IfLetDesugar { .. } => {
|
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) {
|
fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: ast::MatchSource) {
|
||||||
match is_useful(cx, matrix, &[DUMMY_WILD_PAT], ConstructWitness) {
|
match is_useful(cx, matrix, &[DUMMY_WILD_PAT], ConstructWitness) {
|
||||||
UsefulWithWitness(pats) => {
|
UsefulWithWitness(pats) => {
|
||||||
let witness = match &pats[] {
|
let witness = match &pats[..] {
|
||||||
[ref witness] => &**witness,
|
[ref witness] => &**witness,
|
||||||
[] => DUMMY_WILD_PAT,
|
[] => DUMMY_WILD_PAT,
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
@ -360,7 +360,7 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix, source: ast:
|
|||||||
ast::MatchSource::ForLoopDesugar => {
|
ast::MatchSource::ForLoopDesugar => {
|
||||||
// `witness` has the form `Some(<head>)`, peel off the `Some`
|
// `witness` has the form `Some(<head>)`, peel off the `Some`
|
||||||
let witness = match witness.node {
|
let witness = match witness.node {
|
||||||
ast::PatEnum(_, Some(ref pats)) => match &pats[] {
|
ast::PatEnum(_, Some(ref pats)) => match &pats[..] {
|
||||||
[ref pat] => &**pat,
|
[ref pat] => &**pat,
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
@ -664,7 +664,7 @@ fn is_useful(cx: &MatchCheckCtxt,
|
|||||||
UsefulWithWitness(pats) => UsefulWithWitness({
|
UsefulWithWitness(pats) => UsefulWithWitness({
|
||||||
let arity = constructor_arity(cx, &c, left_ty);
|
let arity = constructor_arity(cx, &c, left_ty);
|
||||||
let mut result = {
|
let mut result = {
|
||||||
let pat_slice = &pats[];
|
let pat_slice = &pats[..];
|
||||||
let subpats: Vec<_> = (0..arity).map(|i| {
|
let subpats: Vec<_> = (0..arity).map(|i| {
|
||||||
pat_slice.get(i).map_or(DUMMY_WILD_PAT, |p| &**p)
|
pat_slice.get(i).map_or(DUMMY_WILD_PAT, |p| &**p)
|
||||||
}).collect();
|
}).collect();
|
||||||
@ -711,10 +711,10 @@ fn is_useful_specialized(cx: &MatchCheckCtxt, &Matrix(ref m): &Matrix,
|
|||||||
witness: WitnessPreference) -> Usefulness {
|
witness: WitnessPreference) -> Usefulness {
|
||||||
let arity = constructor_arity(cx, &ctor, lty);
|
let arity = constructor_arity(cx, &ctor, lty);
|
||||||
let matrix = Matrix(m.iter().filter_map(|r| {
|
let matrix = Matrix(m.iter().filter_map(|r| {
|
||||||
specialize(cx, &r[], &ctor, 0, arity)
|
specialize(cx, &r[..], &ctor, 0, arity)
|
||||||
}).collect());
|
}).collect());
|
||||||
match specialize(cx, v, &ctor, 0, arity) {
|
match specialize(cx, v, &ctor, 0, arity) {
|
||||||
Some(v) => is_useful(cx, &matrix, &v[], witness),
|
Some(v) => is_useful(cx, &matrix, &v[..], witness),
|
||||||
None => NotUseful
|
None => NotUseful
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ fn lookup_variant_by_id<'a>(tcx: &'a ty::ctxt,
|
|||||||
None => None,
|
None => None,
|
||||||
Some(ast_map::NodeItem(it)) => match it.node {
|
Some(ast_map::NodeItem(it)) => match it.node {
|
||||||
ast::ItemEnum(ast::EnumDef { ref variants }, _) => {
|
ast::ItemEnum(ast::EnumDef { ref variants }, _) => {
|
||||||
variant_expr(&variants[], variant_def.node)
|
variant_expr(&variants[..], variant_def.node)
|
||||||
}
|
}
|
||||||
_ => None
|
_ => None
|
||||||
},
|
},
|
||||||
@ -83,7 +83,7 @@ fn lookup_variant_by_id<'a>(tcx: &'a ty::ctxt,
|
|||||||
// NOTE this doesn't do the right thing, it compares inlined
|
// NOTE this doesn't do the right thing, it compares inlined
|
||||||
// NodeId's to the original variant_def's NodeId, but they
|
// NodeId's to the original variant_def's NodeId, but they
|
||||||
// come from different crates, so they will likely never match.
|
// 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
|
_ => None
|
||||||
},
|
},
|
||||||
@ -209,7 +209,7 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
|
|||||||
pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val {
|
pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val {
|
||||||
match eval_const_expr_partial(tcx, e, None) {
|
match eval_const_expr_partial(tcx, e, None) {
|
||||||
Ok(r) => r,
|
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<Ty>) -> const_val {
|
|||||||
match lit.node {
|
match lit.node {
|
||||||
ast::LitStr(ref s, _) => const_str((*s).clone()),
|
ast::LitStr(ref s, _) => const_str((*s).clone()),
|
||||||
ast::LitBinary(ref data) => {
|
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::LitByte(n) => const_uint(n as u64),
|
||||||
ast::LitChar(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) {
|
let a = match eval_const_expr_partial(tcx, a, ty_hint) {
|
||||||
Ok(a) => a,
|
Ok(a) => a,
|
||||||
Err(s) => {
|
Err(s) => {
|
||||||
tcx.sess.span_err(a.span, &s[]);
|
tcx.sess.span_err(a.span, &s[..]);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let b = match eval_const_expr_partial(tcx, b, ty_hint) {
|
let b = match eval_const_expr_partial(tcx, b, ty_hint) {
|
||||||
Ok(b) => b,
|
Ok(b) => b,
|
||||||
Err(s) => {
|
Err(s) => {
|
||||||
tcx.sess.span_err(b.span, &s[]);
|
tcx.sess.span_err(b.span, &s[..]);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -89,7 +89,7 @@ struct PropagationContext<'a, 'b: 'a, 'tcx: 'b, O: 'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn to_cfgidx_or_die(id: ast::NodeId, index: &NodeMap<CFGIndex>) -> CFGIndex {
|
fn to_cfgidx_or_die(id: ast::NodeId, index: &NodeMap<CFGIndex>) -> CFGIndex {
|
||||||
let opt_cfgindex = index.get(&id).map(|&i|i);
|
let opt_cfgindex = index.get(&id).cloned();
|
||||||
opt_cfgindex.unwrap_or_else(|| {
|
opt_cfgindex.unwrap_or_else(|| {
|
||||||
panic!("nodeid_to_index does not have entry for NodeId {}", id);
|
panic!("nodeid_to_index does not have entry for NodeId {}", id);
|
||||||
})
|
})
|
||||||
@ -312,7 +312,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
|
|||||||
let mut t = on_entry.to_vec();
|
let mut t = on_entry.to_vec();
|
||||||
self.apply_gen_kill(cfgidx, &mut t);
|
self.apply_gen_kill(cfgidx, &mut t);
|
||||||
temp_bits = t;
|
temp_bits = t;
|
||||||
&temp_bits[]
|
&temp_bits[..]
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
debug!("{} each_bit_for_node({:?}, cfgidx={:?}) bits={}",
|
debug!("{} each_bit_for_node({:?}, cfgidx={:?}) bits={}",
|
||||||
@ -400,7 +400,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
|
|||||||
|
|
||||||
let mut changed = false;
|
let mut changed = false;
|
||||||
for &node_id in &edge.data.exiting_scopes {
|
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 {
|
match opt_cfg_idx {
|
||||||
Some(cfg_idx) => {
|
Some(cfg_idx) => {
|
||||||
let (start, end) = self.compute_id_range(cfg_idx);
|
let (start, end) = self.compute_id_range(cfg_idx);
|
||||||
@ -421,7 +421,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
|
|||||||
let bits = &mut self.kills[start.. end];
|
let bits = &mut self.kills[start.. end];
|
||||||
debug!("{} add_kills_from_flow_exits flow_exit={:?} bits={} [before]",
|
debug!("{} add_kills_from_flow_exits flow_exit={:?} bits={} [before]",
|
||||||
self.analysis_name, flow_exit, mut_bits_to_string(bits));
|
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]",
|
debug!("{} add_kills_from_flow_exits flow_exit={:?} bits={} [after]",
|
||||||
self.analysis_name, flow_exit, mut_bits_to_string(bits));
|
self.analysis_name, flow_exit, mut_bits_to_string(bits));
|
||||||
}
|
}
|
||||||
|
@ -321,7 +321,7 @@ fn has_allow_dead_code_or_lang_attr(attrs: &[ast::Attribute]) -> bool {
|
|||||||
for attr in lint::gather_attrs(attrs) {
|
for attr in lint::gather_attrs(attrs) {
|
||||||
match attr {
|
match attr {
|
||||||
Ok((ref name, lint::Allow, _))
|
Ok((ref name, lint::Allow, _))
|
||||||
if &name[] == dead_code => return true,
|
if &name[..] == dead_code => return true,
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -158,7 +158,7 @@ fn calculate_type(sess: &session::Session,
|
|||||||
|
|
||||||
// Collect what we've got so far in the return vector.
|
// Collect what we've got so far in the return vector.
|
||||||
let mut ret = (1..sess.cstore.next_crate_num()).map(|i| {
|
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,
|
v @ Some(cstore::RequireDynamic) => v,
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@ use middle::ty::{MethodOrigin, MethodParam, MethodTypeParam};
|
|||||||
use middle::ty::{MethodStatic, MethodStaticClosure};
|
use middle::ty::{MethodStatic, MethodStaticClosure};
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
|
|
||||||
use std::marker;
|
|
||||||
use syntax::{ast, ast_util};
|
use syntax::{ast, ast_util};
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
@ -128,16 +127,14 @@ pub enum MatchMode {
|
|||||||
MovingMatch,
|
MovingMatch,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq,Debug)]
|
#[derive(Copy, PartialEq, Debug)]
|
||||||
enum TrackMatchMode<T> {
|
enum TrackMatchMode {
|
||||||
Unknown,
|
Unknown,
|
||||||
Definite(MatchMode),
|
Definite(MatchMode),
|
||||||
Conflicting,
|
Conflicting,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> marker::Copy for TrackMatchMode<T> {}
|
impl TrackMatchMode {
|
||||||
|
|
||||||
impl<T> TrackMatchMode<T> {
|
|
||||||
// Builds up the whole match mode for a pattern from its constituent
|
// Builds up the whole match mode for a pattern from its constituent
|
||||||
// parts. The lattice looks like this:
|
// parts. The lattice looks like this:
|
||||||
//
|
//
|
||||||
@ -931,7 +928,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &ast::Arm) -> TrackMatchMode<Span> {
|
fn arm_move_mode(&mut self, discr_cmt: mc::cmt<'tcx>, arm: &ast::Arm) -> TrackMatchMode {
|
||||||
let mut mode = Unknown;
|
let mut mode = Unknown;
|
||||||
for pat in &arm.pats {
|
for pat in &arm.pats {
|
||||||
self.determine_pat_move_mode(discr_cmt.clone(), &**pat, &mut mode);
|
self.determine_pat_move_mode(discr_cmt.clone(), &**pat, &mut mode);
|
||||||
@ -966,7 +963,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
|||||||
fn determine_pat_move_mode(&mut self,
|
fn determine_pat_move_mode(&mut self,
|
||||||
cmt_discr: mc::cmt<'tcx>,
|
cmt_discr: mc::cmt<'tcx>,
|
||||||
pat: &ast::Pat,
|
pat: &ast::Pat,
|
||||||
mode: &mut TrackMatchMode<Span>) {
|
mode: &mut TrackMatchMode) {
|
||||||
debug!("determine_pat_move_mode cmt_discr={} pat={}", cmt_discr.repr(self.tcx()),
|
debug!("determine_pat_move_mode cmt_discr={} pat={}", cmt_discr.repr(self.tcx()),
|
||||||
pat.repr(self.tcx()));
|
pat.repr(self.tcx()));
|
||||||
return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| {
|
return_if_err!(self.mc.cat_pattern(cmt_discr, pat, |_mc, cmt_pat, pat| {
|
||||||
@ -1166,7 +1163,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
|||||||
let msg = format!("Pattern has unexpected def: {:?} and type {}",
|
let msg = format!("Pattern has unexpected def: {:?} and type {}",
|
||||||
def,
|
def,
|
||||||
cmt_pat.ty.repr(tcx));
|
cmt_pat.ty.repr(tcx));
|
||||||
tcx.sess.span_bug(pat.span, &msg[])
|
tcx.sess.span_bug(pat.span, &msg[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
use std::fmt::{Formatter, Error, Debug};
|
use std::fmt::{Formatter, Error, Debug};
|
||||||
use std::usize;
|
use std::usize;
|
||||||
use std::collections::BitvSet;
|
use std::collections::BitSet;
|
||||||
|
|
||||||
pub struct Graph<N,E> {
|
pub struct Graph<N,E> {
|
||||||
nodes: Vec<Node<N>> ,
|
nodes: Vec<Node<N>> ,
|
||||||
@ -292,7 +292,7 @@ impl<N,E> Graph<N,E> {
|
|||||||
DepthFirstTraversal {
|
DepthFirstTraversal {
|
||||||
graph: self,
|
graph: self,
|
||||||
stack: vec![start],
|
stack: vec![start],
|
||||||
visited: BitvSet::new()
|
visited: BitSet::new()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -300,7 +300,7 @@ impl<N,E> Graph<N,E> {
|
|||||||
pub struct DepthFirstTraversal<'g, N:'g, E:'g> {
|
pub struct DepthFirstTraversal<'g, N:'g, E:'g> {
|
||||||
graph: &'g Graph<N, E>,
|
graph: &'g Graph<N, E>,
|
||||||
stack: Vec<NodeIndex>,
|
stack: Vec<NodeIndex>,
|
||||||
visited: BitvSet
|
visited: BitSet
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'g, N, E> Iterator for DepthFirstTraversal<'g, N, E> {
|
impl<'g, N, E> Iterator for DepthFirstTraversal<'g, N, E> {
|
||||||
|
145
src/librustc/middle/infer/bivariate.rs
Normal file
145
src/librustc/middle/infer/bivariate.rs
Normal file
@ -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 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
//! Applies the "bivariance relationship" to two types and/or regions.
|
||||||
|
//! If (A,B) are bivariant then either A <: B or B <: A. It occurs
|
||||||
|
//! when type/lifetime parameters are unconstrained. Usually this is
|
||||||
|
//! an error, but we permit it in the specific case where a type
|
||||||
|
//! parameter is constrained in a where-clause via an associated type.
|
||||||
|
//!
|
||||||
|
//! There are several ways one could implement bivariance. You could
|
||||||
|
//! just do nothing at all, for example, or you could fully verify
|
||||||
|
//! that one of the two subtyping relationships hold. We choose to
|
||||||
|
//! thread a middle line: we relate types up to regions, but ignore
|
||||||
|
//! all region relationships.
|
||||||
|
//!
|
||||||
|
//! At one point, handling bivariance in this fashion was necessary
|
||||||
|
//! for inference, but I'm actually not sure if that is true anymore.
|
||||||
|
//! In particular, it might be enough to say (A,B) are bivariant for
|
||||||
|
//! all (A,B).
|
||||||
|
|
||||||
|
use middle::ty::{BuiltinBounds};
|
||||||
|
use middle::ty::{self, Ty};
|
||||||
|
use middle::ty::TyVar;
|
||||||
|
use middle::infer::combine::*;
|
||||||
|
use middle::infer::{cres};
|
||||||
|
use middle::infer::type_variable::{BiTo};
|
||||||
|
use util::ppaux::{Repr};
|
||||||
|
|
||||||
|
use syntax::ast::{Unsafety};
|
||||||
|
|
||||||
|
pub struct Bivariate<'f, 'tcx: 'f> {
|
||||||
|
fields: CombineFields<'f, 'tcx>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
pub fn Bivariate<'f, 'tcx>(cf: CombineFields<'f, 'tcx>) -> Bivariate<'f, 'tcx> {
|
||||||
|
Bivariate { fields: cf }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'f, 'tcx> Combine<'tcx> for Bivariate<'f, 'tcx> {
|
||||||
|
fn tag(&self) -> String { "Bivariate".to_string() }
|
||||||
|
fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
|
||||||
|
|
||||||
|
fn tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
|
||||||
|
-> cres<'tcx, Ty<'tcx>>
|
||||||
|
{
|
||||||
|
match v {
|
||||||
|
ty::Invariant => self.equate().tys(a, b),
|
||||||
|
ty::Covariant => self.tys(a, b),
|
||||||
|
ty::Contravariant => self.tys(a, b),
|
||||||
|
ty::Bivariant => self.tys(a, b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
|
||||||
|
-> cres<'tcx, ty::Region>
|
||||||
|
{
|
||||||
|
match v {
|
||||||
|
ty::Invariant => self.equate().regions(a, b),
|
||||||
|
ty::Covariant => self.regions(a, b),
|
||||||
|
ty::Contravariant => self.regions(a, b),
|
||||||
|
ty::Bivariant => self.regions(a, b),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn regions(&self, a: ty::Region, _: ty::Region) -> cres<'tcx, ty::Region> {
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> {
|
||||||
|
debug!("mts({} <: {})",
|
||||||
|
a.repr(self.fields.infcx.tcx),
|
||||||
|
b.repr(self.fields.infcx.tcx));
|
||||||
|
|
||||||
|
if a.mutbl != b.mutbl { return Err(ty::terr_mutability); }
|
||||||
|
let t = try!(self.tys(a.ty, b.ty));
|
||||||
|
Ok(ty::mt { mutbl: a.mutbl, ty: t })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> {
|
||||||
|
if a != b {
|
||||||
|
Err(ty::terr_unsafety_mismatch(expected_found(self, a, b)))
|
||||||
|
} else {
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn builtin_bounds(&self,
|
||||||
|
a: BuiltinBounds,
|
||||||
|
b: BuiltinBounds)
|
||||||
|
-> cres<'tcx, BuiltinBounds>
|
||||||
|
{
|
||||||
|
if a != b {
|
||||||
|
Err(ty::terr_builtin_bounds(expected_found(self, a, b)))
|
||||||
|
} else {
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
|
||||||
|
debug!("{}.tys({}, {})", self.tag(),
|
||||||
|
a.repr(self.fields.infcx.tcx), b.repr(self.fields.infcx.tcx));
|
||||||
|
if a == b { return Ok(a); }
|
||||||
|
|
||||||
|
let infcx = self.fields.infcx;
|
||||||
|
let a = infcx.type_variables.borrow().replace_if_possible(a);
|
||||||
|
let b = infcx.type_variables.borrow().replace_if_possible(b);
|
||||||
|
match (&a.sty, &b.sty) {
|
||||||
|
(&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => {
|
||||||
|
infcx.type_variables.borrow_mut().relate_vars(a_id, BiTo, b_id);
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
(&ty::ty_infer(TyVar(a_id)), _) => {
|
||||||
|
try!(self.fields.instantiate(b, BiTo, a_id));
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
(_, &ty::ty_infer(TyVar(b_id))) => {
|
||||||
|
try!(self.fields.instantiate(a, BiTo, b_id));
|
||||||
|
Ok(a)
|
||||||
|
}
|
||||||
|
|
||||||
|
_ => {
|
||||||
|
super_tys(self, a, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn binders<T>(&self, a: &ty::Binder<T>, b: &ty::Binder<T>) -> cres<'tcx, ty::Binder<T>>
|
||||||
|
where T : Combineable<'tcx>
|
||||||
|
{
|
||||||
|
let a1 = ty::erase_late_bound_regions(self.tcx(), a);
|
||||||
|
let b1 = ty::erase_late_bound_regions(self.tcx(), b);
|
||||||
|
let c = try!(Combineable::combine(self, &a1, &b1));
|
||||||
|
Ok(ty::Binder(c))
|
||||||
|
}
|
||||||
|
}
|
@ -32,6 +32,7 @@
|
|||||||
// is also useful to track which value is the "expected" value in
|
// is also useful to track which value is the "expected" value in
|
||||||
// terms of error reporting.
|
// terms of error reporting.
|
||||||
|
|
||||||
|
use super::bivariate::Bivariate;
|
||||||
use super::equate::Equate;
|
use super::equate::Equate;
|
||||||
use super::glb::Glb;
|
use super::glb::Glb;
|
||||||
use super::lub::Lub;
|
use super::lub::Lub;
|
||||||
@ -39,7 +40,7 @@ use super::sub::Sub;
|
|||||||
use super::unify::InferCtxtMethodsForSimplyUnifiableTypes;
|
use super::unify::InferCtxtMethodsForSimplyUnifiableTypes;
|
||||||
use super::{InferCtxt, cres};
|
use super::{InferCtxt, cres};
|
||||||
use super::{MiscVariable, TypeTrace};
|
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;
|
||||||
use middle::subst::{ErasedRegions, NonerasedRegions, Substs};
|
use middle::subst::{ErasedRegions, NonerasedRegions, Substs};
|
||||||
@ -48,7 +49,7 @@ use middle::ty::{IntType, UintType};
|
|||||||
use middle::ty::{BuiltinBounds};
|
use middle::ty::{BuiltinBounds};
|
||||||
use middle::ty::{self, Ty};
|
use middle::ty::{self, Ty};
|
||||||
use middle::ty_fold;
|
use middle::ty_fold;
|
||||||
use middle::ty_fold::{TypeFoldable};
|
use middle::ty_fold::{TypeFolder, TypeFoldable};
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
|
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -58,41 +59,32 @@ use syntax::abi;
|
|||||||
use syntax::codemap::Span;
|
use syntax::codemap::Span;
|
||||||
|
|
||||||
pub trait Combine<'tcx> : Sized {
|
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 tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.infcx().tcx }
|
||||||
fn tag(&self) -> String;
|
fn tag(&self) -> String;
|
||||||
fn a_is_expected(&self) -> bool;
|
|
||||||
fn trace(&self) -> TypeTrace<'tcx>;
|
|
||||||
|
|
||||||
fn equate<'a>(&'a self) -> Equate<'a, 'tcx>;
|
fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx>;
|
||||||
fn sub<'a>(&'a self) -> Sub<'a, 'tcx>;
|
|
||||||
fn lub<'a>(&'a self) -> Lub<'a, 'tcx>;
|
fn infcx<'a>(&'a self) -> &'a InferCtxt<'a, 'tcx> { self.fields().infcx }
|
||||||
fn glb<'a>(&'a self) -> Glb<'a, 'tcx>;
|
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 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 tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>>;
|
||||||
|
|
||||||
fn tps(&self,
|
fn regions_with_variance(&self, variance: ty::Variance, a: ty::Region, b: ty::Region)
|
||||||
_: subst::ParamSpace,
|
-> cres<'tcx, ty::Region>;
|
||||||
as_: &[Ty<'tcx>],
|
|
||||||
bs: &[Ty<'tcx>])
|
|
||||||
-> cres<'tcx, Vec<Ty<'tcx>>> {
|
|
||||||
// FIXME -- In general, we treat variance a bit wrong
|
|
||||||
// here. For historical reasons, we treat tps and Self
|
|
||||||
// as invariant. This is overly conservative.
|
|
||||||
|
|
||||||
if as_.len() != bs.len() {
|
fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region>;
|
||||||
return Err(ty::terr_ty_param_size(expected_found(self,
|
|
||||||
as_.len(),
|
|
||||||
bs.len())));
|
|
||||||
}
|
|
||||||
|
|
||||||
try!(as_.iter().zip(bs.iter())
|
|
||||||
.map(|(a, b)| self.equate().tys(*a, *b))
|
|
||||||
.collect::<cres<Vec<Ty>>>());
|
|
||||||
Ok(as_.to_vec())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn substs(&self,
|
fn substs(&self,
|
||||||
item_def_id: ast::DefId,
|
item_def_id: ast::DefId,
|
||||||
@ -100,6 +92,11 @@ pub trait Combine<'tcx> : Sized {
|
|||||||
b_subst: &subst::Substs<'tcx>)
|
b_subst: &subst::Substs<'tcx>)
|
||||||
-> cres<'tcx, 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() {
|
let variances = if self.infcx().tcx.variance_computed.get() {
|
||||||
Some(ty::item_variances(self.infcx().tcx, item_def_id))
|
Some(ty::item_variances(self.infcx().tcx, item_def_id))
|
||||||
} else {
|
} else {
|
||||||
@ -119,7 +116,8 @@ pub trait Combine<'tcx> : Sized {
|
|||||||
for &space in &subst::ParamSpace::all() {
|
for &space in &subst::ParamSpace::all() {
|
||||||
let a_tps = a_subst.types.get_slice(space);
|
let a_tps = a_subst.types.get_slice(space);
|
||||||
let b_tps = b_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);
|
substs.types.replace(space, tps);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -132,20 +130,7 @@ pub trait Combine<'tcx> : Sized {
|
|||||||
for &space in &subst::ParamSpace::all() {
|
for &space in &subst::ParamSpace::all() {
|
||||||
let a_regions = a.get_slice(space);
|
let a_regions = a.get_slice(space);
|
||||||
let b_regions = b.get_slice(space);
|
let b_regions = b.get_slice(space);
|
||||||
|
let r_variances = variances.map(|v| v.regions.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 regions = try!(relate_region_params(self,
|
let regions = try!(relate_region_params(self,
|
||||||
r_variances,
|
r_variances,
|
||||||
a_regions,
|
a_regions,
|
||||||
@ -157,13 +142,34 @@ pub trait Combine<'tcx> : Sized {
|
|||||||
|
|
||||||
return Ok(substs);
|
return Ok(substs);
|
||||||
|
|
||||||
|
fn relate_type_params<'tcx, C: Combine<'tcx>>(this: &C,
|
||||||
|
variances: Option<&[ty::Variance]>,
|
||||||
|
a_tys: &[Ty<'tcx>],
|
||||||
|
b_tys: &[Ty<'tcx>])
|
||||||
|
-> cres<'tcx, Vec<Ty<'tcx>>>
|
||||||
|
{
|
||||||
|
if a_tys.len() != b_tys.len() {
|
||||||
|
return Err(ty::terr_ty_param_size(expected_found(this,
|
||||||
|
a_tys.len(),
|
||||||
|
b_tys.len())));
|
||||||
|
}
|
||||||
|
|
||||||
|
range(0, a_tys.len()).map(|i| {
|
||||||
|
let a_ty = a_tys[i];
|
||||||
|
let b_ty = b_tys[i];
|
||||||
|
let v = variances.map_or(ty::Invariant, |v| v[i]);
|
||||||
|
this.tys_with_variance(v, a_ty, b_ty)
|
||||||
|
}).collect()
|
||||||
|
}
|
||||||
|
|
||||||
fn relate_region_params<'tcx, C: Combine<'tcx>>(this: &C,
|
fn relate_region_params<'tcx, C: Combine<'tcx>>(this: &C,
|
||||||
variances: &[ty::Variance],
|
variances: Option<&[ty::Variance]>,
|
||||||
a_rs: &[ty::Region],
|
a_rs: &[ty::Region],
|
||||||
b_rs: &[ty::Region])
|
b_rs: &[ty::Region])
|
||||||
-> cres<'tcx, Vec<ty::Region>> {
|
-> cres<'tcx, Vec<ty::Region>>
|
||||||
|
{
|
||||||
let tcx = this.infcx().tcx;
|
let tcx = this.infcx().tcx;
|
||||||
let num_region_params = variances.len();
|
let num_region_params = a_rs.len();
|
||||||
|
|
||||||
debug!("relate_region_params(\
|
debug!("relate_region_params(\
|
||||||
a_rs={}, \
|
a_rs={}, \
|
||||||
@ -173,22 +179,18 @@ pub trait Combine<'tcx> : Sized {
|
|||||||
b_rs.repr(tcx),
|
b_rs.repr(tcx),
|
||||||
variances.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());
|
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 a_r = a_rs[i];
|
||||||
let b_r = b_rs[i];
|
let b_r = b_rs[i];
|
||||||
let variance = variances[i];
|
let variance = variances.map_or(ty::Invariant, |v| v[i]);
|
||||||
let r = match variance {
|
this.regions_with_variance(variance, a_r, b_r)
|
||||||
ty::Invariant => this.equate().regions(a_r, b_r),
|
}).collect()
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,7 +243,7 @@ pub trait Combine<'tcx> : Sized {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn args(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
|
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>;
|
fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety>;
|
||||||
@ -309,7 +311,7 @@ pub trait Combine<'tcx> : Sized {
|
|||||||
b: &ty::ExistentialBounds<'tcx>)
|
b: &ty::ExistentialBounds<'tcx>)
|
||||||
-> cres<'tcx, 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 nb = try!(self.builtin_bounds(a.builtin_bounds, b.builtin_bounds));
|
||||||
let pb = try!(self.projection_bounds(&a.projection_bounds, &b.projection_bounds));
|
let pb = try!(self.projection_bounds(&a.projection_bounds, &b.projection_bounds));
|
||||||
Ok(ty::ExistentialBounds { region_bound: r,
|
Ok(ty::ExistentialBounds { region_bound: r,
|
||||||
@ -322,11 +324,6 @@ pub trait Combine<'tcx> : Sized {
|
|||||||
b: ty::BuiltinBounds)
|
b: ty::BuiltinBounds)
|
||||||
-> cres<'tcx, 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,
|
fn trait_refs(&self,
|
||||||
a: &ty::TraitRef<'tcx>,
|
a: &ty::TraitRef<'tcx>,
|
||||||
b: &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)) => {
|
(&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
|
// FIXME(14985) If we have mutable references to trait objects, we
|
||||||
// used to use covariant subtyping. I have preserved this behaviour,
|
// used to use covariant subtyping. I have preserved this behaviour,
|
||||||
// even though it is probably incorrect. So don't go down the usual
|
// even though it is probably incorrect. So don't go down the usual
|
||||||
@ -644,6 +642,10 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> {
|
|||||||
Equate((*self).clone())
|
Equate((*self).clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn bivariate(&self) -> Bivariate<'f, 'tcx> {
|
||||||
|
Bivariate((*self).clone())
|
||||||
|
}
|
||||||
|
|
||||||
fn sub(&self) -> Sub<'f, 'tcx> {
|
fn sub(&self) -> Sub<'f, 'tcx> {
|
||||||
Sub((*self).clone())
|
Sub((*self).clone())
|
||||||
}
|
}
|
||||||
@ -697,7 +699,7 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> {
|
|||||||
EqTo => {
|
EqTo => {
|
||||||
self.generalize(a_ty, b_vid, false)
|
self.generalize(a_ty, b_vid, false)
|
||||||
}
|
}
|
||||||
SupertypeOf | SubtypeOf => {
|
BiTo | SupertypeOf | SubtypeOf => {
|
||||||
self.generalize(a_ty, b_vid, true)
|
self.generalize(a_ty, b_vid, true)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -721,6 +723,10 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> {
|
|||||||
// to associate causes/spans with each of the relations in
|
// to associate causes/spans with each of the relations in
|
||||||
// the stack to get this right.
|
// the stack to get this right.
|
||||||
match dir {
|
match dir {
|
||||||
|
BiTo => {
|
||||||
|
try!(self.bivariate().tys(a_ty, b_ty));
|
||||||
|
}
|
||||||
|
|
||||||
EqTo => {
|
EqTo => {
|
||||||
try!(self.equate().tys(a_ty, b_ty));
|
try!(self.equate().tys(a_ty, b_ty));
|
||||||
}
|
}
|
||||||
@ -730,7 +736,7 @@ impl<'f, 'tcx> CombineFields<'f, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SupertypeOf => {
|
SupertypeOf => {
|
||||||
try!(self.sub().contratys(a_ty, b_ty));
|
try!(self.sub().tys_with_variance(ty::Contravariant, a_ty, b_ty));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,7 @@ use middle::ty::{self, Ty};
|
|||||||
use middle::ty::TyVar;
|
use middle::ty::TyVar;
|
||||||
use middle::infer::combine::*;
|
use middle::infer::combine::*;
|
||||||
use middle::infer::{cres};
|
use middle::infer::{cres};
|
||||||
use middle::infer::glb::Glb;
|
use middle::infer::{Subtype};
|
||||||
use middle::infer::InferCtxt;
|
|
||||||
use middle::infer::lub::Lub;
|
|
||||||
use middle::infer::sub::Sub;
|
|
||||||
use middle::infer::{TypeTrace, Subtype};
|
|
||||||
use middle::infer::type_variable::{EqTo};
|
use middle::infer::type_variable::{EqTo};
|
||||||
use util::ppaux::{Repr};
|
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> {
|
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 { "Equate".to_string() }
|
||||||
fn tag(&self) -> String { "eq".to_string() }
|
fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
|
||||||
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 tys_with_variance(&self, _: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
|
||||||
fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { Sub(self.fields.clone()) }
|
-> cres<'tcx, Ty<'tcx>>
|
||||||
fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) }
|
{
|
||||||
fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) }
|
// Once we're equating, it doesn't matter what the variance is.
|
||||||
|
|
||||||
fn contratys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
|
|
||||||
self.tys(a, b)
|
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)
|
self.regions(a, b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -200,9 +200,9 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
ref trace_origins,
|
ref trace_origins,
|
||||||
ref same_regions) => {
|
ref same_regions) => {
|
||||||
if !same_regions.is_empty() {
|
if !same_regions.is_empty() {
|
||||||
self.report_processed_errors(&var_origins[],
|
self.report_processed_errors(&var_origins[..],
|
||||||
&trace_origins[],
|
&trace_origins[..],
|
||||||
&same_regions[]);
|
&same_regions[..]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -675,6 +675,17 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
sup,
|
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) => {
|
infer::AddrOf(span) => {
|
||||||
self.tcx.sess.span_err(
|
self.tcx.sess.span_err(
|
||||||
span,
|
span,
|
||||||
@ -824,7 +835,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
let parent = self.tcx.map.get_parent(scope_id);
|
let parent = self.tcx.map.get_parent(scope_id);
|
||||||
let parent_node = self.tcx.map.find(parent);
|
let parent_node = self.tcx.map.find(parent);
|
||||||
let taken = lifetimes_in_scope(self.tcx, scope_id);
|
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 {
|
let node_inner = match parent_node {
|
||||||
Some(ref node) => match *node {
|
Some(ref node) => match *node {
|
||||||
ast_map::NodeItem(ref item) => {
|
ast_map::NodeItem(ref item) => {
|
||||||
@ -924,7 +935,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
|
|||||||
|
|
||||||
fn rebuild(&self)
|
fn rebuild(&self)
|
||||||
-> (ast::FnDecl, Option<ast::ExplicitSelf_>, ast::Generics) {
|
-> (ast::FnDecl, Option<ast::ExplicitSelf_>, ast::Generics) {
|
||||||
let mut expl_self_opt = self.expl_self_opt.map(|x| x.clone());
|
let mut expl_self_opt = self.expl_self_opt.cloned();
|
||||||
let mut inputs = self.fn_decl.inputs.clone();
|
let mut inputs = self.fn_decl.inputs.clone();
|
||||||
let mut output = self.fn_decl.output.clone();
|
let mut output = self.fn_decl.output.clone();
|
||||||
let mut ty_params = self.generics.ty_params.clone();
|
let mut ty_params = self.generics.ty_params.clone();
|
||||||
@ -942,7 +953,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
expl_self_opt = self.rebuild_expl_self(expl_self_opt, lifetime,
|
expl_self_opt = self.rebuild_expl_self(expl_self_opt, lifetime,
|
||||||
&anon_nums, ®ion_names);
|
&anon_nums, ®ion_names);
|
||||||
inputs = self.rebuild_args_ty(&inputs[], lifetime,
|
inputs = self.rebuild_args_ty(&inputs[..], lifetime,
|
||||||
&anon_nums, ®ion_names);
|
&anon_nums, ®ion_names);
|
||||||
output = self.rebuild_output(&output, lifetime, &anon_nums, ®ion_names);
|
output = self.rebuild_output(&output, lifetime, &anon_nums, ®ion_names);
|
||||||
ty_params = self.rebuild_ty_params(ty_params, lifetime,
|
ty_params = self.rebuild_ty_params(ty_params, lifetime,
|
||||||
@ -1426,7 +1437,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
opt_explicit_self, generics);
|
opt_explicit_self, generics);
|
||||||
let msg = format!("consider using an explicit lifetime \
|
let msg = format!("consider using an explicit lifetime \
|
||||||
parameter as shown: {}", suggested_fn);
|
parameter as shown: {}", suggested_fn);
|
||||||
self.tcx.sess.span_help(span, &msg[]);
|
self.tcx.sess.span_help(span, &msg[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn report_inference_failure(&self,
|
fn report_inference_failure(&self,
|
||||||
@ -1593,6 +1604,11 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
|
|||||||
span,
|
span,
|
||||||
"...so that return value is valid for the call");
|
"...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) => {
|
infer::AddrOf(span) => {
|
||||||
self.tcx.sess.span_note(
|
self.tcx.sess.span_note(
|
||||||
span,
|
span,
|
||||||
@ -1771,7 +1787,7 @@ impl LifeGiver {
|
|||||||
s.push_str(&num_to_string(self.counter.get())[]);
|
s.push_str(&num_to_string(self.counter.get())[]);
|
||||||
if !self.taken.contains(&s) {
|
if !self.taken.contains(&s) {
|
||||||
lifetime = name_to_dummy_lifetime(
|
lifetime = name_to_dummy_lifetime(
|
||||||
token::str_to_ident(&s[]).name);
|
token::str_to_ident(&s[..]).name);
|
||||||
self.generated.borrow_mut().push(lifetime);
|
self.generated.borrow_mut().push(lifetime);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -10,12 +10,9 @@
|
|||||||
|
|
||||||
use super::combine::*;
|
use super::combine::*;
|
||||||
use super::lattice::*;
|
use super::lattice::*;
|
||||||
use super::equate::Equate;
|
|
||||||
use super::higher_ranked::HigherRankedRelations;
|
use super::higher_ranked::HigherRankedRelations;
|
||||||
use super::lub::Lub;
|
use super::{cres};
|
||||||
use super::sub::Sub;
|
use super::Subtype;
|
||||||
use super::{cres, InferCtxt};
|
|
||||||
use super::{TypeTrace, Subtype};
|
|
||||||
|
|
||||||
use middle::ty::{BuiltinBounds};
|
use middle::ty::{BuiltinBounds};
|
||||||
use middle::ty::{self, Ty};
|
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> {
|
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 tag(&self) -> String { "glb".to_string() }
|
fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
|
||||||
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 tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
|
||||||
fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { Sub(self.fields.clone()) }
|
-> cres<'tcx, Ty<'tcx>>
|
||||||
fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) }
|
{
|
||||||
fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) }
|
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>> {
|
fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> {
|
||||||
let tcx = self.fields.infcx.tcx;
|
let tcx = self.fields.infcx.tcx;
|
||||||
@ -75,10 +87,6 @@ impl<'f, 'tcx> Combine<'tcx> for Glb<'f, '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> {
|
fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> {
|
||||||
match (a, b) {
|
match (a, b) {
|
||||||
(Unsafety::Normal, _) | (_, Unsafety::Normal) => Ok(Unsafety::Normal),
|
(Unsafety::Normal, _) | (_, Unsafety::Normal) => Ok(Unsafety::Normal),
|
||||||
@ -104,11 +112,6 @@ impl<'f, 'tcx> Combine<'tcx> for Glb<'f, 'tcx> {
|
|||||||
Ok(self.fields.infcx.region_vars.glb_regions(Subtype(self.trace()), a, b))
|
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>> {
|
fn tys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
|
||||||
super_lattice_tys(self, a, b)
|
super_lattice_tys(self, a, b)
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ pub trait HigherRankedRelations<'tcx> {
|
|||||||
where T : Combineable<'tcx>;
|
where T : Combineable<'tcx>;
|
||||||
}
|
}
|
||||||
|
|
||||||
trait InferCtxtExt<'tcx> {
|
trait InferCtxtExt {
|
||||||
fn tainted_regions(&self, snapshot: &CombinedSnapshot, r: ty::Region) -> Vec<ty::Region>;
|
fn tainted_regions(&self, snapshot: &CombinedSnapshot, r: ty::Region) -> Vec<ty::Region>;
|
||||||
|
|
||||||
fn region_vars_confined_to_snapshot(&self,
|
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<ty::Region> {
|
fn tainted_regions(&self, snapshot: &CombinedSnapshot, r: ty::Region) -> Vec<ty::Region> {
|
||||||
self.region_vars.tainted(&snapshot.region_vars_snapshot, r)
|
self.region_vars.tainted(&snapshot.region_vars_snapshot, r)
|
||||||
}
|
}
|
||||||
|
@ -9,13 +9,10 @@
|
|||||||
// except according to those terms.
|
// except according to those terms.
|
||||||
|
|
||||||
use super::combine::*;
|
use super::combine::*;
|
||||||
use super::equate::Equate;
|
|
||||||
use super::glb::Glb;
|
|
||||||
use super::higher_ranked::HigherRankedRelations;
|
use super::higher_ranked::HigherRankedRelations;
|
||||||
use super::lattice::*;
|
use super::lattice::*;
|
||||||
use super::sub::Sub;
|
use super::{cres};
|
||||||
use super::{cres, InferCtxt};
|
use super::{Subtype};
|
||||||
use super::{TypeTrace, Subtype};
|
|
||||||
|
|
||||||
use middle::ty::{BuiltinBounds};
|
use middle::ty::{BuiltinBounds};
|
||||||
use middle::ty::{self, Ty};
|
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> {
|
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 tag(&self) -> String { "lub".to_string() }
|
fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
|
||||||
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 tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
|
||||||
fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { Sub(self.fields.clone()) }
|
-> cres<'tcx, Ty<'tcx>>
|
||||||
fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) }
|
{
|
||||||
fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) }
|
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>> {
|
fn mts(&self, a: &ty::mt<'tcx>, b: &ty::mt<'tcx>) -> cres<'tcx, ty::mt<'tcx>> {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
@ -70,10 +82,6 @@ impl<'f, 'tcx> Combine<'tcx> for Lub<'f, '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> {
|
fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> {
|
||||||
match (a, b) {
|
match (a, b) {
|
||||||
(Unsafety::Unsafe, _) | (_, Unsafety::Unsafe) => Ok(Unsafety::Unsafe),
|
(Unsafety::Unsafe, _) | (_, Unsafety::Unsafe) => Ok(Unsafety::Unsafe),
|
||||||
@ -90,11 +98,6 @@ impl<'f, 'tcx> Combine<'tcx> for Lub<'f, 'tcx> {
|
|||||||
Ok(a.intersection(b))
|
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> {
|
fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> {
|
||||||
debug!("{}.regions({}, {})",
|
debug!("{}.regions({}, {})",
|
||||||
self.tag(),
|
self.tag(),
|
||||||
|
@ -45,6 +45,7 @@ use self::lub::Lub;
|
|||||||
use self::unify::{UnificationTable, InferCtxtMethodsForSimplyUnifiableTypes};
|
use self::unify::{UnificationTable, InferCtxtMethodsForSimplyUnifiableTypes};
|
||||||
use self::error_reporting::ErrorReporting;
|
use self::error_reporting::ErrorReporting;
|
||||||
|
|
||||||
|
pub mod bivariate;
|
||||||
pub mod combine;
|
pub mod combine;
|
||||||
pub mod equate;
|
pub mod equate;
|
||||||
pub mod error_reporting;
|
pub mod error_reporting;
|
||||||
@ -209,6 +210,9 @@ pub enum SubregionOrigin<'tcx> {
|
|||||||
// Region in return type of invoked fn must enclose call
|
// Region in return type of invoked fn must enclose call
|
||||||
CallReturn(Span),
|
CallReturn(Span),
|
||||||
|
|
||||||
|
// Operands must be in scope
|
||||||
|
Operand(Span),
|
||||||
|
|
||||||
// Region resulting from a `&` expr must enclose the `&` expr
|
// Region resulting from a `&` expr must enclose the `&` expr
|
||||||
AddrOf(Span),
|
AddrOf(Span),
|
||||||
|
|
||||||
@ -1194,6 +1198,7 @@ impl<'tcx> SubregionOrigin<'tcx> {
|
|||||||
CallRcvr(a) => a,
|
CallRcvr(a) => a,
|
||||||
CallArg(a) => a,
|
CallArg(a) => a,
|
||||||
CallReturn(a) => a,
|
CallReturn(a) => a,
|
||||||
|
Operand(a) => a,
|
||||||
AddrOf(a) => a,
|
AddrOf(a) => a,
|
||||||
AutoBorrow(a) => a,
|
AutoBorrow(a) => a,
|
||||||
SafeDestructor(a) => a,
|
SafeDestructor(a) => a,
|
||||||
@ -1257,6 +1262,7 @@ impl<'tcx> Repr<'tcx> for SubregionOrigin<'tcx> {
|
|||||||
CallRcvr(a) => format!("CallRcvr({})", a.repr(tcx)),
|
CallRcvr(a) => format!("CallRcvr({})", a.repr(tcx)),
|
||||||
CallArg(a) => format!("CallArg({})", a.repr(tcx)),
|
CallArg(a) => format!("CallArg({})", a.repr(tcx)),
|
||||||
CallReturn(a) => format!("CallReturn({})", a.repr(tcx)),
|
CallReturn(a) => format!("CallReturn({})", a.repr(tcx)),
|
||||||
|
Operand(a) => format!("Operand({})", a.repr(tcx)),
|
||||||
AddrOf(a) => format!("AddrOf({})", a.repr(tcx)),
|
AddrOf(a) => format!("AddrOf({})", a.repr(tcx)),
|
||||||
AutoBorrow(a) => format!("AutoBorrow({})", a.repr(tcx)),
|
AutoBorrow(a) => format!("AutoBorrow({})", a.repr(tcx)),
|
||||||
SafeDestructor(a) => format!("SafeDestructor({})", a.repr(tcx)),
|
SafeDestructor(a) => format!("SafeDestructor({})", a.repr(tcx)),
|
||||||
|
@ -977,7 +977,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
|
|||||||
self.expansion(&mut var_data);
|
self.expansion(&mut var_data);
|
||||||
self.contraction(&mut var_data);
|
self.contraction(&mut var_data);
|
||||||
let values =
|
let values =
|
||||||
self.extract_values_and_collect_conflicts(&var_data[],
|
self.extract_values_and_collect_conflicts(&var_data[..],
|
||||||
errors);
|
errors);
|
||||||
self.collect_concrete_region_errors(&values, errors);
|
self.collect_concrete_region_errors(&values, errors);
|
||||||
values
|
values
|
||||||
|
@ -10,12 +10,8 @@
|
|||||||
|
|
||||||
use super::combine::*;
|
use super::combine::*;
|
||||||
use super::{cres, CresCompare};
|
use super::{cres, CresCompare};
|
||||||
use super::equate::Equate;
|
|
||||||
use super::glb::Glb;
|
|
||||||
use super::higher_ranked::HigherRankedRelations;
|
use super::higher_ranked::HigherRankedRelations;
|
||||||
use super::InferCtxt;
|
use super::{Subtype};
|
||||||
use super::lub::Lub;
|
|
||||||
use super::{TypeTrace, Subtype};
|
|
||||||
use super::type_variable::{SubtypeOf, SupertypeOf};
|
use super::type_variable::{SubtypeOf, SupertypeOf};
|
||||||
|
|
||||||
use middle::ty::{BuiltinBounds};
|
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> {
|
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 tag(&self) -> String { "sub".to_string() }
|
fn fields<'a>(&'a self) -> &'a CombineFields<'a, 'tcx> { &self.fields }
|
||||||
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 tys_with_variance(&self, v: ty::Variance, a: Ty<'tcx>, b: Ty<'tcx>)
|
||||||
fn sub<'a>(&'a self) -> Sub<'a, 'tcx> { Sub(self.fields.clone()) }
|
-> cres<'tcx, Ty<'tcx>>
|
||||||
fn lub<'a>(&'a self) -> Lub<'a, 'tcx> { Lub(self.fields.clone()) }
|
{
|
||||||
fn glb<'a>(&'a self) -> Glb<'a, 'tcx> { Glb(self.fields.clone()) }
|
match v {
|
||||||
|
ty::Invariant => self.equate().tys(a, b),
|
||||||
fn contratys(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> cres<'tcx, Ty<'tcx>> {
|
ty::Covariant => self.tys(a, b),
|
||||||
Sub(self.fields.switch_expected()).tys(b, a)
|
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)
|
fn regions_with_variance(&self, v: ty::Variance, a: ty::Region, b: ty::Region)
|
||||||
-> cres<'tcx, ty::Region> {
|
-> cres<'tcx, ty::Region>
|
||||||
let opp = CombineFields {
|
{
|
||||||
a_is_expected: !self.fields.a_is_expected,
|
match v {
|
||||||
..self.fields.clone()
|
ty::Invariant => self.equate().regions(a, b),
|
||||||
};
|
ty::Covariant => self.regions(a, b),
|
||||||
Sub(opp).regions(b, a)
|
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> {
|
fn regions(&self, a: ty::Region, b: ty::Region) -> cres<'tcx, ty::Region> {
|
||||||
debug!("{}.regions({}, {})",
|
debug!("{}.regions({}, {})",
|
||||||
|
@ -14,6 +14,7 @@ use self::UndoEntry::*;
|
|||||||
|
|
||||||
use middle::ty::{self, Ty};
|
use middle::ty::{self, Ty};
|
||||||
use std::cmp::min;
|
use std::cmp::min;
|
||||||
|
use std::marker::PhantomData;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::u32;
|
use std::u32;
|
||||||
use util::snapshot_vec as sv;
|
use util::snapshot_vec as sv;
|
||||||
@ -42,13 +43,13 @@ enum UndoEntry {
|
|||||||
Relate(ty::TyVid, ty::TyVid),
|
Relate(ty::TyVid, ty::TyVid),
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Delegate<'tcx>;
|
struct Delegate<'tcx>(PhantomData<&'tcx ()>);
|
||||||
|
|
||||||
type Relation = (RelationDir, ty::TyVid);
|
type Relation = (RelationDir, ty::TyVid);
|
||||||
|
|
||||||
#[derive(Copy, PartialEq, Debug)]
|
#[derive(Copy, PartialEq, Debug)]
|
||||||
pub enum RelationDir {
|
pub enum RelationDir {
|
||||||
SubtypeOf, SupertypeOf, EqTo
|
SubtypeOf, SupertypeOf, EqTo, BiTo
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RelationDir {
|
impl RelationDir {
|
||||||
@ -56,14 +57,15 @@ impl RelationDir {
|
|||||||
match self {
|
match self {
|
||||||
SubtypeOf => SupertypeOf,
|
SubtypeOf => SupertypeOf,
|
||||||
SupertypeOf => SubtypeOf,
|
SupertypeOf => SubtypeOf,
|
||||||
EqTo => EqTo
|
EqTo => EqTo,
|
||||||
|
BiTo => BiTo,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeVariableTable<'tcx> {
|
impl<'tcx> TypeVariableTable<'tcx> {
|
||||||
pub fn new() -> TypeVariableTable<'tcx> {
|
pub fn new() -> TypeVariableTable<'tcx> {
|
||||||
TypeVariableTable { values: sv::SnapshotVec::new(Delegate) }
|
TypeVariableTable { values: sv::SnapshotVec::new(Delegate(PhantomData)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn relations<'a>(&'a mut self, a: ty::TyVid) -> &'a mut Vec<Relation> {
|
fn relations<'a>(&'a mut self, a: ty::TyVid) -> &'a mut Vec<Relation> {
|
||||||
|
@ -18,6 +18,7 @@ use middle::infer::{uok, ures};
|
|||||||
use middle::infer::InferCtxt;
|
use middle::infer::InferCtxt;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::marker::PhantomData;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use util::snapshot_vec as sv;
|
use util::snapshot_vec as sv;
|
||||||
|
|
||||||
@ -79,7 +80,7 @@ pub struct UnificationTable<K:UnifyKey> {
|
|||||||
/// made during the snapshot may either be *committed* or *rolled back*.
|
/// made during the snapshot may either be *committed* or *rolled back*.
|
||||||
pub struct Snapshot<K:UnifyKey> {
|
pub struct Snapshot<K:UnifyKey> {
|
||||||
// Link snapshot to the key type `K` of the table.
|
// Link snapshot to the key type `K` of the table.
|
||||||
marker: marker::CovariantType<K>,
|
marker: marker::PhantomData<K>,
|
||||||
snapshot: sv::Snapshot,
|
snapshot: sv::Snapshot,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +93,7 @@ pub struct Node<K:UnifyKey> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy)]
|
#[derive(Copy)]
|
||||||
pub struct Delegate<K>;
|
pub struct Delegate<K>(PhantomData<K>);
|
||||||
|
|
||||||
// We can't use V:LatticeValue, much as I would like to,
|
// We can't use V:LatticeValue, much as I would like to,
|
||||||
// because frequently the pattern is that V=Option<U> for some
|
// because frequently the pattern is that V=Option<U> for some
|
||||||
@ -102,14 +103,14 @@ pub struct Delegate<K>;
|
|||||||
impl<K:UnifyKey> UnificationTable<K> {
|
impl<K:UnifyKey> UnificationTable<K> {
|
||||||
pub fn new() -> UnificationTable<K> {
|
pub fn new() -> UnificationTable<K> {
|
||||||
UnificationTable {
|
UnificationTable {
|
||||||
values: sv::SnapshotVec::new(Delegate),
|
values: sv::SnapshotVec::new(Delegate(PhantomData)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Starts a new snapshot. Each snapshot must be either
|
/// Starts a new snapshot. Each snapshot must be either
|
||||||
/// rolled back or committed in a "LIFO" (stack) order.
|
/// rolled back or committed in a "LIFO" (stack) order.
|
||||||
pub fn snapshot(&mut self) -> Snapshot<K> {
|
pub fn snapshot(&mut self) -> Snapshot<K> {
|
||||||
Snapshot { marker: marker::CovariantType::<K>,
|
Snapshot { marker: marker::PhantomData::<K>,
|
||||||
snapshot: self.values.start_snapshot() }
|
snapshot: self.values.start_snapshot() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,18 +147,12 @@ struct LanguageItemCollector<'a> {
|
|||||||
|
|
||||||
impl<'a, 'v> Visitor<'v> for LanguageItemCollector<'a> {
|
impl<'a, 'v> Visitor<'v> for LanguageItemCollector<'a> {
|
||||||
fn visit_item(&mut self, item: &ast::Item) {
|
fn visit_item(&mut self, item: &ast::Item) {
|
||||||
match extract(&item.attrs) {
|
if let Some(value) = extract(&item.attrs) {
|
||||||
Some(value) => {
|
let item_index = self.item_refs.get(&value[..]).cloned();
|
||||||
let item_index = self.item_refs.get(&value[]).map(|x| *x);
|
|
||||||
|
|
||||||
match item_index {
|
if let Some(item_index) = item_index {
|
||||||
Some(item_index) => {
|
self.collect_item(item_index, local_def(item.id), item.span)
|
||||||
self.collect_item(item_index, local_def(item.id), item.span)
|
|
||||||
}
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
None => {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visit::walk_item(self, item);
|
visit::walk_item(self, item);
|
||||||
@ -312,12 +306,13 @@ lets_do_this! {
|
|||||||
ExchangeHeapLangItem, "exchange_heap", exchange_heap;
|
ExchangeHeapLangItem, "exchange_heap", exchange_heap;
|
||||||
OwnedBoxLangItem, "owned_box", owned_box;
|
OwnedBoxLangItem, "owned_box", owned_box;
|
||||||
|
|
||||||
|
PhantomFnItem, "phantom_fn", phantom_fn;
|
||||||
PhantomDataItem, "phantom_data", phantom_data;
|
PhantomDataItem, "phantom_data", phantom_data;
|
||||||
|
|
||||||
|
// Deprecated:
|
||||||
CovariantTypeItem, "covariant_type", covariant_type;
|
CovariantTypeItem, "covariant_type", covariant_type;
|
||||||
ContravariantTypeItem, "contravariant_type", contravariant_type;
|
ContravariantTypeItem, "contravariant_type", contravariant_type;
|
||||||
InvariantTypeItem, "invariant_type", invariant_type;
|
InvariantTypeItem, "invariant_type", invariant_type;
|
||||||
|
|
||||||
CovariantLifetimeItem, "covariant_lifetime", covariant_lifetime;
|
CovariantLifetimeItem, "covariant_lifetime", covariant_lifetime;
|
||||||
ContravariantLifetimeItem, "contravariant_lifetime", contravariant_lifetime;
|
ContravariantLifetimeItem, "contravariant_lifetime", contravariant_lifetime;
|
||||||
InvariantLifetimeItem, "invariant_lifetime", invariant_lifetime;
|
InvariantLifetimeItem, "invariant_lifetime", invariant_lifetime;
|
||||||
|
@ -1119,7 +1119,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
// Uninteresting cases: just propagate in rev exec order
|
// Uninteresting cases: just propagate in rev exec order
|
||||||
|
|
||||||
ast::ExprVec(ref exprs) => {
|
ast::ExprVec(ref exprs) => {
|
||||||
self.propagate_through_exprs(&exprs[], succ)
|
self.propagate_through_exprs(&exprs[..], succ)
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprRepeat(ref element, ref count) => {
|
ast::ExprRepeat(ref element, ref count) => {
|
||||||
@ -1143,7 +1143,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
succ
|
succ
|
||||||
};
|
};
|
||||||
let succ = self.propagate_through_exprs(&args[], succ);
|
let succ = self.propagate_through_exprs(&args[..], succ);
|
||||||
self.propagate_through_expr(&**f, succ)
|
self.propagate_through_expr(&**f, succ)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1156,11 +1156,11 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
|||||||
} else {
|
} else {
|
||||||
succ
|
succ
|
||||||
};
|
};
|
||||||
self.propagate_through_exprs(&args[], succ)
|
self.propagate_through_exprs(&args[..], succ)
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprTup(ref exprs) => {
|
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) => {
|
ast::ExprBinary(op, ref l, ref r) if ast_util::lazy_binop(op.node) => {
|
||||||
|
@ -407,7 +407,7 @@ impl RegionMaps {
|
|||||||
|
|
||||||
pub fn opt_encl_scope(&self, id: CodeExtent) -> Option<CodeExtent> {
|
pub fn opt_encl_scope(&self, id: CodeExtent) -> Option<CodeExtent> {
|
||||||
//! Returns the narrowest scope that encloses `id`, if any.
|
//! 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
|
#[allow(dead_code)] // used in middle::cfg
|
||||||
|
@ -562,7 +562,7 @@ pub fn early_bound_lifetimes<'a>(generics: &'a ast::Generics) -> Vec<ast::Lifeti
|
|||||||
|
|
||||||
generics.lifetimes.iter()
|
generics.lifetimes.iter()
|
||||||
.filter(|l| referenced_idents.iter().any(|&i| i == l.lifetime.name))
|
.filter(|l| referenced_idents.iter().any(|&i| i == l.lifetime.name))
|
||||||
.map(|l| (*l).clone())
|
.cloned()
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ impl<'tcx> Substs<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn self_ty(&self) -> Option<Ty<'tcx>> {
|
pub fn self_ty(&self) -> Option<Ty<'tcx>> {
|
||||||
self.types.get_self().map(|&t| t)
|
self.types.get_self().cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_self_ty(&self, self_ty: Ty<'tcx>) -> Substs<'tcx> {
|
pub fn with_self_ty(&self, self_ty: Ty<'tcx>) -> Substs<'tcx> {
|
||||||
|
@ -10,24 +10,27 @@
|
|||||||
|
|
||||||
//! See `doc.rs` for high-level documentation
|
//! See `doc.rs` for high-level documentation
|
||||||
|
|
||||||
|
use super::Normalized;
|
||||||
use super::SelectionContext;
|
use super::SelectionContext;
|
||||||
use super::{Obligation, ObligationCause};
|
use super::{ObligationCause};
|
||||||
|
use super::PredicateObligation;
|
||||||
use super::project;
|
use super::project;
|
||||||
use super::util;
|
use super::util;
|
||||||
|
|
||||||
use middle::subst::{Subst, TypeSpace};
|
use middle::subst::{Subst, TypeSpace};
|
||||||
use middle::ty::{self, Ty};
|
use middle::ty::{self, ToPolyTraitRef, Ty};
|
||||||
use middle::infer::InferCtxt;
|
use middle::infer::{self, InferCtxt};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::codemap::DUMMY_SP;
|
use syntax::codemap::DUMMY_SP;
|
||||||
use util::ppaux::Repr;
|
use util::ppaux::Repr;
|
||||||
|
|
||||||
pub fn impl_can_satisfy(infcx: &InferCtxt,
|
/// True if there exist types that satisfy both of the two given impls.
|
||||||
impl1_def_id: ast::DefId,
|
pub fn overlapping_impls(infcx: &InferCtxt,
|
||||||
impl2_def_id: ast::DefId)
|
impl1_def_id: ast::DefId,
|
||||||
-> bool
|
impl2_def_id: ast::DefId)
|
||||||
|
-> bool
|
||||||
{
|
{
|
||||||
debug!("impl_can_satisfy(\
|
debug!("impl_can_satisfy(\
|
||||||
impl1_def_id={}, \
|
impl1_def_id={}, \
|
||||||
@ -35,28 +38,68 @@ pub fn impl_can_satisfy(infcx: &InferCtxt,
|
|||||||
impl1_def_id.repr(infcx.tcx),
|
impl1_def_id.repr(infcx.tcx),
|
||||||
impl2_def_id.repr(infcx.tcx));
|
impl2_def_id.repr(infcx.tcx));
|
||||||
|
|
||||||
let param_env = ty::empty_parameter_environment(infcx.tcx);
|
let param_env = &ty::empty_parameter_environment(infcx.tcx);
|
||||||
let mut selcx = SelectionContext::intercrate(infcx, ¶m_env);
|
let selcx = &mut SelectionContext::intercrate(infcx, param_env);
|
||||||
let cause = ObligationCause::dummy();
|
infcx.probe(|_| {
|
||||||
|
overlap(selcx, impl1_def_id, impl2_def_id) || overlap(selcx, impl2_def_id, impl1_def_id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// `impl1` provides an implementation of `Foo<X,Y> for Z`.
|
/// Can the types from impl `a` be used to satisfy impl `b`?
|
||||||
let impl1_substs =
|
/// (Including all conditions)
|
||||||
util::fresh_substs_for_impl(infcx, DUMMY_SP, impl1_def_id);
|
fn overlap(selcx: &mut SelectionContext,
|
||||||
let impl1_trait_ref =
|
a_def_id: ast::DefId,
|
||||||
(*ty::impl_trait_ref(infcx.tcx, impl1_def_id).unwrap()).subst(infcx.tcx, &impl1_substs);
|
b_def_id: ast::DefId)
|
||||||
let impl1_trait_ref =
|
-> bool
|
||||||
project::normalize(&mut selcx, cause.clone(), &impl1_trait_ref);
|
{
|
||||||
|
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);
|
||||||
|
|
||||||
// Determine whether `impl2` can provide an implementation for those
|
// Does `a <: b` hold? If not, no overlap.
|
||||||
// same types.
|
if let Err(_) = infer::mk_sub_poly_trait_refs(selcx.infcx(),
|
||||||
let obligation = Obligation::new(cause,
|
true,
|
||||||
ty::Binder(ty::TraitPredicate {
|
infer::Misc(DUMMY_SP),
|
||||||
trait_ref: Rc::new(impl1_trait_ref.value),
|
a_trait_ref.to_poly_trait_ref(),
|
||||||
}));
|
b_trait_ref.to_poly_trait_ref()) {
|
||||||
debug!("impl_can_satisfy(obligation={})", obligation.repr(infcx.tcx));
|
return false;
|
||||||
selcx.evaluate_impl(impl2_def_id, &obligation) &&
|
}
|
||||||
impl1_trait_ref.obligations.iter().all(
|
|
||||||
|o| selcx.evaluate_obligation(o))
|
// Are any of the obligations unsatisfiable? If so, no overlap.
|
||||||
|
a_obligations.iter()
|
||||||
|
.chain(b_obligations.iter())
|
||||||
|
.all(|o| selcx.evaluate_obligation(o))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Instantiate fresh variables for all bound parameters of the impl
|
||||||
|
/// and return the impl trait ref with those variables substituted.
|
||||||
|
fn impl_trait_ref_and_oblig<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
|
||||||
|
impl_def_id: ast::DefId)
|
||||||
|
-> (Rc<ty::TraitRef<'tcx>>,
|
||||||
|
Vec<PredicateObligation<'tcx>>)
|
||||||
|
{
|
||||||
|
let impl_substs =
|
||||||
|
&util::fresh_substs_for_impl(selcx.infcx(), DUMMY_SP, impl_def_id);
|
||||||
|
let impl_trait_ref =
|
||||||
|
ty::impl_trait_ref(selcx.tcx(), impl_def_id).unwrap();
|
||||||
|
let impl_trait_ref =
|
||||||
|
impl_trait_ref.subst(selcx.tcx(), impl_substs);
|
||||||
|
let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
|
||||||
|
project::normalize(selcx, ObligationCause::dummy(), &impl_trait_ref);
|
||||||
|
|
||||||
|
let predicates = ty::lookup_predicates(selcx.tcx(), impl_def_id);
|
||||||
|
let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
|
||||||
|
let Normalized { value: predicates, obligations: normalization_obligations2 } =
|
||||||
|
project::normalize(selcx, ObligationCause::dummy(), &predicates);
|
||||||
|
let impl_obligations =
|
||||||
|
util::predicates_for_generics(selcx.tcx(), ObligationCause::dummy(), 0, &predicates);
|
||||||
|
|
||||||
|
let impl_obligations: Vec<_> =
|
||||||
|
impl_obligations.into_iter()
|
||||||
|
.chain(normalization_obligations1.into_iter())
|
||||||
|
.chain(normalization_obligations2.into_iter())
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
(impl_trait_ref, impl_obligations)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum OrphanCheckErr<'tcx> {
|
pub enum OrphanCheckErr<'tcx> {
|
||||||
|
@ -28,6 +28,7 @@ use util::ppaux::{Repr, UserString};
|
|||||||
pub use self::error_reporting::report_fulfillment_errors;
|
pub use self::error_reporting::report_fulfillment_errors;
|
||||||
pub use self::error_reporting::suggest_new_overflow_limit;
|
pub use self::error_reporting::suggest_new_overflow_limit;
|
||||||
pub use self::coherence::orphan_check;
|
pub use self::coherence::orphan_check;
|
||||||
|
pub use self::coherence::overlapping_impls;
|
||||||
pub use self::coherence::OrphanCheckErr;
|
pub use self::coherence::OrphanCheckErr;
|
||||||
pub use self::fulfill::{FulfillmentContext, RegionObligation};
|
pub use self::fulfill::{FulfillmentContext, RegionObligation};
|
||||||
pub use self::project::MismatchedProjectionTypes;
|
pub use self::project::MismatchedProjectionTypes;
|
||||||
@ -270,16 +271,6 @@ pub struct VtableObjectData<'tcx> {
|
|||||||
pub object_ty: Ty<'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.
|
/// Creates predicate obligations from the generic bounds.
|
||||||
pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
|
pub fn predicates_for_generics<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
use super::supertraits;
|
use super::supertraits;
|
||||||
use super::elaborate_predicates;
|
use super::elaborate_predicates;
|
||||||
|
|
||||||
use middle::subst::{self, SelfSpace};
|
use middle::subst::{self, SelfSpace, TypeSpace};
|
||||||
use middle::traits;
|
use middle::traits;
|
||||||
use middle::ty::{self, Ty};
|
use middle::ty::{self, Ty};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
@ -31,6 +31,10 @@ pub enum ObjectSafetyViolation<'tcx> {
|
|||||||
/// Self : Sized declared on the trait
|
/// Self : Sized declared on the trait
|
||||||
SizedSelf,
|
SizedSelf,
|
||||||
|
|
||||||
|
/// Supertrait reference references `Self` an in illegal location
|
||||||
|
/// (e.g. `trait Foo : Bar<Self>`)
|
||||||
|
SupertraitSelf,
|
||||||
|
|
||||||
/// Method has something illegal
|
/// Method has something illegal
|
||||||
Method(Rc<ty::Method<'tcx>>, MethodViolationCode),
|
Method(Rc<ty::Method<'tcx>>, 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:
|
// Because we query yes/no results frequently, we keep a cache:
|
||||||
let cached_result =
|
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 =
|
let result =
|
||||||
cached_result.unwrap_or_else(|| {
|
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) {
|
if trait_has_sized_self(tcx, trait_def_id) {
|
||||||
violations.push(ObjectSafetyViolation::SizedSelf);
|
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={}) = {}",
|
debug!("object_safety_violations_for_trait(trait_def_id={}) = {}",
|
||||||
trait_def_id.repr(tcx),
|
trait_def_id.repr(tcx),
|
||||||
@ -118,6 +125,35 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||||||
violations
|
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>,
|
fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||||
trait_def_id: ast::DefId)
|
trait_def_id: ast::DefId)
|
||||||
-> bool
|
-> bool
|
||||||
@ -138,11 +174,7 @@ fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
|
|||||||
.any(|predicate| {
|
.any(|predicate| {
|
||||||
match predicate {
|
match predicate {
|
||||||
ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
|
ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
|
||||||
let self_ty = trait_pred.0.self_ty();
|
is_self(trait_pred.0.self_ty())
|
||||||
match self_ty.sty {
|
|
||||||
ty::ty_param(ref data) => data.space == subst::SelfSpace,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ty::Predicate::Projection(..) |
|
ty::Predicate::Projection(..) |
|
||||||
ty::Predicate::Trait(..) |
|
ty::Predicate::Trait(..) |
|
||||||
@ -295,8 +327,17 @@ impl<'tcx> Repr<'tcx> for ObjectSafetyViolation<'tcx> {
|
|||||||
match *self {
|
match *self {
|
||||||
ObjectSafetyViolation::SizedSelf =>
|
ObjectSafetyViolation::SizedSelf =>
|
||||||
format!("SizedSelf"),
|
format!("SizedSelf"),
|
||||||
|
ObjectSafetyViolation::SupertraitSelf =>
|
||||||
|
format!("SupertraitSelf"),
|
||||||
ObjectSafetyViolation::Method(ref m, code) =>
|
ObjectSafetyViolation::Method(ref m, code) =>
|
||||||
format!("Method({},{:?})", m.repr(tcx), 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,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -132,6 +132,7 @@ pub enum MethodMatchedData {
|
|||||||
/// parameters) that would have to be inferred from the impl.
|
/// parameters) that would have to be inferred from the impl.
|
||||||
#[derive(PartialEq,Eq,Debug,Clone)]
|
#[derive(PartialEq,Eq,Debug,Clone)]
|
||||||
enum SelectionCandidate<'tcx> {
|
enum SelectionCandidate<'tcx> {
|
||||||
|
PhantomFnCandidate,
|
||||||
BuiltinCandidate(ty::BuiltinBound),
|
BuiltinCandidate(ty::BuiltinBound),
|
||||||
ParamCandidate(ty::PolyTraitRef<'tcx>),
|
ParamCandidate(ty::PolyTraitRef<'tcx>),
|
||||||
ImplCandidate(ast::DefId),
|
ImplCandidate(ast::DefId),
|
||||||
@ -736,7 +737,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
{
|
{
|
||||||
let cache = self.pick_candidate_cache();
|
let cache = self.pick_candidate_cache();
|
||||||
let hashmap = cache.hashmap.borrow();
|
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,
|
fn insert_candidate_cache(&mut self,
|
||||||
@ -793,8 +794,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
stack: &TraitObligationStack<'o, 'tcx>)
|
stack: &TraitObligationStack<'o, 'tcx>)
|
||||||
-> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>>
|
-> Result<SelectionCandidateSet<'tcx>, SelectionError<'tcx>>
|
||||||
{
|
{
|
||||||
// Check for overflow.
|
|
||||||
|
|
||||||
let TraitObligationStack { obligation, .. } = *stack;
|
let TraitObligationStack { obligation, .. } = *stack;
|
||||||
|
|
||||||
let mut candidates = SelectionCandidateSet {
|
let mut candidates = SelectionCandidateSet {
|
||||||
@ -802,6 +801,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
ambiguous: false
|
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
|
// Other bounds. Consider both in-scope bounds from fn decl
|
||||||
// and applicable impls. There is a certain set of precedence rules here.
|
// and applicable impls. There is a certain set of precedence rules here.
|
||||||
|
|
||||||
@ -996,7 +1003,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
|
|
||||||
let all_bounds =
|
let all_bounds =
|
||||||
util::transitive_bounds(
|
util::transitive_bounds(
|
||||||
self.tcx(), &caller_trait_refs[]);
|
self.tcx(), &caller_trait_refs[..]);
|
||||||
|
|
||||||
let matching_bounds =
|
let matching_bounds =
|
||||||
all_bounds.filter(
|
all_bounds.filter(
|
||||||
@ -1521,7 +1528,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
ty::substd_enum_variants(self.tcx(), def_id, substs)
|
ty::substd_enum_variants(self.tcx(), def_id, substs)
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|variant| variant.args.iter())
|
.flat_map(|variant| variant.args.iter())
|
||||||
.map(|&ty| ty)
|
.cloned()
|
||||||
.collect();
|
.collect();
|
||||||
nominal(self, bound, def_id, types)
|
nominal(self, bound, def_id, types)
|
||||||
}
|
}
|
||||||
@ -1629,6 +1636,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
try!(self.confirm_builtin_candidate(obligation, builtin_bound))))
|
try!(self.confirm_builtin_candidate(obligation, builtin_bound))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PhantomFnCandidate |
|
||||||
ErrorCandidate => {
|
ErrorCandidate => {
|
||||||
Ok(VtableBuiltin(VtableBuiltinData { nested: VecPerParamSpace::empty() }))
|
Ok(VtableBuiltin(VtableBuiltinData { nested: VecPerParamSpace::empty() }))
|
||||||
}
|
}
|
||||||
@ -2295,6 +2303,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
|||||||
impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
|
impl<'tcx> Repr<'tcx> for SelectionCandidate<'tcx> {
|
||||||
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
|
||||||
match *self {
|
match *self {
|
||||||
|
PhantomFnCandidate => format!("PhantomFnCandidate"),
|
||||||
ErrorCandidate => format!("ErrorCandidate"),
|
ErrorCandidate => format!("ErrorCandidate"),
|
||||||
BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b),
|
BuiltinCandidate(b) => format!("BuiltinCandidate({:?})", b),
|
||||||
ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)),
|
ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)),
|
||||||
|
@ -68,15 +68,16 @@ use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
|
|||||||
use util::nodemap::{FnvHashMap};
|
use util::nodemap::{FnvHashMap};
|
||||||
|
|
||||||
use arena::TypedArena;
|
use arena::TypedArena;
|
||||||
use std::borrow::{BorrowFrom, Cow};
|
use std::borrow::{Borrow, Cow};
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::{Cell, RefCell};
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::fmt;
|
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::mem;
|
||||||
use std::ops;
|
use std::ops;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::vec::CowVec;
|
use std::vec::{CowVec, IntoIter};
|
||||||
use collections::enum_set::{EnumSet, CLike};
|
use collections::enum_set::{EnumSet, CLike};
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use syntax::abi;
|
use syntax::abi;
|
||||||
@ -958,11 +959,18 @@ impl<'tcx> PartialEq for TyS<'tcx> {
|
|||||||
}
|
}
|
||||||
impl<'tcx> Eq for TyS<'tcx> {}
|
impl<'tcx> Eq for TyS<'tcx> {}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
impl<'tcx, S: Writer + Hasher> Hash<S> for TyS<'tcx> {
|
impl<'tcx, S: Writer + Hasher> Hash<S> for TyS<'tcx> {
|
||||||
fn hash(&self, s: &mut S) {
|
fn hash(&self, s: &mut S) {
|
||||||
(self as *const _).hash(s)
|
(self as *const _).hash(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
impl<'tcx> Hash for TyS<'tcx> {
|
||||||
|
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||||
|
(self as *const _).hash(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
|
pub type Ty<'tcx> = &'tcx TyS<'tcx>;
|
||||||
|
|
||||||
@ -980,15 +988,22 @@ impl<'tcx> PartialEq for InternedTy<'tcx> {
|
|||||||
|
|
||||||
impl<'tcx> Eq for InternedTy<'tcx> {}
|
impl<'tcx> Eq for InternedTy<'tcx> {}
|
||||||
|
|
||||||
|
#[cfg(stage0)]
|
||||||
impl<'tcx, S: Writer + Hasher> Hash<S> for InternedTy<'tcx> {
|
impl<'tcx, S: Writer + Hasher> Hash<S> for InternedTy<'tcx> {
|
||||||
fn hash(&self, s: &mut S) {
|
fn hash(&self, s: &mut S) {
|
||||||
self.ty.sty.hash(s)
|
self.ty.sty.hash(s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(not(stage0))]
|
||||||
|
impl<'tcx> Hash for InternedTy<'tcx> {
|
||||||
|
fn hash<H: Hasher>(&self, s: &mut H) {
|
||||||
|
self.ty.sty.hash(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> BorrowFrom<InternedTy<'tcx>> for sty<'tcx> {
|
impl<'tcx> Borrow<sty<'tcx>> for InternedTy<'tcx> {
|
||||||
fn borrow_from<'a>(ty: &'a InternedTy<'tcx>) -> &'a sty<'tcx> {
|
fn borrow<'a>(&'a self) -> &'a sty<'tcx> {
|
||||||
&ty.ty.sty
|
&self.ty.sty
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2004,6 +2019,40 @@ impl<'tcx> AsPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> 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<Ty<'tcx>> {
|
||||||
|
let vec: Vec<_> = match *self {
|
||||||
|
ty::Predicate::Trait(ref data) => {
|
||||||
|
data.0.trait_ref.substs.types.as_slice().to_vec()
|
||||||
|
}
|
||||||
|
ty::Predicate::Equate(ty::Binder(ref data)) => {
|
||||||
|
vec![data.0, data.1]
|
||||||
|
}
|
||||||
|
ty::Predicate::TypeOutlives(ty::Binder(ref data)) => {
|
||||||
|
vec![data.0]
|
||||||
|
}
|
||||||
|
ty::Predicate::RegionOutlives(..) => {
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
ty::Predicate::Projection(ref data) => {
|
||||||
|
let trait_inputs = data.0.projection_ty.trait_ref.substs.types.as_slice();
|
||||||
|
trait_inputs.iter()
|
||||||
|
.cloned()
|
||||||
|
.chain(Some(data.0.ty).into_iter())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// The only reason to collect into a vector here is that I was
|
||||||
|
// too lazy to make the full (somewhat complicated) iterator
|
||||||
|
// type that would be needed here. But I wanted this fn to
|
||||||
|
// return an iterator conceptually, rather than a `Vec`, so as
|
||||||
|
// to be closer to `Ty::walk`.
|
||||||
|
vec.into_iter()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn has_escaping_regions(&self) -> bool {
|
pub fn has_escaping_regions(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Predicate::Trait(ref trait_ref) => trait_ref.has_escaping_regions(),
|
Predicate::Trait(ref trait_ref) => trait_ref.has_escaping_regions(),
|
||||||
@ -2331,7 +2380,7 @@ impl ClosureKind {
|
|||||||
};
|
};
|
||||||
match result {
|
match result {
|
||||||
Ok(trait_did) => trait_did,
|
Ok(trait_did) => trait_did,
|
||||||
Err(err) => cx.sess.fatal(&err[]),
|
Err(err) => cx.sess.fatal(&err[..]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2665,7 +2714,7 @@ impl FlagComputation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
&ty_tup(ref ts) => {
|
&ty_tup(ref ts) => {
|
||||||
self.add_tys(&ts[]);
|
self.add_tys(&ts[..]);
|
||||||
}
|
}
|
||||||
|
|
||||||
&ty_bare_fn(_, ref f) => {
|
&ty_bare_fn(_, ref f) => {
|
||||||
@ -2836,7 +2885,7 @@ pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>,
|
|||||||
def_id: ast::DefId,
|
def_id: ast::DefId,
|
||||||
input_tys: &[Ty<'tcx>],
|
input_tys: &[Ty<'tcx>],
|
||||||
output: Ty<'tcx>) -> 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,
|
mk_bare_fn(cx,
|
||||||
Some(def_id),
|
Some(def_id),
|
||||||
cx.mk_bare_fn(BareFnTy {
|
cx.mk_bare_fn(BareFnTy {
|
||||||
@ -2959,6 +3008,13 @@ impl<'tcx> TyS<'tcx> {
|
|||||||
assert_eq!(r, Some(self));
|
assert_eq!(r, Some(self));
|
||||||
walker
|
walker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
|
||||||
|
match self.sty {
|
||||||
|
ty::ty_param(ref d) => Some(d.clone()),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn walk_ty<'tcx, F>(ty_root: Ty<'tcx>, mut f: F)
|
pub fn walk_ty<'tcx, F>(ty_root: Ty<'tcx>, mut f: F)
|
||||||
@ -3451,7 +3507,7 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
|
|||||||
ty_struct(did, substs) => {
|
ty_struct(did, substs) => {
|
||||||
let flds = struct_fields(cx, did, substs);
|
let flds = struct_fields(cx, did, substs);
|
||||||
let mut res =
|
let mut res =
|
||||||
TypeContents::union(&flds[],
|
TypeContents::union(&flds[..],
|
||||||
|f| tc_mt(cx, f.mt, cache));
|
|f| tc_mt(cx, f.mt, cache));
|
||||||
|
|
||||||
if !lookup_repr_hints(cx, did).contains(&attr::ReprExtern) {
|
if !lookup_repr_hints(cx, did).contains(&attr::ReprExtern) {
|
||||||
@ -3474,14 +3530,14 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ty_tup(ref tys) => {
|
ty_tup(ref tys) => {
|
||||||
TypeContents::union(&tys[],
|
TypeContents::union(&tys[..],
|
||||||
|ty| tc_ty(cx, *ty, cache))
|
|ty| tc_ty(cx, *ty, cache))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty_enum(did, substs) => {
|
ty_enum(did, substs) => {
|
||||||
let variants = substd_enum_variants(cx, did, substs);
|
let variants = substd_enum_variants(cx, did, substs);
|
||||||
let mut res =
|
let mut res =
|
||||||
TypeContents::union(&variants[], |variant| {
|
TypeContents::union(&variants[..], |variant| {
|
||||||
TypeContents::union(&variant.args[],
|
TypeContents::union(&variant.args[],
|
||||||
|arg_ty| {
|
|arg_ty| {
|
||||||
tc_ty(cx, *arg_ty, cache)
|
tc_ty(cx, *arg_ty, cache)
|
||||||
@ -3805,7 +3861,7 @@ pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
|
|||||||
-> Representability {
|
-> Representability {
|
||||||
match ty.sty {
|
match ty.sty {
|
||||||
ty_tup(ref ts) => {
|
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.
|
// Fixed-length vectors.
|
||||||
// FIXME(#11924) Behavior undecided for zero-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<ast::DefId>) -> Option<Ty<'tcx>> {
|
variant: Option<ast::DefId>) -> Option<Ty<'tcx>> {
|
||||||
|
|
||||||
match (&ty.sty, variant) {
|
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)
|
(&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<ast::DefId> {
|
pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option<ast::DefId> {
|
||||||
cx.provided_method_sources.borrow().get(&id).map(|x| *x)
|
cx.provided_method_sources.borrow().get(&id).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
|
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 {
|
match item.node {
|
||||||
ItemTrait(_, _, _, ref ms) => {
|
ItemTrait(_, _, _, ref ms) => {
|
||||||
let (_, p) =
|
let (_, p) =
|
||||||
ast_util::split_trait_methods(&ms[]);
|
ast_util::split_trait_methods(&ms[..]);
|
||||||
p.iter()
|
p.iter()
|
||||||
.map(|m| {
|
.map(|m| {
|
||||||
match impl_or_trait_item(
|
match impl_or_trait_item(
|
||||||
@ -6600,7 +6656,7 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A free variable referred to in a function.
|
/// A free variable referred to in a function.
|
||||||
#[derive(Copy, RustcEncodable, RustcDecodable)]
|
#[derive(Copy, Clone, RustcEncodable, RustcDecodable)]
|
||||||
pub struct Freevar {
|
pub struct Freevar {
|
||||||
/// The variable being accessed free.
|
/// The variable being accessed free.
|
||||||
pub def: def::Def,
|
pub def: def::Def,
|
||||||
@ -6625,7 +6681,7 @@ pub fn with_freevars<T, F>(tcx: &ty::ctxt, fid: ast::NodeId, f: F) -> T where
|
|||||||
{
|
{
|
||||||
match tcx.freevars.borrow().get(&fid) {
|
match tcx.freevars.borrow().get(&fid) {
|
||||||
None => f(&[]),
|
None => f(&[]),
|
||||||
Some(d) => f(&d[])
|
Some(d) => f(&d[..])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user