auto merge of #19958 : alexcrichton/rust/rollup, r=alexcrichton
This commit is contained in:
commit
22a9f250b5
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -11,3 +11,6 @@
|
||||
[submodule "src/jemalloc"]
|
||||
path = src/jemalloc
|
||||
url = https://github.com/rust-lang/jemalloc.git
|
||||
[submodule "src/rust-installer"]
|
||||
path = src/rust-installer
|
||||
url = https://github.com/rust-lang/rust-installer
|
||||
|
@ -27,7 +27,7 @@ CTAGS_LOCATIONS=$(patsubst ${CFG_SRC_DIR}src/llvm,, \
|
||||
$(patsubst ${CFG_SRC_DIR}src/rt/msvc,, \
|
||||
$(patsubst ${CFG_SRC_DIR}src/rt/vg,, \
|
||||
$(wildcard ${CFG_SRC_DIR}src/*) $(wildcard ${CFG_SRC_DIR}src/rt/*) \
|
||||
)))))))))
|
||||
))))))))
|
||||
CTAGS_OPTS=--options="${CFG_SRC_DIR}src/etc/ctags.rust" --languages=-javascript --recurse ${CTAGS_LOCATIONS}
|
||||
# We could use `--languages=Rust`, but there is value in producing tags for the
|
||||
# C++ parts of the code base too (at the time of writing, those are .h and .cpp
|
||||
|
22
mk/dist.mk
22
mk/dist.mk
@ -58,6 +58,7 @@ PKG_FILES := \
|
||||
rt \
|
||||
rustllvm \
|
||||
snapshots.txt \
|
||||
rust-installer \
|
||||
test) \
|
||||
$(PKG_GITMODULES) \
|
||||
$(filter-out config.stamp, \
|
||||
@ -209,33 +210,40 @@ distcheck-osx: dist-osx
|
||||
# Unix binary installer tarballs
|
||||
######################################################################
|
||||
|
||||
NON_INSTALLED_PREFIXES=COPYRIGHT,LICENSE-APACHE,LICENSE-MIT,README.md,doc
|
||||
|
||||
define DEF_INSTALLER
|
||||
|
||||
$$(eval $$(call DEF_PREPARE,dir-$(1)))
|
||||
|
||||
dist-install-dir-$(1): PREPARE_HOST=$(1)
|
||||
dist-install-dir-$(1): PREPARE_TARGETS=$(2)
|
||||
dist-install-dir-$(1): PREPARE_DEST_DIR=tmp/dist/$$(PKG_NAME)-$(1)
|
||||
dist-install-dir-$(1): PREPARE_DEST_DIR=tmp/dist/$$(PKG_NAME)-$(1)-image
|
||||
dist-install-dir-$(1): PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD)
|
||||
dist-install-dir-$(1): PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD)
|
||||
dist-install-dir-$(1): PREPARE_LIB_CMD=$(DEFAULT_PREPARE_LIB_CMD)
|
||||
dist-install-dir-$(1): PREPARE_MAN_CMD=$(DEFAULT_PREPARE_MAN_CMD)
|
||||
dist-install-dir-$(1): PREPARE_CLEAN=true
|
||||
dist-install-dir-$(1): prepare-base-dir-$(1) docs compiler-docs
|
||||
$$(Q)(cd $$(PREPARE_DEST_DIR)/ && find . -type f | sed 's/^\.\///') \
|
||||
> tmp/dist/manifest-$(1).in
|
||||
$$(Q)mv tmp/dist/manifest-$(1).in $$(PREPARE_DEST_DIR)/$$(CFG_LIBDIR_RELATIVE)/rustlib/manifest.in
|
||||
# Add remaining non-installed files
|
||||
$$(Q)$$(PREPARE_MAN_CMD) $$(S)COPYRIGHT $$(PREPARE_DEST_DIR)
|
||||
$$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-APACHE $$(PREPARE_DEST_DIR)
|
||||
$$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-MIT $$(PREPARE_DEST_DIR)
|
||||
$$(Q)$$(PREPARE_MAN_CMD) $$(S)README.md $$(PREPARE_DEST_DIR)
|
||||
$$(Q)cp -r doc $$(PREPARE_DEST_DIR)
|
||||
$$(Q)$$(PREPARE_BIN_CMD) $$(S)src/etc/install.sh $$(PREPARE_DEST_DIR)
|
||||
|
||||
dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1)
|
||||
@$(call E, build: $$@)
|
||||
$$(Q)tar -czf dist/$$(PKG_NAME)-$(1).tar.gz -C tmp/dist $$(PKG_NAME)-$(1)
|
||||
$$(Q)$$(S)src/rust-installer/gen-installer.sh \
|
||||
--product-name=Rust \
|
||||
--verify-bin=rustc \
|
||||
--rel-manifest-dir=rustlib \
|
||||
--success-message=Rust-is-ready-to-roll. \
|
||||
--image-dir=tmp/dist/$$(PKG_NAME)-$(1)-image \
|
||||
--work-dir=tmp/dist \
|
||||
--output-dir=dist \
|
||||
--non-installed-prefixes=$$(NON_INSTALLED_PREFIXES) \
|
||||
--package-name=$$(PKG_NAME)-$(1)
|
||||
$$(Q)rm -R tmp/dist/$$(PKG_NAME)-$(1)-image
|
||||
|
||||
endef
|
||||
|
||||
|
@ -25,7 +25,7 @@ endif
|
||||
# Remove tmp files because it's a decent amount of disk space
|
||||
$(Q)rm -R tmp/dist
|
||||
|
||||
prepare_install: dist-install-dir-$(CFG_BUILD) | tmp/empty_dir
|
||||
prepare_install: dist/$(PKG_NAME)-$(CFG_BUILD).tar.gz | tmp/empty_dir
|
||||
|
||||
uninstall:
|
||||
ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
|
||||
@ -38,7 +38,7 @@ endif
|
||||
# Remove tmp files because it's a decent amount of disk space
|
||||
$(Q)rm -R tmp/dist
|
||||
|
||||
prepare_uninstall: dist-install-dir-$(CFG_BUILD) | tmp/empty_dir
|
||||
prepare_uninstall: dist/$(PKG_NAME)-$(CFG_BUILD).tar.gz | tmp/empty_dir
|
||||
|
||||
.PHONY: install prepare_install uninstall prepare_uninstall
|
||||
|
||||
|
@ -394,7 +394,7 @@ fn extract_gdb_version(full_version_line: Option<String>) -> Option<String> {
|
||||
|
||||
match re.captures(full_version_line) {
|
||||
Some(captures) => {
|
||||
Some(captures.at(2).to_string())
|
||||
Some(captures.at(2).unwrap_or("").to_string())
|
||||
}
|
||||
None => {
|
||||
println!("Could not extract GDB version from line '{}'",
|
||||
@ -428,7 +428,7 @@ fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> {
|
||||
|
||||
match re.captures(full_version_line) {
|
||||
Some(captures) => {
|
||||
Some(captures.at(1).to_string())
|
||||
Some(captures.at(1).unwrap_or("").to_string())
|
||||
}
|
||||
None => {
|
||||
println!("Could not extract LLDB version from line '{}'",
|
||||
|
@ -66,10 +66,10 @@ fn parse_expected(last_nonfollow_error: Option<uint>,
|
||||
line: &str,
|
||||
re: &Regex) -> Option<(WhichLine, ExpectedError)> {
|
||||
re.captures(line).and_then(|caps| {
|
||||
let adjusts = caps.name("adjusts").len();
|
||||
let kind = caps.name("kind").to_ascii_lower();
|
||||
let msg = caps.name("msg").trim().to_string();
|
||||
let follow = caps.name("follow").len() > 0;
|
||||
let adjusts = caps.name("adjusts").unwrap_or("").len();
|
||||
let kind = caps.name("kind").unwrap_or("").to_ascii_lower();
|
||||
let msg = caps.name("msg").unwrap_or("").trim().to_string();
|
||||
let follow = caps.name("follow").unwrap_or("").len() > 0;
|
||||
|
||||
let (which, line) = if follow {
|
||||
assert!(adjusts == 0, "use either //~| or //~^, not both.");
|
||||
|
@ -24,7 +24,7 @@ Some examples that demonstrate different aspects of the language:
|
||||
[HashMap]: https://github.com/rust-lang/rust/blob/master/src/libcollections/hashmap.rs
|
||||
[json]: https://github.com/rust-lang/rust/blob/master/src/libserialize/json.rs
|
||||
|
||||
You may also be interested in browsing [GitHub's Rust][github-rust] page.
|
||||
You may also be interested in browsing [trending Rust repositories][github-rust] on GitHub.
|
||||
|
||||
[github-rust]: https://github.com/trending?l=rust
|
||||
|
||||
@ -42,7 +42,7 @@ Let the fact that this is an easily countable number be a warning.
|
||||
|
||||
## Does it run on Windows?
|
||||
|
||||
Yes. All development happens in lock-step on all 3 target platforms. Using MinGW, not Cygwin. Note that the windows implementation currently has some limitations: in particular 64-bit build is [not fully supported yet][win64], and all executables created by rustc [depend on libgcc DLL at runtime][libgcc].
|
||||
Yes. All development happens in lockstep on all 3 target platforms (using MinGW, not Cygwin). Note that the Windows implementation currently has some limitations; in particular, the 64-bit build is [not fully supported yet][win64], and all executables created by rustc [depend on libgcc DLL at runtime][libgcc].
|
||||
|
||||
[win64]: https://github.com/rust-lang/rust/issues/1237
|
||||
[libgcc]: https://github.com/rust-lang/rust/issues/11782
|
||||
@ -104,7 +104,7 @@ Similar to the reasoning about default-sync: it wires fewer assumptions into the
|
||||
|
||||
## Why are strings UTF-8 by default? Why not UCS2 or UCS4?
|
||||
|
||||
The `str` type is UTF-8 because we observe more text in the wild in this encoding -- particularly in network transmissions, which are endian-agnostic -- and we think it's best that the default treatment of I/O not involve having to recode codepoints in each direction.
|
||||
The `str` type is UTF-8 because we observe more text in the wild in this encoding – particularly in network transmissions, which are endian-agnostic – and we think it's best that the default treatment of I/O not involve having to recode codepoints in each direction.
|
||||
|
||||
This does mean that indexed access to a Unicode codepoint inside a `str` value is an O(n) operation. On the one hand, this is clearly undesirable; on the other hand, this problem is full of trade-offs and we'd like to point a few important qualifications:
|
||||
|
||||
@ -145,7 +145,7 @@ For simplicity, we do not plan to do so. Implementing automatic semicolon insert
|
||||
|
||||
## How do I get my program to display the output of logging macros?
|
||||
|
||||
**Short answer** set the RUST_LOG environment variable to the name of your source file, sans extension.
|
||||
**Short Answer**: Set the `RUST_LOG` environment variable to the name of your source file, sans extension.
|
||||
|
||||
```sh
|
||||
rustc hello.rs
|
||||
@ -153,15 +153,19 @@ export RUST_LOG=hello
|
||||
./hello
|
||||
```
|
||||
|
||||
**Long answer** RUST_LOG takes a 'logging spec' that consists of a
|
||||
**Long Answer**: `RUST_LOG` takes a 'logging spec' that consists of a
|
||||
comma-separated list of paths, where a path consists of the crate name and
|
||||
sequence of module names, each separated by double-colons. For standalone .rs
|
||||
files the crate is implicitly named after the source file, so in the above
|
||||
example we were setting RUST_LOG to the name of the hello crate. Multiple paths
|
||||
sequence of module names, each separated by double-colons. For standalone `.rs`
|
||||
files, the crate is implicitly named after the source file, so in the above
|
||||
example we were setting `RUST_LOG` to the name of the hello crate. Multiple paths
|
||||
can be combined to control the exact logging you want to see. For example, when
|
||||
debugging linking in the compiler you might set
|
||||
`RUST_LOG=rustc::metadata::creader,rustc::util::filesearch,rustc::back::rpath`
|
||||
For a full description see [the logging crate][1].
|
||||
debugging linking in the compiler, you might set the following:
|
||||
|
||||
```sh
|
||||
RUST_LOG=rustc::metadata::creader,rustc::util::filesearch,rustc::back::rpath
|
||||
```
|
||||
|
||||
For a full description, see [the logging crate][1].
|
||||
|
||||
## How fast is Rust?
|
||||
|
||||
@ -172,6 +176,6 @@ performance.
|
||||
That said, it is an explicit goal of Rust to be as fast as C++ for most things.
|
||||
Language decisions are made with performance in mind, and we want Rust to be as
|
||||
fast as possible. Given that Rust is built on top of LLVM, any performance
|
||||
improvements in it also help us be faster.
|
||||
improvements in it also help Rust become faster.
|
||||
|
||||
[1]:log/index.html
|
||||
|
@ -195,7 +195,7 @@ early_return!(input_2, [T::SpecialB]);
|
||||
As the above example demonstrates, `$(...)*` is also valid on the right-hand
|
||||
side of a macro definition. The behavior of `*` in transcription,
|
||||
especially in cases where multiple `*`s are nested, and multiple different
|
||||
names are involved, can seem somewhat magical and intuitive at first. The
|
||||
names are involved, can seem somewhat magical and unintuitive at first. The
|
||||
system that interprets them is called "Macro By Example". The two rules to
|
||||
keep in mind are (1) the behavior of `$(...)*` is to walk through one "layer"
|
||||
of repetitions for all of the `$name`s it contains in lockstep, and (2) each
|
||||
|
@ -341,7 +341,7 @@ fn main() {
|
||||
{ // |
|
||||
let y = &5i; // ---+ y goes into scope
|
||||
let f = Foo { x: y }; // ---+ f goes into scope
|
||||
x = &f.x; // | | error here
|
||||
x = &f.x; // | | error here
|
||||
} // ---+ f & y go out of scope
|
||||
// |
|
||||
println!("{}", x); // |
|
||||
@ -416,7 +416,7 @@ note: `car` moved here because it has type `Car`, which is non-copyable
|
||||
```
|
||||
|
||||
We need our `Car` to be pointed to by multiple `Wheel`s. We can't do that with
|
||||
`Box<T>`, because it has a single owner. We can do t with `Rc<T>` instead:
|
||||
`Box<T>`, because it has a single owner. We can do it with `Rc<T>` instead:
|
||||
|
||||
```rust
|
||||
use std::rc::Rc;
|
||||
|
@ -357,7 +357,7 @@ Let's finally check out that third section: documentation tests.
|
||||
|
||||
Nothing is better than documentation with examples. Nothing is worse than
|
||||
examples that don't actually work, because the code has changed since the
|
||||
documentation has been written. To this end, Rust supports automaticaly
|
||||
documentation has been written. To this end, Rust supports automatically
|
||||
running examples in your documentation. Here's a fleshed-out `src/lib.rs`
|
||||
with examples:
|
||||
|
||||
|
@ -418,6 +418,19 @@ let x: int = 5;
|
||||
If I asked you to read this out loud to the rest of the class, you'd say "`x`
|
||||
is a binding with the type `int` and the value `five`."
|
||||
|
||||
In future examples, we may annotate the type in a comment. The examples will
|
||||
look like this:
|
||||
|
||||
```{rust}
|
||||
fn main() {
|
||||
let x = 5i; // x: int
|
||||
}
|
||||
```
|
||||
|
||||
Note the similarities between this annotation and the syntax you use with `let`.
|
||||
Including these kinds of comments is not idiomatic Rust, but we'll occasionally
|
||||
include them to help you understand what the types that Rust infers are.
|
||||
|
||||
By default, bindings are **immutable**. This code will not compile:
|
||||
|
||||
```{ignore}
|
||||
@ -436,7 +449,7 @@ error: re-assignment of immutable variable `x`
|
||||
If you want a binding to be mutable, you can use `mut`:
|
||||
|
||||
```{rust}
|
||||
let mut x = 5i;
|
||||
let mut x = 5i; // mut x: int
|
||||
x = 10i;
|
||||
```
|
||||
|
||||
@ -538,7 +551,7 @@ format in a more detailed manner, there are a [wide number of options
|
||||
available](std/fmt/index.html). For now, we'll just stick to the default:
|
||||
integers aren't very complicated to print.
|
||||
|
||||
# If
|
||||
# `if`
|
||||
|
||||
Rust's take on `if` is not particularly complex, but it's much more like the
|
||||
`if` you'll find in a dynamically typed language than in a more traditional
|
||||
@ -584,7 +597,7 @@ let y = if x == 5i {
|
||||
10i
|
||||
} else {
|
||||
15i
|
||||
};
|
||||
}; // y: int
|
||||
```
|
||||
|
||||
Which we can (and probably should) write like this:
|
||||
@ -592,7 +605,7 @@ Which we can (and probably should) write like this:
|
||||
```{rust}
|
||||
let x = 5i;
|
||||
|
||||
let y = if x == 5i { 10i } else { 15i };
|
||||
let y = if x == 5i { 10i } else { 15i }; // y: int
|
||||
```
|
||||
|
||||
This reveals two interesting things about Rust: it is an expression-based
|
||||
@ -928,8 +941,8 @@ destructuring. You can assign one tuple into another, if they have the same
|
||||
arity and contained types.
|
||||
|
||||
```rust
|
||||
let mut x = (1i, 2i);
|
||||
let y = (2i, 3i);
|
||||
let mut x = (1i, 2i); // x: (int, int)
|
||||
let y = (2i, 3i); // y: (int, int)
|
||||
|
||||
x = y;
|
||||
```
|
||||
@ -981,7 +994,7 @@ struct Point {
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let origin = Point { x: 0i, y: 0i };
|
||||
let origin = Point { x: 0i, y: 0i }; // origin: Point
|
||||
|
||||
println!("The origin is at ({}, {})", origin.x, origin.y);
|
||||
}
|
||||
@ -1101,7 +1114,7 @@ fn main() {
|
||||
let x = 5i;
|
||||
let y = 10i;
|
||||
|
||||
let ordering = cmp(x, y);
|
||||
let ordering = cmp(x, y); // ordering: Ordering
|
||||
|
||||
if ordering == Less {
|
||||
println!("less");
|
||||
@ -1388,7 +1401,7 @@ Instead, it looks like this:
|
||||
|
||||
```{rust}
|
||||
for x in range(0i, 10i) {
|
||||
println!("{}", x);
|
||||
println!("{}", x); // x: int
|
||||
}
|
||||
```
|
||||
|
||||
@ -1423,8 +1436,8 @@ The other kind of looping construct in Rust is the `while` loop. It looks like
|
||||
this:
|
||||
|
||||
```{rust}
|
||||
let mut x = 5u;
|
||||
let mut done = false;
|
||||
let mut x = 5u; // mut x: uint
|
||||
let mut done = false; // mut done: bool
|
||||
|
||||
while !done {
|
||||
x += x - 3;
|
||||
@ -1520,7 +1533,7 @@ The first kind is a `&str`. This is pronounced a 'string slice.' String literals
|
||||
are of the type `&str`:
|
||||
|
||||
```{rust}
|
||||
let string = "Hello there.";
|
||||
let string = "Hello there."; // string: &str
|
||||
```
|
||||
|
||||
This string is statically allocated, meaning that it's saved inside our
|
||||
@ -1532,7 +1545,7 @@ A `String`, on the other hand, is an in-memory string. This string is
|
||||
growable, and is also guaranteed to be UTF-8.
|
||||
|
||||
```{rust}
|
||||
let mut s = "Hello".to_string();
|
||||
let mut s = "Hello".to_string(); // mut s: String
|
||||
println!("{}", s);
|
||||
|
||||
s.push_str(", world.");
|
||||
@ -1588,16 +1601,19 @@ things. The most basic is the **array**, a fixed-size list of elements of the
|
||||
same type. By default, arrays are immutable.
|
||||
|
||||
```{rust}
|
||||
let a = [1i, 2i, 3i];
|
||||
let mut m = [1i, 2i, 3i];
|
||||
let a = [1i, 2i, 3i]; // a: [int, ..3]
|
||||
let mut m = [1i, 2i, 3i]; // mut m: [int, ..3]
|
||||
```
|
||||
|
||||
You can create an array with a given number of elements, all initialized to the
|
||||
same value, with `[val, ..N]` syntax. The compiler ensures that arrays are
|
||||
always initialized.
|
||||
|
||||
There's a shorthand for initializing each element of an array to the same
|
||||
value. In this example, each element of `a` will be initialized to `0i`:
|
||||
|
||||
```{rust}
|
||||
let a = [0i, ..20]; // Shorthand for array of 20 elements all initialized to 0
|
||||
let a = [0i, ..20]; // a: [int, ..20]
|
||||
```
|
||||
|
||||
Arrays have type `[T,..N]`. We'll talk about this `T` notation later, when we
|
||||
@ -1608,7 +1624,7 @@ You can get the number of elements in an array `a` with `a.len()`, and use
|
||||
number in order:
|
||||
|
||||
```{rust}
|
||||
let a = [1i, 2, 3]; // Only the first item needs a type suffix
|
||||
let a = [1i, 2, 3]; // Only the first item needs a type suffix
|
||||
|
||||
println!("a has {} elements", a.len());
|
||||
for e in a.iter() {
|
||||
@ -1619,7 +1635,7 @@ for e in a.iter() {
|
||||
You can access a particular element of an array with **subscript notation**:
|
||||
|
||||
```{rust}
|
||||
let names = ["Graydon", "Brian", "Niko"];
|
||||
let names = ["Graydon", "Brian", "Niko"]; // names: [&str, 3]
|
||||
|
||||
println!("The second name is: {}", names[1]);
|
||||
```
|
||||
@ -1637,7 +1653,7 @@ later). Vectors are to arrays what `String` is to `&str`. You can create them
|
||||
with the `vec!` macro:
|
||||
|
||||
```{rust}
|
||||
let v = vec![1i, 2, 3];
|
||||
let v = vec![1i, 2, 3]; // v: Vec<int>
|
||||
```
|
||||
|
||||
(Notice that unlike the `println!` macro we've used in the past, we use square
|
||||
@ -1648,8 +1664,10 @@ You can get the length of, iterate over, and subscript vectors just like
|
||||
arrays. In addition, (mutable) vectors can grow automatically:
|
||||
|
||||
```{rust}
|
||||
let mut nums = vec![1i, 2, 3];
|
||||
let mut nums = vec![1i, 2, 3]; // mut nums: Vec<int>
|
||||
|
||||
nums.push(4);
|
||||
|
||||
println!("The length of nums is now {}", nums.len()); // Prints 4
|
||||
```
|
||||
|
||||
@ -1823,10 +1841,12 @@ use std::io;
|
||||
fn main() {
|
||||
println!("Type something!");
|
||||
|
||||
let input = io::stdin()
|
||||
.read_line()
|
||||
.ok()
|
||||
.expect("Failed to read line");
|
||||
// here, we'll show the types at each step
|
||||
|
||||
let input = io::stdin() // std::io::stdio::StdinReader
|
||||
.read_line() // IoResult<String>
|
||||
.ok() // Option<String>
|
||||
.expect("Failed to read line"); // String
|
||||
|
||||
println!("{}", input);
|
||||
}
|
||||
@ -1969,7 +1989,7 @@ use std::rand;
|
||||
fn main() {
|
||||
println!("Guess the number!");
|
||||
|
||||
let secret_number = (rand::random() % 100i) + 1i;
|
||||
let secret_number = (rand::random() % 100i) + 1i; // secret_number: int
|
||||
|
||||
println!("The secret number is: {}", secret_number);
|
||||
|
||||
@ -2262,8 +2282,8 @@ In this case, we say `x` is a `uint` explicitly, so Rust is able to properly
|
||||
tell `random()` what to generate. In a similar fashion, both of these work:
|
||||
|
||||
```{rust,ignore}
|
||||
let input_num = from_str::<uint>("5");
|
||||
let input_num: Option<uint> = from_str("5");
|
||||
let input_num = from_str::<uint>("5"); // input_num: Option<uint>
|
||||
let input_num: Option<uint> = from_str("5"); // input_num: Option<uint>
|
||||
```
|
||||
|
||||
Anyway, with us now converting our input to a number, our code looks like this:
|
||||
@ -4419,7 +4439,7 @@ for i in range(0u, nums.len()) {
|
||||
```
|
||||
|
||||
This is strictly worse than using an actual iterator. The `.iter()` method on
|
||||
vectors returns an iterator which iterates through a reference to each element
|
||||
vectors returns an iterator that iterates through a reference to each element
|
||||
of the vector in turn. So write this:
|
||||
|
||||
```{rust}
|
||||
|
@ -1,519 +0,0 @@
|
||||
#!/bin/sh
|
||||
# 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.
|
||||
|
||||
msg() {
|
||||
echo "install: $1"
|
||||
}
|
||||
|
||||
step_msg() {
|
||||
msg
|
||||
msg "$1"
|
||||
msg
|
||||
}
|
||||
|
||||
warn() {
|
||||
echo "install: WARNING: $1"
|
||||
}
|
||||
|
||||
err() {
|
||||
echo "install: error: $1"
|
||||
exit 1
|
||||
}
|
||||
|
||||
need_ok() {
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
err "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
need_cmd() {
|
||||
if command -v $1 >/dev/null 2>&1
|
||||
then msg "found $1"
|
||||
else err "need $1"
|
||||
fi
|
||||
}
|
||||
|
||||
putvar() {
|
||||
local T
|
||||
eval T=\$$1
|
||||
eval TLEN=\${#$1}
|
||||
if [ $TLEN -gt 35 ]
|
||||
then
|
||||
printf "install: %-20s := %.35s ...\n" $1 "$T"
|
||||
else
|
||||
printf "install: %-20s := %s %s\n" $1 "$T" "$2"
|
||||
fi
|
||||
}
|
||||
|
||||
valopt() {
|
||||
VAL_OPTIONS="$VAL_OPTIONS $1"
|
||||
|
||||
local OP=$1
|
||||
local DEFAULT=$2
|
||||
shift
|
||||
shift
|
||||
local DOC="$*"
|
||||
if [ $HELP -eq 0 ]
|
||||
then
|
||||
local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_')
|
||||
local V="CFG_${UOP}"
|
||||
eval $V="$DEFAULT"
|
||||
for arg in $CFG_ARGS
|
||||
do
|
||||
if echo "$arg" | grep -q -- "--$OP="
|
||||
then
|
||||
val=$(echo "$arg" | cut -f2 -d=)
|
||||
eval $V=$val
|
||||
fi
|
||||
done
|
||||
putvar $V
|
||||
else
|
||||
if [ -z "$DEFAULT" ]
|
||||
then
|
||||
DEFAULT="<none>"
|
||||
fi
|
||||
OP="${OP}=[${DEFAULT}]"
|
||||
printf " --%-30s %s\n" "$OP" "$DOC"
|
||||
fi
|
||||
}
|
||||
|
||||
opt() {
|
||||
BOOL_OPTIONS="$BOOL_OPTIONS $1"
|
||||
|
||||
local OP=$1
|
||||
local DEFAULT=$2
|
||||
shift
|
||||
shift
|
||||
local DOC="$*"
|
||||
local FLAG=""
|
||||
|
||||
if [ $DEFAULT -eq 0 ]
|
||||
then
|
||||
FLAG="enable"
|
||||
else
|
||||
FLAG="disable"
|
||||
DOC="don't $DOC"
|
||||
fi
|
||||
|
||||
if [ $HELP -eq 0 ]
|
||||
then
|
||||
for arg in $CFG_ARGS
|
||||
do
|
||||
if [ "$arg" = "--${FLAG}-${OP}" ]
|
||||
then
|
||||
OP=$(echo $OP | tr 'a-z-' 'A-Z_')
|
||||
FLAG=$(echo $FLAG | tr 'a-z' 'A-Z')
|
||||
local V="CFG_${FLAG}_${OP}"
|
||||
eval $V=1
|
||||
putvar $V
|
||||
fi
|
||||
done
|
||||
else
|
||||
if [ ! -z "$META" ]
|
||||
then
|
||||
OP="$OP=<$META>"
|
||||
fi
|
||||
printf " --%-30s %s\n" "$FLAG-$OP" "$DOC"
|
||||
fi
|
||||
}
|
||||
|
||||
flag() {
|
||||
BOOL_OPTIONS="$BOOL_OPTIONS $1"
|
||||
|
||||
local OP=$1
|
||||
shift
|
||||
local DOC="$*"
|
||||
|
||||
if [ $HELP -eq 0 ]
|
||||
then
|
||||
for arg in $CFG_ARGS
|
||||
do
|
||||
if [ "$arg" = "--${OP}" ]
|
||||
then
|
||||
OP=$(echo $OP | tr 'a-z-' 'A-Z_')
|
||||
local V="CFG_${OP}"
|
||||
eval $V=1
|
||||
putvar $V
|
||||
fi
|
||||
done
|
||||
else
|
||||
if [ ! -z "$META" ]
|
||||
then
|
||||
OP="$OP=<$META>"
|
||||
fi
|
||||
printf " --%-30s %s\n" "$OP" "$DOC"
|
||||
fi
|
||||
}
|
||||
|
||||
validate_opt () {
|
||||
for arg in $CFG_ARGS
|
||||
do
|
||||
isArgValid=0
|
||||
for option in $BOOL_OPTIONS
|
||||
do
|
||||
if test --disable-$option = $arg
|
||||
then
|
||||
isArgValid=1
|
||||
fi
|
||||
if test --enable-$option = $arg
|
||||
then
|
||||
isArgValid=1
|
||||
fi
|
||||
if test --$option = $arg
|
||||
then
|
||||
isArgValid=1
|
||||
fi
|
||||
done
|
||||
for option in $VAL_OPTIONS
|
||||
do
|
||||
if echo "$arg" | grep -q -- "--$option="
|
||||
then
|
||||
isArgValid=1
|
||||
fi
|
||||
done
|
||||
if [ "$arg" = "--help" ]
|
||||
then
|
||||
echo
|
||||
echo "No more help available for Configure options,"
|
||||
echo "check the Wiki or join our IRC channel"
|
||||
break
|
||||
else
|
||||
if test $isArgValid -eq 0
|
||||
then
|
||||
err "Option '$arg' is not recognized"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
absolutify() {
|
||||
FILE_PATH="${1}"
|
||||
FILE_PATH_DIRNAME="$(dirname ${FILE_PATH})"
|
||||
FILE_PATH_BASENAME="$(basename ${FILE_PATH})"
|
||||
FILE_ABS_PATH="$(cd ${FILE_PATH_DIRNAME} && pwd)"
|
||||
FILE_PATH="${FILE_ABS_PATH}/${FILE_PATH_BASENAME}"
|
||||
# This is the return value
|
||||
ABSOLUTIFIED="${FILE_PATH}"
|
||||
}
|
||||
|
||||
msg "looking for install programs"
|
||||
need_cmd mkdir
|
||||
need_cmd printf
|
||||
need_cmd cut
|
||||
need_cmd grep
|
||||
need_cmd uname
|
||||
need_cmd tr
|
||||
need_cmd sed
|
||||
|
||||
CFG_SRC_DIR="$(cd $(dirname $0) && pwd)"
|
||||
CFG_SELF="$0"
|
||||
CFG_ARGS="$@"
|
||||
|
||||
HELP=0
|
||||
if [ "$1" = "--help" ]
|
||||
then
|
||||
HELP=1
|
||||
shift
|
||||
echo
|
||||
echo "Usage: $CFG_SELF [options]"
|
||||
echo
|
||||
echo "Options:"
|
||||
echo
|
||||
else
|
||||
step_msg "processing $CFG_SELF args"
|
||||
fi
|
||||
|
||||
# Check for mingw or cygwin in order to special case $CFG_LIBDIR_RELATIVE.
|
||||
# This logic is duplicated from configure in order to get the correct libdir
|
||||
# for Windows installs.
|
||||
CFG_OSTYPE=$(uname -s)
|
||||
|
||||
case $CFG_OSTYPE in
|
||||
|
||||
MINGW32*)
|
||||
CFG_OSTYPE=pc-mingw32
|
||||
;;
|
||||
|
||||
MINGW64*)
|
||||
# msys2, MSYSTEM=MINGW64
|
||||
CFG_OSTYPE=w64-mingw32
|
||||
;;
|
||||
|
||||
# Thad's Cygwin identifers below
|
||||
|
||||
# Vista 32 bit
|
||||
CYGWIN_NT-6.0)
|
||||
CFG_OSTYPE=pc-mingw32
|
||||
;;
|
||||
|
||||
# Vista 64 bit
|
||||
CYGWIN_NT-6.0-WOW64)
|
||||
CFG_OSTYPE=w64-mingw32
|
||||
;;
|
||||
|
||||
# Win 7 32 bit
|
||||
CYGWIN_NT-6.1)
|
||||
CFG_OSTYPE=pc-mingw32
|
||||
;;
|
||||
|
||||
# Win 7 64 bit
|
||||
CYGWIN_NT-6.1-WOW64)
|
||||
CFG_OSTYPE=w64-mingw32
|
||||
;;
|
||||
esac
|
||||
|
||||
OPTIONS=""
|
||||
BOOL_OPTIONS=""
|
||||
VAL_OPTIONS=""
|
||||
|
||||
# On windows we just store the libraries in the bin directory because
|
||||
# there's no rpath. This is where the build system itself puts libraries;
|
||||
# --libdir is used to configure the installation directory.
|
||||
# FIXME: Thise needs to parameterized over target triples. Do it in platform.mk
|
||||
CFG_LIBDIR_RELATIVE=lib
|
||||
if [ "$CFG_OSTYPE" = "pc-mingw32" ] || [ "$CFG_OSTYPE" = "w64-mingw32" ]
|
||||
then
|
||||
CFG_LIBDIR_RELATIVE=bin
|
||||
fi
|
||||
|
||||
if [ "$CFG_OSTYPE" = "pc-mingw32" ] || [ "$CFG_OSTYPE" = "w64-mingw32" ]
|
||||
then
|
||||
CFG_LD_PATH_VAR=PATH
|
||||
CFG_OLD_LD_PATH_VAR=$PATH
|
||||
elif [ "$CFG_OSTYPE" = "Darwin" ]
|
||||
then
|
||||
CFG_LD_PATH_VAR=DYLD_LIBRARY_PATH
|
||||
CFG_OLD_LD_PATH_VAR=$DYLD_LIBRARY_PATH
|
||||
else
|
||||
CFG_LD_PATH_VAR=LD_LIBRARY_PATH
|
||||
CFG_OLD_LD_PATH_VAR=$LD_LIBRARY_PATH
|
||||
fi
|
||||
|
||||
flag uninstall "only uninstall from the installation prefix"
|
||||
opt verify 1 "verify that the installed binaries run correctly"
|
||||
valopt prefix "/usr/local" "set installation prefix"
|
||||
# NB This is exactly the same definition as in `configure`.
|
||||
valopt libdir "${CFG_PREFIX}/${CFG_LIBDIR_RELATIVE}" "install libraries"
|
||||
case "$CFG_LIBDIR" in
|
||||
"$CFG_PREFIX"/*) CAT_INC=2;;
|
||||
"$CFG_PREFIX"*) CAT_INC=1;;
|
||||
*)
|
||||
err "libdir must begin with the prefix. Use --prefix to set it accordingly.";;
|
||||
esac
|
||||
CFG_LIBDIR_RELATIVE=`echo ${CFG_LIBDIR} | cut -c$((${#CFG_PREFIX}+${CAT_INC}))-`
|
||||
|
||||
valopt mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
|
||||
|
||||
if [ $HELP -eq 1 ]
|
||||
then
|
||||
echo
|
||||
exit 0
|
||||
fi
|
||||
|
||||
step_msg "validating $CFG_SELF args"
|
||||
validate_opt
|
||||
|
||||
|
||||
# OK, let's get installing ...
|
||||
|
||||
# Sanity check: can we run the binaries?
|
||||
if [ -z "${CFG_DISABLE_VERIFY}" ]
|
||||
then
|
||||
# Don't do this if uninstalling. Failure here won't help in any way.
|
||||
if [ -z "${CFG_UNINSTALL}" ]
|
||||
then
|
||||
msg "verifying platform can run binaries"
|
||||
export $CFG_LD_PATH_VAR="${CFG_SRC_DIR}/lib:$CFG_OLD_LD_PATH_VAR"
|
||||
"${CFG_SRC_DIR}/bin/rustc" --version > /dev/null
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
err "can't execute rustc binary on this platform"
|
||||
fi
|
||||
export $CFG_LD_PATH_VAR=$CFG_OLD_LD_PATH_VAR
|
||||
fi
|
||||
fi
|
||||
|
||||
# Sanity check: can we can write to the destination?
|
||||
msg "verifying destination is writable"
|
||||
umask 022 && mkdir -p "${CFG_LIBDIR}"
|
||||
need_ok "can't write to destination. consider \`sudo\`."
|
||||
touch "${CFG_LIBDIR}/rust-install-probe" > /dev/null
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
err "can't write to destination. consider \`sudo\`."
|
||||
fi
|
||||
rm -f "${CFG_LIBDIR}/rust-install-probe"
|
||||
need_ok "failed to remove install probe"
|
||||
|
||||
# Sanity check: don't install to the directory containing the installer.
|
||||
# That would surely cause chaos.
|
||||
msg "verifying destination is not the same as source"
|
||||
INSTALLER_DIR="$(cd $(dirname $0) && pwd)"
|
||||
PREFIX_DIR="$(cd ${CFG_PREFIX} && pwd)"
|
||||
if [ "${INSTALLER_DIR}" = "${PREFIX_DIR}" ]
|
||||
then
|
||||
err "can't install to same directory as installer"
|
||||
fi
|
||||
|
||||
# Using an absolute path to libdir in a few places so that the status
|
||||
# messages are consistently using absolute paths.
|
||||
absolutify "${CFG_LIBDIR}"
|
||||
ABS_LIBDIR="${ABSOLUTIFIED}"
|
||||
|
||||
# The file name of the manifest we're going to create during install
|
||||
INSTALLED_MANIFEST="${ABS_LIBDIR}/rustlib/manifest"
|
||||
|
||||
# First, uninstall from the installation prefix.
|
||||
# Errors are warnings - try to rm everything in the manifest even if some fail.
|
||||
if [ -f "${INSTALLED_MANIFEST}" ]
|
||||
then
|
||||
# Iterate through installed manifest and remove files
|
||||
while read p; do
|
||||
# The installed manifest contains absolute paths
|
||||
msg "removing $p"
|
||||
if [ -f "$p" ]
|
||||
then
|
||||
rm -f "$p"
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
warn "failed to remove $p"
|
||||
fi
|
||||
else
|
||||
warn "supposedly installed file $p does not exist!"
|
||||
fi
|
||||
done < "${INSTALLED_MANIFEST}"
|
||||
|
||||
# If we fail to remove rustlib below, then the installed manifest will
|
||||
# still be full; the installed manifest needs to be empty before install.
|
||||
msg "removing ${INSTALLED_MANIFEST}"
|
||||
rm -f "${INSTALLED_MANIFEST}"
|
||||
# For the above reason, this is a hard error
|
||||
need_ok "failed to remove installed manifest"
|
||||
|
||||
# Remove 'rustlib' directory
|
||||
msg "removing ${ABS_LIBDIR}/rustlib"
|
||||
rm -Rf "${ABS_LIBDIR}/rustlib"
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
warn "failed to remove rustlib"
|
||||
fi
|
||||
else
|
||||
# There's no manifest. If we were asked to uninstall, then that's a problem.
|
||||
if [ -n "${CFG_UNINSTALL}" ]
|
||||
then
|
||||
err "unable to find installation manifest at ${CFG_LIBDIR}/rustlib"
|
||||
fi
|
||||
fi
|
||||
|
||||
# If we're only uninstalling then exit
|
||||
if [ -n "${CFG_UNINSTALL}" ]
|
||||
then
|
||||
echo
|
||||
echo " Rust is uninstalled. Have a nice day."
|
||||
echo
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Create the installed manifest, which we will fill in with absolute file paths
|
||||
mkdir -p "${CFG_LIBDIR}/rustlib"
|
||||
need_ok "failed to create rustlib"
|
||||
touch "${INSTALLED_MANIFEST}"
|
||||
need_ok "failed to create installed manifest"
|
||||
|
||||
# Now install, iterate through the new manifest and copy files
|
||||
while read p; do
|
||||
|
||||
# Decide the destination of the file
|
||||
FILE_INSTALL_PATH="${CFG_PREFIX}/$p"
|
||||
|
||||
if echo "$p" | grep "^${CFG_LIBDIR_RELATIVE}/" > /dev/null
|
||||
then
|
||||
pp=`echo $p | sed "s%^${CFG_LIBDIR_RELATIVE}/%%"`
|
||||
FILE_INSTALL_PATH="${CFG_LIBDIR}/$pp"
|
||||
fi
|
||||
|
||||
if echo "$p" | grep "^share/man/" > /dev/null
|
||||
then
|
||||
pp=`echo $p | sed 's/^share\/man\///'`
|
||||
FILE_INSTALL_PATH="${CFG_MANDIR}/$pp"
|
||||
fi
|
||||
|
||||
# Make sure there's a directory for it
|
||||
umask 022 && mkdir -p "$(dirname ${FILE_INSTALL_PATH})"
|
||||
need_ok "directory creation failed"
|
||||
|
||||
# Make the path absolute so we can uninstall it later without
|
||||
# starting from the installation cwd
|
||||
absolutify "${FILE_INSTALL_PATH}"
|
||||
FILE_INSTALL_PATH="${ABSOLUTIFIED}"
|
||||
|
||||
# Install the file
|
||||
msg "${FILE_INSTALL_PATH}"
|
||||
if echo "$p" | grep "^bin/" > /dev/null
|
||||
then
|
||||
install -m755 "${CFG_SRC_DIR}/$p" "${FILE_INSTALL_PATH}"
|
||||
else
|
||||
install -m644 "${CFG_SRC_DIR}/$p" "${FILE_INSTALL_PATH}"
|
||||
fi
|
||||
need_ok "file creation failed"
|
||||
|
||||
# Update the manifest
|
||||
echo "${FILE_INSTALL_PATH}" >> "${INSTALLED_MANIFEST}"
|
||||
need_ok "failed to update manifest"
|
||||
|
||||
# The manifest lists all files to install
|
||||
done < "${CFG_SRC_DIR}/${CFG_LIBDIR_RELATIVE}/rustlib/manifest.in"
|
||||
|
||||
# Run ldconfig to make dynamic libraries available to the linker
|
||||
if [ "$CFG_OSTYPE" = "Linux" ]
|
||||
then
|
||||
ldconfig
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
warn "failed to run ldconfig."
|
||||
warn "this may happen when not installing as root and may be fine"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Sanity check: can we run the installed binaries?
|
||||
#
|
||||
# As with the verification above, make sure the right LD_LIBRARY_PATH-equivalent
|
||||
# is in place. Try first without this variable, and if that fails try again with
|
||||
# the variable. If the second time tries, print a hopefully helpful message to
|
||||
# add something to the appropriate environment variable.
|
||||
if [ -z "${CFG_DISABLE_VERIFY}" ]
|
||||
then
|
||||
msg "verifying installed binaries are executable"
|
||||
"${CFG_PREFIX}/bin/rustc" --version 2> /dev/null 1> /dev/null
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
export $CFG_LD_PATH_VAR="${CFG_PREFIX}/lib:$CFG_OLD_LD_PATH_VAR"
|
||||
"${CFG_PREFIX}/bin/rustc" --version > /dev/null
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
ERR="can't execute installed rustc binary. "
|
||||
ERR="${ERR}installation may be broken. "
|
||||
ERR="${ERR}if this is expected then rerun install.sh with \`--disable-verify\` "
|
||||
ERR="${ERR}or \`make install\` with \`--disable-verify-install\`"
|
||||
err "${ERR}"
|
||||
else
|
||||
echo
|
||||
echo " Note: please ensure '${CFG_PREFIX}/lib' is added to ${CFG_LD_PATH_VAR}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
echo " Rust is ready to roll."
|
||||
echo
|
||||
|
||||
|
@ -107,7 +107,7 @@ def make_win_dist(rust_root, gcc_root, target_triple):
|
||||
for src in target_tools:
|
||||
shutil.copy(src, target_bin_dir)
|
||||
|
||||
# Copy platform libs to platform-spcific lib directory
|
||||
# Copy platform libs to platform-specific lib directory
|
||||
target_lib_dir = os.path.join(gcc_root, "bin", "rustlib", target_triple, "lib")
|
||||
if not os.path.exists(target_lib_dir):
|
||||
os.makedirs(target_lib_dir)
|
||||
|
@ -231,6 +231,7 @@ validate_opt() {
|
||||
|
||||
probe_need CFG_CURL curl
|
||||
probe_need CFG_TAR tar
|
||||
probe_need CFG_FILE file
|
||||
|
||||
CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
|
||||
CFG_SELF="$0"
|
||||
@ -359,7 +360,7 @@ esac
|
||||
# Detect 64 bit linux systems with 32 bit userland and force 32 bit compilation
|
||||
if [ $CFG_OSTYPE = unknown-linux-gnu -a $CFG_CPUTYPE = x86_64 ]
|
||||
then
|
||||
file -L "$SHELL" | grep -q "x86[_-]64"
|
||||
"${CFG_FILE}" -L "$SHELL" | grep -q "x86[_-]64"
|
||||
if [ $? != 0 ]; then
|
||||
CFG_CPUTYPE=i686
|
||||
fi
|
||||
|
@ -173,10 +173,10 @@ fn parse_antlr_token(s: &str, tokens: &HashMap<String, token::Token>) -> TokenAn
|
||||
);
|
||||
|
||||
let m = re.captures(s).expect(format!("The regex didn't match {}", s).as_slice());
|
||||
let start = m.name("start");
|
||||
let end = m.name("end");
|
||||
let toknum = m.name("toknum");
|
||||
let content = m.name("content");
|
||||
let start = m.name("start").unwrap_or("");
|
||||
let end = m.name("end").unwrap_or("");
|
||||
let toknum = m.name("toknum").unwrap_or("");
|
||||
let content = m.name("content").unwrap_or("");
|
||||
|
||||
let proto_tok = tokens.get(toknum).expect(format!("didn't find token {} in the map",
|
||||
toknum).as_slice());
|
||||
|
@ -14,6 +14,7 @@
|
||||
//! between tasks.
|
||||
|
||||
use core::atomic;
|
||||
use core::borrow::BorrowFrom;
|
||||
use core::clone::Clone;
|
||||
use core::fmt::{mod, Show};
|
||||
use core::cmp::{Eq, Ord, PartialEq, PartialOrd, Ordering};
|
||||
@ -155,6 +156,12 @@ impl<T> Clone for Arc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> BorrowFrom<Arc<T>> for T {
|
||||
fn borrow_from(owned: &Arc<T>) -> &T {
|
||||
&**owned
|
||||
}
|
||||
}
|
||||
|
||||
#[experimental = "Deref is experimental."]
|
||||
impl<T> Deref<T> for Arc<T> {
|
||||
#[inline]
|
||||
@ -316,7 +323,9 @@ impl<T: fmt::Show> fmt::Show for Arc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<T: Default + Sync + Send> Default for Arc<T> {
|
||||
#[stable]
|
||||
fn default() -> Arc<T> { Arc::new(Default::default()) }
|
||||
}
|
||||
|
||||
|
@ -45,11 +45,15 @@ pub static HEAP: () = ();
|
||||
#[unstable = "custom allocators will add an additional type parameter (with default)"]
|
||||
pub struct Box<T>(*mut T);
|
||||
|
||||
#[stable]
|
||||
impl<T: Default> Default for Box<T> {
|
||||
#[stable]
|
||||
fn default() -> Box<T> { box Default::default() }
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<T> Default for Box<[T]> {
|
||||
#[stable]
|
||||
fn default() -> Box<[T]> { box [] }
|
||||
}
|
||||
|
||||
|
@ -448,6 +448,7 @@ impl<T: Default> Default for Rc<T> {
|
||||
/// let x: Rc<int> = Default::default();
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable]
|
||||
fn default() -> Rc<T> {
|
||||
Rc::new(Default::default())
|
||||
}
|
||||
|
@ -172,8 +172,10 @@ pub struct BinaryHeap<T> {
|
||||
data: Vec<T>,
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<T: Ord> Default for BinaryHeap<T> {
|
||||
#[inline]
|
||||
#[stable]
|
||||
fn default() -> BinaryHeap<T> { BinaryHeap::new() }
|
||||
}
|
||||
|
||||
|
@ -824,8 +824,10 @@ pub fn from_fn<F>(len: uint, mut f: F) -> Bitv where F: FnMut(uint) -> bool {
|
||||
bitv
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl Default for Bitv {
|
||||
#[inline]
|
||||
#[stable]
|
||||
fn default() -> Bitv { Bitv::new() }
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@ use std::hash::{Writer, Hash};
|
||||
use core::default::Default;
|
||||
use core::{iter, fmt, mem};
|
||||
use core::fmt::Show;
|
||||
use core::iter::Map;
|
||||
|
||||
use ring_buf::RingBuf;
|
||||
|
||||
@ -110,12 +111,14 @@ pub struct MoveEntries<K, V> {
|
||||
}
|
||||
|
||||
/// An iterator over a BTreeMap's keys.
|
||||
pub type Keys<'a, K, V> =
|
||||
iter::Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>;
|
||||
pub struct Keys<'a, K: 'a, V: 'a> {
|
||||
inner: Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
|
||||
}
|
||||
|
||||
/// An iterator over a BTreeMap's values.
|
||||
pub type Values<'a, K, V> =
|
||||
iter::Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>;
|
||||
pub struct Values<'a, K: 'a, V: 'a> {
|
||||
inner: Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
|
||||
}
|
||||
|
||||
/// A view into a single entry in a map, which may either be vacant or occupied.
|
||||
pub enum Entry<'a, K:'a, V:'a> {
|
||||
@ -829,7 +832,9 @@ impl<S: Writer, K: Hash<S>, V: Hash<S>> Hash<S> for BTreeMap<K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<K: Ord, V> Default for BTreeMap<K, V> {
|
||||
#[stable]
|
||||
fn default() -> BTreeMap<K, V> {
|
||||
BTreeMap::new()
|
||||
}
|
||||
@ -1054,6 +1059,25 @@ impl<K, V> DoubleEndedIterator<(K, V)> for MoveEntries<K, V> {
|
||||
impl<K, V> ExactSizeIterator<(K, V)> for MoveEntries<K, V> {}
|
||||
|
||||
|
||||
impl<'a, K, V> Iterator<&'a K> for Keys<'a, K, V> {
|
||||
fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
|
||||
}
|
||||
impl<'a, K, V> DoubleEndedIterator<&'a K> for Keys<'a, K, V> {
|
||||
fn next_back(&mut self) -> Option<(&'a K)> { self.inner.next_back() }
|
||||
}
|
||||
impl<'a, K, V> ExactSizeIterator<&'a K> for Keys<'a, K, V> {}
|
||||
|
||||
|
||||
impl<'a, K, V> Iterator<&'a V> for Values<'a, K, V> {
|
||||
fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
|
||||
}
|
||||
impl<'a, K, V> DoubleEndedIterator<&'a V> for Values<'a, K, V> {
|
||||
fn next_back(&mut self) -> Option<(&'a V)> { self.inner.next_back() }
|
||||
}
|
||||
impl<'a, K, V> ExactSizeIterator<&'a V> for Values<'a, K, V> {}
|
||||
|
||||
|
||||
impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
|
||||
/// Sets the value of the entry with the VacantEntry's key,
|
||||
@ -1204,7 +1228,7 @@ impl<K, V> BTreeMap<K, V> {
|
||||
pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
|
||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||
|
||||
self.iter().map(first)
|
||||
Keys { inner: self.iter().map(first) }
|
||||
}
|
||||
|
||||
/// Gets an iterator over the values of the map.
|
||||
@ -1225,7 +1249,7 @@ impl<K, V> BTreeMap<K, V> {
|
||||
pub fn values<'a>(&'a self) -> Values<'a, K, V> {
|
||||
fn second<A, B>((_, b): (A, B)) -> B { b }
|
||||
|
||||
self.iter().map(second)
|
||||
Values { inner: self.iter().map(second) }
|
||||
}
|
||||
|
||||
/// Return the number of elements in the map.
|
||||
|
@ -19,7 +19,6 @@ pub use self::TraversalItem::*;
|
||||
use core::prelude::*;
|
||||
|
||||
use core::{slice, mem, ptr, cmp, num, raw};
|
||||
use core::kinds::marker;
|
||||
use core::iter::Zip;
|
||||
use core::borrow::BorrowFrom;
|
||||
use alloc::heap;
|
||||
@ -176,7 +175,6 @@ fn calculate_offsets_generic<K, V>(capacity: uint, is_leaf: bool) -> (uint, uint
|
||||
struct RawItems<T> {
|
||||
head: *const T,
|
||||
tail: *const T,
|
||||
marker: marker::NoCopy
|
||||
}
|
||||
|
||||
impl<T> RawItems<T> {
|
||||
@ -189,13 +187,11 @@ impl<T> RawItems<T> {
|
||||
RawItems {
|
||||
head: ptr,
|
||||
tail: (ptr as uint + len) as *const T,
|
||||
marker: marker::NoCopy
|
||||
}
|
||||
} else {
|
||||
RawItems {
|
||||
head: ptr,
|
||||
tail: ptr.offset(len as int),
|
||||
marker: marker::NoCopy
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ use btree_map::{BTreeMap, Keys, MoveEntries};
|
||||
use std::hash::Hash;
|
||||
use core::borrow::BorrowFrom;
|
||||
use core::default::Default;
|
||||
use core::{iter, fmt};
|
||||
use core::iter::Peekable;
|
||||
use core::fmt;
|
||||
use core::iter::{Peekable, Map};
|
||||
use core::fmt::Show;
|
||||
|
||||
// FIXME(conventions): implement bounded iterators
|
||||
@ -33,11 +33,14 @@ pub struct BTreeSet<T>{
|
||||
}
|
||||
|
||||
/// An iterator over a BTreeSet's items.
|
||||
pub type Items<'a, T> = Keys<'a, T, ()>;
|
||||
pub struct Items<'a, T: 'a> {
|
||||
iter: Keys<'a, T, ()>
|
||||
}
|
||||
|
||||
/// An owning iterator over a BTreeSet's items.
|
||||
pub type MoveItems<T> =
|
||||
iter::Map<(T, ()), T, MoveEntries<T, ()>, fn((T, ())) -> T>;
|
||||
pub struct MoveItems<T> {
|
||||
iter: Map<(T, ()), T, MoveEntries<T, ()>, fn((T, ())) -> T>
|
||||
}
|
||||
|
||||
/// A lazy iterator producing elements in the set difference (in-order).
|
||||
pub struct DifferenceItems<'a, T:'a> {
|
||||
@ -105,7 +108,7 @@ impl<T> BTreeSet<T> {
|
||||
/// ```
|
||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||
pub fn iter<'a>(&'a self) -> Items<'a, T> {
|
||||
self.map.keys()
|
||||
Items { iter: self.map.keys() }
|
||||
}
|
||||
|
||||
/// Gets an iterator for moving out the BtreeSet's contents.
|
||||
@ -124,7 +127,7 @@ impl<T> BTreeSet<T> {
|
||||
pub fn into_iter(self) -> MoveItems<T> {
|
||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||
|
||||
self.map.into_iter().map(first)
|
||||
MoveItems { iter: self.map.into_iter().map(first) }
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,7 +439,9 @@ impl<T: Ord> Extend<T> for BTreeSet<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<T: Ord> Default for BTreeSet<T> {
|
||||
#[stable]
|
||||
fn default() -> BTreeSet<T> {
|
||||
BTreeSet::new()
|
||||
}
|
||||
@ -635,6 +640,25 @@ impl<T: Show> Show for BTreeSet<T> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T> Iterator<&'a T> for Items<'a, T> {
|
||||
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
|
||||
}
|
||||
impl<'a, T> DoubleEndedIterator<&'a T> for Items<'a, T> {
|
||||
fn next_back(&mut self) -> Option<&'a T> { self.iter.next_back() }
|
||||
}
|
||||
impl<'a, T> ExactSizeIterator<&'a T> for Items<'a, T> {}
|
||||
|
||||
|
||||
impl<T> Iterator<T> for MoveItems<T> {
|
||||
fn next(&mut self) -> Option<T> { self.iter.next() }
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
|
||||
}
|
||||
impl<T> DoubleEndedIterator<T> for MoveItems<T> {
|
||||
fn next_back(&mut self) -> Option<T> { self.iter.next_back() }
|
||||
}
|
||||
impl<T> ExactSizeIterator<T> for MoveItems<T> {}
|
||||
|
||||
/// Compare `x` and `y`, but return `short` if x is None and `long` if y is None
|
||||
fn cmp_opt<T: Ord>(x: Option<&T>, y: Option<&T>,
|
||||
short: Ordering, long: Ordering) -> Ordering {
|
||||
|
@ -192,8 +192,10 @@ impl<T> DList<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<T> Default for DList<T> {
|
||||
#[inline]
|
||||
#[stable]
|
||||
fn default() -> DList<T> { DList::new() }
|
||||
}
|
||||
|
||||
|
@ -68,7 +68,9 @@ impl<T> Drop for RingBuf<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<T> Default for RingBuf<T> {
|
||||
#[stable]
|
||||
#[inline]
|
||||
fn default() -> RingBuf<T> { RingBuf::new() }
|
||||
}
|
||||
@ -102,17 +104,15 @@ impl<T> RingBuf<T> {
|
||||
|
||||
/// Copies a contiguous block of memory len long from src to dst
|
||||
#[inline]
|
||||
fn copy(&self, dst: uint, src: uint, len: uint) {
|
||||
unsafe {
|
||||
debug_assert!(dst + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
|
||||
self.cap);
|
||||
debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
|
||||
self.cap);
|
||||
ptr::copy_memory(
|
||||
self.ptr.offset(dst as int),
|
||||
self.ptr.offset(src as int) as *const T,
|
||||
len);
|
||||
}
|
||||
unsafe fn copy(&self, dst: uint, src: uint, len: uint) {
|
||||
debug_assert!(dst + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
|
||||
self.cap);
|
||||
debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
|
||||
self.cap);
|
||||
ptr::copy_memory(
|
||||
self.ptr.offset(dst as int),
|
||||
self.ptr.offset(src as int) as *const T,
|
||||
len);
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,7 +377,7 @@ impl<T> RingBuf<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a front-to-back iterator which returns mutable references.
|
||||
/// Returns a front-to-back iterator that returns mutable references.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -402,7 +402,6 @@ impl<T> RingBuf<T> {
|
||||
cap: self.cap,
|
||||
ptr: self.ptr,
|
||||
marker: marker::ContravariantLifetime::<'a>,
|
||||
marker2: marker::NoCopy
|
||||
}
|
||||
}
|
||||
|
||||
@ -732,7 +731,7 @@ impl<T> RingBuf<T> {
|
||||
|
||||
self.tail = self.wrap_index(self.tail - 1);
|
||||
},
|
||||
(true, true, _) => {
|
||||
(true, true, _) => unsafe {
|
||||
// contiguous, insert closer to tail:
|
||||
//
|
||||
// T I H
|
||||
@ -752,13 +751,15 @@ impl<T> RingBuf<T> {
|
||||
// [o I A o o o o o . . . . . . . o]
|
||||
// M M
|
||||
|
||||
let old_tail = self.tail;
|
||||
self.tail = self.wrap_index(self.tail - 1);
|
||||
let new_tail = self.wrap_index(self.tail - 1);
|
||||
|
||||
self.copy(self.tail, old_tail, 1);
|
||||
self.copy(old_tail, old_tail + 1, i);
|
||||
self.copy(new_tail, self.tail, 1);
|
||||
// Already moved the tail, so we only copy `i - 1` elements.
|
||||
self.copy(self.tail, self.tail + 1, i - 1);
|
||||
|
||||
self.tail = new_tail;
|
||||
},
|
||||
(true, false, _) => {
|
||||
(true, false, _) => unsafe {
|
||||
// contiguous, insert closer to head:
|
||||
//
|
||||
// T I H
|
||||
@ -768,12 +769,11 @@ impl<T> RingBuf<T> {
|
||||
// [. . . o o o o I A o o . . . . .]
|
||||
// M M M
|
||||
|
||||
let old_head = self.head;
|
||||
self.copy(idx + 1, idx, self.head - idx);
|
||||
self.head = self.wrap_index(self.head + 1);
|
||||
self.copy(idx + 1, idx, old_head - idx);
|
||||
},
|
||||
(false, true, true) => {
|
||||
// discontiguous, tail section, insert closer to tail:
|
||||
(false, true, true) => unsafe {
|
||||
// discontiguous, insert closer to tail, tail section:
|
||||
//
|
||||
// H T I
|
||||
// [o o o o o o . . . . . o o A o o]
|
||||
@ -782,12 +782,11 @@ impl<T> RingBuf<T> {
|
||||
// [o o o o o o . . . . o o I A o o]
|
||||
// M M
|
||||
|
||||
let old_tail = self.tail;
|
||||
self.tail = self.tail - 1;
|
||||
self.copy(self.tail, old_tail, i);
|
||||
self.copy(self.tail - 1, self.tail, i);
|
||||
self.tail -= 1;
|
||||
},
|
||||
(false, false, true) => {
|
||||
// discontiguous, tail section, insert closer to head:
|
||||
(false, false, true) => unsafe {
|
||||
// discontiguous, insert closer to head, tail section:
|
||||
//
|
||||
// H T I
|
||||
// [o o . . . . . . . o o o o o A o]
|
||||
@ -796,20 +795,19 @@ impl<T> RingBuf<T> {
|
||||
// [o o o . . . . . . o o o o o I A]
|
||||
// M M M M
|
||||
|
||||
let old_head = self.head;
|
||||
self.head = self.head + 1;
|
||||
|
||||
// copy elements up to new head
|
||||
self.copy(1, 0, old_head);
|
||||
self.copy(1, 0, self.head);
|
||||
|
||||
// copy last element into empty spot at bottom of buffer
|
||||
self.copy(0, self.cap - 1, 1);
|
||||
|
||||
// move elements from idx to end forward not including ^ element
|
||||
self.copy(idx + 1, idx, self.cap - 1 - idx);
|
||||
|
||||
self.head += 1;
|
||||
},
|
||||
(false, true, false) if idx == 0 => {
|
||||
// discontiguous, head section, insert is closer to tail,
|
||||
(false, true, false) if idx == 0 => unsafe {
|
||||
// discontiguous, insert is closer to tail, head section,
|
||||
// and is at index zero in the internal buffer:
|
||||
//
|
||||
// I H T
|
||||
@ -819,16 +817,16 @@ impl<T> RingBuf<T> {
|
||||
// [A o o o o o o o o o . . o o o I]
|
||||
// M M M
|
||||
|
||||
let old_tail = self.tail;
|
||||
self.tail = self.tail - 1;
|
||||
// copy elements up to new tail
|
||||
self.copy(old_tail - 1, old_tail, i);
|
||||
self.copy(self.tail - 1, self.tail, self.cap - self.tail);
|
||||
|
||||
// copy last element into empty spot at bottom of buffer
|
||||
self.copy(self.cap - 1, 0, 1);
|
||||
|
||||
self.tail -= 1;
|
||||
},
|
||||
(false, true, false) => {
|
||||
// discontiguous, head section, insert closer to tail:
|
||||
(false, true, false) => unsafe {
|
||||
// discontiguous, insert closer to tail, head section:
|
||||
//
|
||||
// I H T
|
||||
// [o o o A o o o o o o . . . o o o]
|
||||
@ -837,19 +835,19 @@ impl<T> RingBuf<T> {
|
||||
// [o o I A o o o o o o . . o o o o]
|
||||
// M M M M M M
|
||||
|
||||
let old_tail = self.tail;
|
||||
self.tail = self.tail - 1;
|
||||
// copy elements up to new tail
|
||||
self.copy(old_tail - 1, old_tail, i);
|
||||
self.copy(self.tail - 1, self.tail, self.cap - self.tail);
|
||||
|
||||
// copy last element into empty spot at bottom of buffer
|
||||
self.copy(self.cap - 1, 0, 1);
|
||||
|
||||
// move elements from idx-1 to end forward not including ^ element
|
||||
self.copy(0, 1, idx - 1);
|
||||
}
|
||||
(false, false, false) => {
|
||||
// discontiguous, head section, insert closer to head:
|
||||
|
||||
self.tail -= 1;
|
||||
},
|
||||
(false, false, false) => unsafe {
|
||||
// discontiguous, insert closer to head, head section:
|
||||
//
|
||||
// I H T
|
||||
// [o o o o A o o . . . . . . o o o]
|
||||
@ -858,9 +856,8 @@ impl<T> RingBuf<T> {
|
||||
// [o o o o I A o o . . . . . o o o]
|
||||
// M M M
|
||||
|
||||
let old_head = self.head;
|
||||
self.head = self.head + 1;
|
||||
self.copy(idx + 1, idx, old_head - idx);
|
||||
self.copy(idx + 1, idx, self.head - idx);
|
||||
self.head += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -870,6 +867,170 @@ impl<T> RingBuf<T> {
|
||||
self.buffer_write(new_idx, t);
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes and returns the element at position `i` from the ringbuf.
|
||||
/// Whichever end is closer to the removal point will be moved to make
|
||||
/// room, and all the affected elements will be moved to new positions.
|
||||
/// Returns `None` if `i` is out of bounds.
|
||||
///
|
||||
/// # Example
|
||||
/// ```rust
|
||||
/// use std::collections::RingBuf;
|
||||
///
|
||||
/// let mut buf = RingBuf::new();
|
||||
/// buf.push_back(5i);
|
||||
/// buf.push_back(10i);
|
||||
/// buf.push_back(12i);
|
||||
/// buf.push_back(15);
|
||||
/// buf.remove(2);
|
||||
/// assert_eq!(Some(&15), buf.get(2));
|
||||
/// ```
|
||||
#[unstable = "matches collection reform specification; waiting on panic semantics"]
|
||||
pub fn remove(&mut self, i: uint) -> Option<T> {
|
||||
if self.is_empty() || self.len() <= i {
|
||||
return None;
|
||||
}
|
||||
|
||||
// There are three main cases:
|
||||
// Elements are contiguous
|
||||
// Elements are discontiguous and the removal is in the tail section
|
||||
// Elements are discontiguous and the removal is in the head section
|
||||
// - special case when elements are technically contiguous,
|
||||
// but self.head = 0
|
||||
//
|
||||
// For each of those there are two more cases:
|
||||
// Insert is closer to tail
|
||||
// Insert is closer to head
|
||||
//
|
||||
// Key: H - self.head
|
||||
// T - self.tail
|
||||
// o - Valid element
|
||||
// x - Element marked for removal
|
||||
// R - Indicates element that is being removed
|
||||
// M - Indicates element was moved
|
||||
|
||||
let idx = self.wrap_index(self.tail + i);
|
||||
|
||||
let elem = unsafe {
|
||||
Some(self.buffer_read(idx))
|
||||
};
|
||||
|
||||
let distance_to_tail = i;
|
||||
let distance_to_head = self.len() - i;
|
||||
|
||||
let contiguous = self.tail <= self.head;
|
||||
|
||||
match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
|
||||
(true, true, _) => unsafe {
|
||||
// contiguous, remove closer to tail:
|
||||
//
|
||||
// T R H
|
||||
// [. . . o o x o o o o . . . . . .]
|
||||
//
|
||||
// T H
|
||||
// [. . . . o o o o o o . . . . . .]
|
||||
// M M
|
||||
|
||||
self.copy(self.tail + 1, self.tail, i);
|
||||
self.tail += 1;
|
||||
},
|
||||
(true, false, _) => unsafe {
|
||||
// contiguous, remove closer to head:
|
||||
//
|
||||
// T R H
|
||||
// [. . . o o o o x o o . . . . . .]
|
||||
//
|
||||
// T H
|
||||
// [. . . o o o o o o . . . . . . .]
|
||||
// M M
|
||||
|
||||
self.copy(idx, idx + 1, self.head - idx - 1);
|
||||
self.head -= 1;
|
||||
},
|
||||
(false, true, true) => unsafe {
|
||||
// discontiguous, remove closer to tail, tail section:
|
||||
//
|
||||
// H T R
|
||||
// [o o o o o o . . . . . o o x o o]
|
||||
//
|
||||
// H T
|
||||
// [o o o o o o . . . . . . o o o o]
|
||||
// M M
|
||||
|
||||
self.copy(self.tail + 1, self.tail, i);
|
||||
self.tail = self.wrap_index(self.tail + 1);
|
||||
},
|
||||
(false, false, false) => unsafe {
|
||||
// discontiguous, remove closer to head, head section:
|
||||
//
|
||||
// R H T
|
||||
// [o o o o x o o . . . . . . o o o]
|
||||
//
|
||||
// H T
|
||||
// [o o o o o o . . . . . . . o o o]
|
||||
// M M
|
||||
|
||||
self.copy(idx, idx + 1, self.head - idx - 1);
|
||||
self.head -= 1;
|
||||
},
|
||||
(false, false, true) => unsafe {
|
||||
// discontiguous, remove closer to head, tail section:
|
||||
//
|
||||
// H T R
|
||||
// [o o o . . . . . . o o o o o x o]
|
||||
//
|
||||
// H T
|
||||
// [o o . . . . . . . o o o o o o o]
|
||||
// M M M M
|
||||
//
|
||||
// or quasi-discontiguous, remove next to head, tail section:
|
||||
//
|
||||
// H T R
|
||||
// [. . . . . . . . . o o o o o x o]
|
||||
//
|
||||
// T H
|
||||
// [. . . . . . . . . o o o o o o .]
|
||||
// M
|
||||
|
||||
// draw in elements in the tail section
|
||||
self.copy(idx, idx + 1, self.cap - idx - 1);
|
||||
|
||||
// Prevents underflow.
|
||||
if self.head != 0 {
|
||||
// copy first element into empty spot
|
||||
self.copy(self.cap - 1, 0, 1);
|
||||
|
||||
// move elements in the head section backwards
|
||||
self.copy(0, 1, self.head - 1);
|
||||
}
|
||||
|
||||
self.head = self.wrap_index(self.head - 1);
|
||||
},
|
||||
(false, true, false) => unsafe {
|
||||
// discontiguous, remove closer to tail, head section:
|
||||
//
|
||||
// R H T
|
||||
// [o o x o o o o o o o . . . o o o]
|
||||
//
|
||||
// H T
|
||||
// [o o o o o o o o o o . . . . o o]
|
||||
// M M M M M
|
||||
|
||||
// draw in elements up to idx
|
||||
self.copy(1, 0, idx);
|
||||
|
||||
// copy last element into empty spot
|
||||
self.copy(0, self.cap - 1, 1);
|
||||
|
||||
// move elements from tail to end forward, excluding the last one
|
||||
self.copy(self.tail + 1, self.tail, self.cap - self.tail - 1);
|
||||
|
||||
self.tail = self.wrap_index(self.tail + 1);
|
||||
}
|
||||
}
|
||||
|
||||
return elem;
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the index in the underlying buffer for a given logical element index.
|
||||
@ -952,7 +1113,6 @@ pub struct MutItems<'a, T:'a> {
|
||||
head: uint,
|
||||
cap: uint,
|
||||
marker: marker::ContravariantLifetime<'a>,
|
||||
marker2: marker::NoCopy
|
||||
}
|
||||
|
||||
impl<'a, T> Iterator<&'a mut T> for MutItems<'a, T> {
|
||||
@ -1103,6 +1263,7 @@ mod tests {
|
||||
use core::iter;
|
||||
use self::Taggy::*;
|
||||
use self::Taggypar::*;
|
||||
use std::cmp;
|
||||
use std::fmt::Show;
|
||||
use std::prelude::*;
|
||||
use std::hash;
|
||||
@ -1892,11 +2053,11 @@ mod tests {
|
||||
#[test]
|
||||
fn test_insert() {
|
||||
// This test checks that every single combination of tail position, length, and
|
||||
// insertion position is tested. Capacity 7 should be large enough to cover every case.
|
||||
// insertion position is tested. Capacity 15 should be large enough to cover every case.
|
||||
|
||||
let mut tester = RingBuf::with_capacity(7);
|
||||
// can't guarantee we got 7, so have to get what we got.
|
||||
// 7 would be great, but we will definitely get 2^k - 1, for k >= 3, or else
|
||||
let mut tester = RingBuf::with_capacity(15);
|
||||
// can't guarantee we got 15, so have to get what we got.
|
||||
// 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
|
||||
// this test isn't covering what it wants to
|
||||
let cap = tester.capacity();
|
||||
|
||||
@ -1915,6 +2076,45 @@ mod tests {
|
||||
}
|
||||
}
|
||||
tester.insert(to_insert, to_insert);
|
||||
assert!(tester.tail < tester.cap);
|
||||
assert!(tester.head < tester.cap);
|
||||
assert_eq!(tester, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_remove() {
|
||||
// This test checks that every single combination of tail position, length, and
|
||||
// removal position is tested. Capacity 15 should be large enough to cover every case.
|
||||
|
||||
let mut tester = RingBuf::with_capacity(15);
|
||||
// can't guarantee we got 15, so have to get what we got.
|
||||
// 15 would be great, but we will definitely get 2^k - 1, for k >= 4, or else
|
||||
// this test isn't covering what it wants to
|
||||
let cap = tester.capacity();
|
||||
|
||||
// len is the length *after* removal
|
||||
for len in range(0, cap - 1) {
|
||||
// 0, 1, 2, .., len - 1
|
||||
let expected = iter::count(0, 1).take(len).collect();
|
||||
for tail_pos in range(0, cap) {
|
||||
for to_remove in range(0, len + 1) {
|
||||
tester.tail = tail_pos;
|
||||
tester.head = tail_pos;
|
||||
for i in range(0, len) {
|
||||
if i == to_remove {
|
||||
tester.push_back(1234);
|
||||
}
|
||||
tester.push_back(i);
|
||||
}
|
||||
if to_remove == len {
|
||||
tester.push_back(1234);
|
||||
}
|
||||
tester.remove(to_remove);
|
||||
assert!(tester.tail < tester.cap);
|
||||
assert!(tester.head < tester.cap);
|
||||
assert_eq!(tester, expected);
|
||||
}
|
||||
}
|
||||
|
@ -1597,17 +1597,24 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_escape_unicode() {
|
||||
assert_eq!("abc".escape_unicode(), String::from_str("\\x61\\x62\\x63"));
|
||||
assert_eq!("a c".escape_unicode(), String::from_str("\\x61\\x20\\x63"));
|
||||
assert_eq!("\r\n\t".escape_unicode(), String::from_str("\\x0d\\x0a\\x09"));
|
||||
assert_eq!("'\"\\".escape_unicode(), String::from_str("\\x27\\x22\\x5c"));
|
||||
assert_eq!("abc".escape_unicode(),
|
||||
String::from_str("\\u{61}\\u{62}\\u{63}"));
|
||||
assert_eq!("a c".escape_unicode(),
|
||||
String::from_str("\\u{61}\\u{20}\\u{63}"));
|
||||
assert_eq!("\r\n\t".escape_unicode(),
|
||||
String::from_str("\\u{d}\\u{a}\\u{9}"));
|
||||
assert_eq!("'\"\\".escape_unicode(),
|
||||
String::from_str("\\u{27}\\u{22}\\u{5c}"));
|
||||
assert_eq!("\x00\x01\u{fe}\u{ff}".escape_unicode(),
|
||||
String::from_str("\\x00\\x01\\u00fe\\u00ff"));
|
||||
assert_eq!("\u{100}\u{ffff}".escape_unicode(), String::from_str("\\u0100\\uffff"));
|
||||
String::from_str("\\u{0}\\u{1}\\u{fe}\\u{ff}"));
|
||||
assert_eq!("\u{100}\u{ffff}".escape_unicode(),
|
||||
String::from_str("\\u{100}\\u{ffff}"));
|
||||
assert_eq!("\u{10000}\u{10ffff}".escape_unicode(),
|
||||
String::from_str("\\U00010000\\U0010ffff"));
|
||||
assert_eq!("ab\u{fb00}".escape_unicode(), String::from_str("\\x61\\x62\\ufb00"));
|
||||
assert_eq!("\u{1d4ea}\r".escape_unicode(), String::from_str("\\U0001d4ea\\x0d"));
|
||||
String::from_str("\\u{10000}\\u{10ffff}"));
|
||||
assert_eq!("ab\u{fb00}".escape_unicode(),
|
||||
String::from_str("\\u{61}\\u{62}\\u{fb00}"));
|
||||
assert_eq!("\u{1d4ea}\r".escape_unicode(),
|
||||
String::from_str("\\u{1d4ea}\\u{d}"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -1616,11 +1623,14 @@ mod tests {
|
||||
assert_eq!("a c".escape_default(), String::from_str("a c"));
|
||||
assert_eq!("\r\n\t".escape_default(), String::from_str("\\r\\n\\t"));
|
||||
assert_eq!("'\"\\".escape_default(), String::from_str("\\'\\\"\\\\"));
|
||||
assert_eq!("\u{100}\u{ffff}".escape_default(), String::from_str("\\u0100\\uffff"));
|
||||
assert_eq!("\u{100}\u{ffff}".escape_default(),
|
||||
String::from_str("\\u{100}\\u{ffff}"));
|
||||
assert_eq!("\u{10000}\u{10ffff}".escape_default(),
|
||||
String::from_str("\\U00010000\\U0010ffff"));
|
||||
assert_eq!("ab\u{fb00}".escape_default(), String::from_str("ab\\ufb00"));
|
||||
assert_eq!("\u{1d4ea}\r".escape_default(), String::from_str("\\U0001d4ea\\r"));
|
||||
String::from_str("\\u{10000}\\u{10ffff}"));
|
||||
assert_eq!("ab\u{fb00}".escape_default(),
|
||||
String::from_str("ab\\u{fb00}"));
|
||||
assert_eq!("\u{1d4ea}\r".escape_default(),
|
||||
String::from_str("\\u{1d4ea}\\r"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -826,6 +826,7 @@ impl StrAllocating for String {
|
||||
|
||||
#[stable]
|
||||
impl Default for String {
|
||||
#[stable]
|
||||
fn default() -> String {
|
||||
String::new()
|
||||
}
|
||||
@ -859,6 +860,16 @@ impl<'a, S: Str> Equiv<S> for String {
|
||||
#[cfg(stage0)]
|
||||
#[experimental = "waiting on Add stabilization"]
|
||||
impl<S: Str> Add<S, String> for String {
|
||||
/// Concatenates `self` and `other` as a new mutable `String`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let string1 = "foo".to_string();
|
||||
/// let string2 = "bar".to_string();
|
||||
/// let string3 = string1 + string2;
|
||||
/// assert_eq!(string3, "foobar".to_string());
|
||||
/// ```
|
||||
fn add(&self, other: &S) -> String {
|
||||
let mut s = String::from_str(self.as_slice());
|
||||
s.push_str(other.as_slice());
|
||||
|
@ -185,8 +185,10 @@ impl<K: Ord + Show, V: Show> Show for TreeMap<K, V> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<K: Ord, V> Default for TreeMap<K,V> {
|
||||
#[inline]
|
||||
#[stable]
|
||||
fn default() -> TreeMap<K, V> { TreeMap::new() }
|
||||
}
|
||||
|
||||
|
@ -134,8 +134,10 @@ impl<T: Ord + Show> Show for TreeSet<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<T: Ord> Default for TreeSet<T> {
|
||||
#[inline]
|
||||
#[stable]
|
||||
fn default() -> TreeSet<T> { TreeSet::new() }
|
||||
}
|
||||
|
||||
|
@ -150,8 +150,10 @@ impl<T: Show> Show for TrieMap<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<T> Default for TrieMap<T> {
|
||||
#[inline]
|
||||
#[stable]
|
||||
fn default() -> TrieMap<T> { TrieMap::new() }
|
||||
}
|
||||
|
||||
|
@ -69,8 +69,10 @@ impl Show for TrieSet {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl Default for TrieSet {
|
||||
#[inline]
|
||||
#[stable]
|
||||
fn default() -> TrieSet { TrieSet::new() }
|
||||
}
|
||||
|
||||
|
@ -11,6 +11,38 @@
|
||||
//! A growable list type, written `Vec<T>` but pronounced 'vector.'
|
||||
//!
|
||||
//! Vectors have `O(1)` indexing, push (to the end) and pop (from the end).
|
||||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! Explicitly creating a `Vec<T>` with `new()`:
|
||||
//!
|
||||
//! ```
|
||||
//! let xs: Vec<i32> = Vec::new();
|
||||
//! ```
|
||||
//!
|
||||
//! Using the `vec!` macro:
|
||||
//!
|
||||
//! ```
|
||||
//! let ys: Vec<i32> = vec![];
|
||||
//!
|
||||
//! let zs = vec![1i32, 2, 3, 4, 5];
|
||||
//! ```
|
||||
//!
|
||||
//! Push:
|
||||
//!
|
||||
//! ```
|
||||
//! let mut xs = vec![1i32, 2];
|
||||
//!
|
||||
//! xs.push(3);
|
||||
//! ```
|
||||
//!
|
||||
//! And pop:
|
||||
//!
|
||||
//! ```
|
||||
//! let mut xs = vec![1i32, 2];
|
||||
//!
|
||||
//! let two = xs.pop();
|
||||
//! ```
|
||||
|
||||
use core::prelude::*;
|
||||
|
||||
@ -32,7 +64,7 @@ use core::uint;
|
||||
|
||||
use slice::CloneSliceExt;
|
||||
|
||||
/// An owned, growable vector.
|
||||
/// A growable list type, written `Vec<T>` but pronounced 'vector.'
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -66,7 +98,7 @@ use slice::CloneSliceExt;
|
||||
/// assert_eq!(vec, vec![1, 2, 3, 4]);
|
||||
/// ```
|
||||
///
|
||||
/// Use a `Vec` as an efficient stack:
|
||||
/// Use a `Vec<T>` as an efficient stack:
|
||||
///
|
||||
/// ```
|
||||
/// let mut stack = Vec::new();
|
||||
@ -87,20 +119,17 @@ use slice::CloneSliceExt;
|
||||
///
|
||||
/// # Capacity and reallocation
|
||||
///
|
||||
/// The capacity of a vector is the amount of space allocated for any future
|
||||
/// elements that will be added onto the vector. This is not to be confused
|
||||
/// with the *length* of a vector, which specifies the number of actual
|
||||
/// elements within the vector. If a vector's length exceeds its capacity,
|
||||
/// its capacity will automatically be increased, but its elements will
|
||||
/// have to be reallocated.
|
||||
/// The capacity of a vector is the amount of space allocated for any future elements that will be
|
||||
/// added onto the vector. This is not to be confused with the *length* of a vector, which
|
||||
/// specifies the number of actual elements within the vector. If a vector's length exceeds its
|
||||
/// capacity, its capacity will automatically be increased, but its elements will have to be
|
||||
/// reallocated.
|
||||
///
|
||||
/// For example, a vector with capacity 10 and length 0 would be an empty
|
||||
/// vector with space for 10 more elements. Pushing 10 or fewer elements onto
|
||||
/// the vector will not change its capacity or cause reallocation to occur.
|
||||
/// However, if the vector's length is increased to 11, it will have to
|
||||
/// reallocate, which can be slow. For this reason, it is recommended
|
||||
/// to use `Vec::with_capacity` whenever possible to specify how big the vector
|
||||
/// is expected to get.
|
||||
/// For example, a vector with capacity 10 and length 0 would be an empty vector with space for 10
|
||||
/// more elements. Pushing 10 or fewer elements onto the vector will not change its capacity or
|
||||
/// cause reallocation to occur. However, if the vector's length is increased to 11, it will have
|
||||
/// to reallocate, which can be slow. For this reason, it is recommended to use
|
||||
/// `Vec::with_capacity` whenever possible to specify how big the vector is expected to get.
|
||||
#[unsafe_no_drop_flag]
|
||||
#[stable]
|
||||
pub struct Vec<T> {
|
||||
@ -131,7 +160,7 @@ impl<'a, T> IntoCow<'a, Vec<T>, [T]> for &'a [T] where T: Clone {
|
||||
}
|
||||
|
||||
impl<T> Vec<T> {
|
||||
/// Constructs a new, empty `Vec`.
|
||||
/// Constructs a new, empty `Vec<T>`.
|
||||
///
|
||||
/// The vector will not allocate until elements are pushed onto it.
|
||||
///
|
||||
@ -150,16 +179,15 @@ impl<T> Vec<T> {
|
||||
Vec { ptr: EMPTY as *mut T, len: 0, cap: 0 }
|
||||
}
|
||||
|
||||
/// Constructs a new, empty `Vec` with the specified capacity.
|
||||
/// Constructs a new, empty `Vec<T>` with the specified capacity.
|
||||
///
|
||||
/// The vector will be able to hold exactly `capacity` elements without
|
||||
/// reallocating. If `capacity` is 0, the vector will not allocate.
|
||||
/// The vector will be able to hold exactly `capacity` elements without reallocating. If
|
||||
/// `capacity` is 0, the vector will not allocate.
|
||||
///
|
||||
/// It is important to note that this function does not specify the
|
||||
/// *length* of the returned vector, but only the *capacity*. (For an
|
||||
/// explanation of the difference between length and capacity, see
|
||||
/// the main `Vec` docs above, 'Capacity and reallocation'.) To create
|
||||
/// a vector of a given length, use `Vec::from_elem` or `Vec::from_fn`.
|
||||
/// It is important to note that this function does not specify the *length* of the returned
|
||||
/// vector, but only the *capacity*. (For an explanation of the difference between length and
|
||||
/// capacity, see the main `Vec<T>` docs above, 'Capacity and reallocation'.) To create a
|
||||
/// vector of a given length, use `Vec::from_elem` or `Vec::from_fn`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -193,10 +221,10 @@ impl<T> Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates and initializes a `Vec`.
|
||||
/// Creates and initializes a `Vec<T>`.
|
||||
///
|
||||
/// Creates a `Vec` of size `length` and initializes the elements to the
|
||||
/// value returned by the closure `op`.
|
||||
/// Creates a `Vec<T>` of size `length` and initializes the elements to the value returned by
|
||||
/// the closure `op`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -261,10 +289,9 @@ impl<T> Vec<T> {
|
||||
|
||||
/// Creates a vector by copying the elements from a raw pointer.
|
||||
///
|
||||
/// This function will copy `elts` contiguous elements starting at `ptr`
|
||||
/// into a new allocation owned by the returned `Vec`. The elements of the
|
||||
/// buffer are copied into the vector without cloning, as if `ptr::read()`
|
||||
/// were called on them.
|
||||
/// This function will copy `elts` contiguous elements starting at `ptr` into a new allocation
|
||||
/// owned by the returned `Vec<T>`. The elements of the buffer are copied into the vector
|
||||
/// without cloning, as if `ptr::read()` were called on them.
|
||||
#[inline]
|
||||
#[unstable = "just renamed from raw::from_buf"]
|
||||
pub unsafe fn from_raw_buf(ptr: *const T, elts: uint) -> Vec<T> {
|
||||
@ -274,11 +301,10 @@ impl<T> Vec<T> {
|
||||
dst
|
||||
}
|
||||
|
||||
/// Consumes the `Vec`, partitioning it based on a predicate.
|
||||
/// Consumes the `Vec<T>`, partitioning it based on a predicate.
|
||||
///
|
||||
/// Partitions the `Vec` into two `Vec`s `(A,B)`, where all elements of `A`
|
||||
/// satisfy `f` and all elements of `B` do not. The order of elements is
|
||||
/// preserved.
|
||||
/// Partitions the `Vec<T>` into two `Vec<T>`s `(A,B)`, where all elements of `A` satisfy `f`
|
||||
/// and all elements of `B` do not. The order of elements is preserved.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -307,9 +333,9 @@ impl<T> Vec<T> {
|
||||
}
|
||||
|
||||
impl<T: Clone> Vec<T> {
|
||||
/// Constructs a `Vec` with copies of a value.
|
||||
/// Constructs a `Vec<T>` with copies of a value.
|
||||
///
|
||||
/// Creates a `Vec` with `length` copies of `value`.
|
||||
/// Creates a `Vec<T>` with `length` copies of `value`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -332,10 +358,10 @@ impl<T: Clone> Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Appends all elements in a slice to the `Vec`.
|
||||
/// Appends all elements in a slice to the `Vec<T>`.
|
||||
///
|
||||
/// Iterates over the slice `other`, clones each element, and then appends
|
||||
/// it to this `Vec`. The `other` vector is traversed in-order.
|
||||
/// it to this `Vec<T>`. The `other` vector is traversed in-order.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -364,9 +390,9 @@ impl<T: Clone> Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Grows the `Vec` in-place.
|
||||
/// Grows the `Vec<T>` in-place.
|
||||
///
|
||||
/// Adds `n` copies of `value` to the `Vec`.
|
||||
/// Adds `n` copies of `value` to the `Vec<T>`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -388,7 +414,7 @@ impl<T: Clone> Vec<T> {
|
||||
|
||||
/// Partitions a vector based on a predicate.
|
||||
///
|
||||
/// Clones the elements of the vector, partitioning them into two `Vec`s
|
||||
/// Clones the elements of the vector, partitioning them into two `Vec<T>`s
|
||||
/// `(a, b)`, where all elements of `a` satisfy `f` and all elements of `b`
|
||||
/// do not. The order of elements is preserved.
|
||||
///
|
||||
@ -647,8 +673,7 @@ unsafe fn dealloc<T>(ptr: *mut T, len: uint) {
|
||||
}
|
||||
|
||||
impl<T> Vec<T> {
|
||||
/// Returns the number of elements the vector can hold without
|
||||
/// reallocating.
|
||||
/// Returns the number of elements the vector can hold without reallocating.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -669,7 +694,7 @@ impl<T> Vec<T> {
|
||||
}
|
||||
|
||||
/// Reserves capacity for at least `additional` more elements to be inserted in the given
|
||||
/// `Vec`. The collection may reserve more space to avoid frequent reallocations.
|
||||
/// `Vec<T>`. The collection may reserve more space to avoid frequent reallocations.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
@ -703,7 +728,7 @@ impl<T> Vec<T> {
|
||||
}
|
||||
|
||||
/// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
|
||||
/// given `Vec`. Does nothing if the capacity is already sufficient.
|
||||
/// given `Vec<T>`. Does nothing if the capacity is already sufficient.
|
||||
///
|
||||
/// Note that the allocator may give the collection more space than it requests. Therefore
|
||||
/// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future
|
||||
@ -730,16 +755,19 @@ impl<T> Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Shrinks the capacity of the vector as much as possible. It will drop
|
||||
/// down as close as possible to the length but the allocator may still
|
||||
/// inform the vector that there is space for a few more elements.
|
||||
/// Shrinks the capacity of the vector as much as possible.
|
||||
///
|
||||
/// It will drop down as close as possible to the length but the allocator may still inform the
|
||||
/// vector that there is space for a few more elements.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut vec: Vec<int> = Vec::with_capacity(10);
|
||||
///
|
||||
/// vec.push_all(&[1, 2, 3]);
|
||||
/// assert_eq!(vec.capacity(), 10);
|
||||
///
|
||||
/// vec.shrink_to_fit();
|
||||
/// assert!(vec.capacity() >= 3);
|
||||
/// ```
|
||||
@ -828,14 +856,14 @@ impl<T> Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Creates a consuming iterator, that is, one that moves each
|
||||
/// value out of the vector (from start to end). The vector cannot
|
||||
/// be used after calling this.
|
||||
/// Creates a consuming iterator, that is, one that moves each value out of the vector (from
|
||||
/// start to end). The vector cannot be used after calling this.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let v = vec!["a".to_string(), "b".to_string()];
|
||||
///
|
||||
/// for s in v.into_iter() {
|
||||
/// // s has type String, not &String
|
||||
/// println!("{}", s);
|
||||
@ -860,9 +888,8 @@ impl<T> Vec<T> {
|
||||
|
||||
/// Sets the length of a vector.
|
||||
///
|
||||
/// This will explicitly set the size of the vector, without actually
|
||||
/// modifying its buffers, so it is up to the caller to ensure that the
|
||||
/// vector is actually the specified size.
|
||||
/// This will explicitly set the size of the vector, without actually modifying its buffers, so
|
||||
/// it is up to the caller to ensure that the vector is actually the specified size.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -878,8 +905,10 @@ impl<T> Vec<T> {
|
||||
self.len = len;
|
||||
}
|
||||
|
||||
/// Removes an element from anywhere in the vector and return it, replacing
|
||||
/// it with the last element. This does not preserve ordering, but is O(1).
|
||||
/// Removes an element from anywhere in the vector and return it, replacing it with the last
|
||||
/// element.
|
||||
///
|
||||
/// This does not preserve ordering, but is O(1).
|
||||
///
|
||||
/// Returns `None` if `index` is out of bounds.
|
||||
///
|
||||
@ -908,13 +937,12 @@ impl<T> Vec<T> {
|
||||
self.pop()
|
||||
}
|
||||
|
||||
/// Inserts an element at position `index` within the vector, shifting all
|
||||
/// elements after position `i` one position to the right.
|
||||
/// Inserts an element at position `index` within the vector, shifting all elements after
|
||||
/// position `i` one position to the right.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if `index` is not between `0` and the vector's length (both
|
||||
/// bounds inclusive).
|
||||
/// Panics if `index` is not between `0` and the vector's length (both bounds inclusive).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -947,9 +975,9 @@ impl<T> Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes and returns the element at position `index` within the vector,
|
||||
/// shifting all elements after position `index` one position to the left.
|
||||
/// Returns `None` if `i` is out of bounds.
|
||||
/// Removes and returns the element at position `index` within the vector, shifting all
|
||||
/// elements after position `index` one position to the left. Returns `None` if `i` is out of
|
||||
/// bounds.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -988,8 +1016,8 @@ impl<T> Vec<T> {
|
||||
|
||||
/// Retains only the elements specified by the predicate.
|
||||
///
|
||||
/// In other words, remove all elements `e` such that `f(&e)` returns false.
|
||||
/// This method operates in place and preserves the order of the retained elements.
|
||||
/// In other words, remove all elements `e` such that `f(&e)` returns false. This method
|
||||
/// operates in place and preserves the order of the retained elements.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -1078,8 +1106,7 @@ impl<T> Vec<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes the last element from a vector and returns it, or `None` if
|
||||
/// it is empty.
|
||||
/// Removes the last element from a vector and returns it, or `None` if it is empty.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -1107,7 +1134,9 @@ impl<T> Vec<T> {
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = vec![1i, 2, 3];
|
||||
///
|
||||
/// v.clear();
|
||||
///
|
||||
/// assert!(v.is_empty());
|
||||
/// ```
|
||||
#[inline]
|
||||
@ -1116,7 +1145,7 @@ impl<T> Vec<T> {
|
||||
self.truncate(0)
|
||||
}
|
||||
|
||||
/// Return the number of elements in the vector
|
||||
/// Returns the number of elements in the vector.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -1128,13 +1157,14 @@ impl<T> Vec<T> {
|
||||
#[stable]
|
||||
pub fn len(&self) -> uint { self.len }
|
||||
|
||||
/// Returns true if the vector contains no elements
|
||||
/// Returns `true` if the vector contains no elements.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let mut v = Vec::new();
|
||||
/// assert!(v.is_empty());
|
||||
///
|
||||
/// v.push(1i);
|
||||
/// assert!(!v.is_empty());
|
||||
/// ```
|
||||
@ -1169,7 +1199,9 @@ impl<T: PartialEq> Vec<T> {
|
||||
///
|
||||
/// ```
|
||||
/// let mut vec = vec![1i, 2, 2, 3, 2];
|
||||
///
|
||||
/// vec.dedup();
|
||||
///
|
||||
/// assert_eq!(vec, vec![1i, 2, 3, 2]);
|
||||
/// ```
|
||||
#[unstable = "this function may be renamed"]
|
||||
@ -1330,6 +1362,7 @@ impl<T> Drop for Vec<T> {
|
||||
|
||||
#[stable]
|
||||
impl<T> Default for Vec<T> {
|
||||
#[stable]
|
||||
fn default() -> Vec<T> {
|
||||
Vec::new()
|
||||
}
|
||||
@ -1441,10 +1474,9 @@ impl<T> Drop for MoveItems<T> {
|
||||
|
||||
/// Converts an iterator of pairs into a pair of vectors.
|
||||
///
|
||||
/// Returns a tuple containing two vectors where the i-th element of the first
|
||||
/// vector contains the first element of the i-th tuple of the input iterator,
|
||||
/// and the i-th element of the second vector contains the second element
|
||||
/// of the i-th tuple of the input iterator.
|
||||
/// Returns a tuple containing two vectors where the i-th element of the first vector contains the
|
||||
/// first element of the i-th tuple of the input iterator, and the i-th element of the second
|
||||
/// vector contains the second element of the i-th tuple of the input iterator.
|
||||
#[unstable = "this functionality may become more generic over time"]
|
||||
pub fn unzip<T, U, V: Iterator<(T, U)>>(mut iter: V) -> (Vec<T>, Vec<U>) {
|
||||
let (lo, _) = iter.size_hint();
|
||||
|
@ -19,7 +19,7 @@ use core::default::Default;
|
||||
use core::fmt;
|
||||
use core::hash::{Hash, Writer};
|
||||
use core::iter;
|
||||
use core::iter::{Enumerate, FilterMap};
|
||||
use core::iter::{Enumerate, FilterMap, Map};
|
||||
use core::mem::replace;
|
||||
use core::ops::FnOnce;
|
||||
|
||||
@ -66,7 +66,9 @@ pub struct VecMap<V> {
|
||||
v: Vec<Option<V>>,
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<V> Default for VecMap<V> {
|
||||
#[stable]
|
||||
#[inline]
|
||||
fn default() -> VecMap<V> { VecMap::new() }
|
||||
}
|
||||
@ -144,7 +146,7 @@ impl<V> VecMap<V> {
|
||||
pub fn keys<'r>(&'r self) -> Keys<'r, V> {
|
||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||
|
||||
self.iter().map(first)
|
||||
Keys { iter: self.iter().map(first) }
|
||||
}
|
||||
|
||||
/// Returns an iterator visiting all values in ascending order by the keys.
|
||||
@ -153,7 +155,7 @@ impl<V> VecMap<V> {
|
||||
pub fn values<'r>(&'r self) -> Values<'r, V> {
|
||||
fn second<A, B>((_, b): (A, B)) -> B { b }
|
||||
|
||||
self.iter().map(second)
|
||||
Values { iter: self.iter().map(second) }
|
||||
}
|
||||
|
||||
/// Returns an iterator visiting all key-value pairs in ascending order by the keys.
|
||||
@ -240,7 +242,7 @@ impl<V> VecMap<V> {
|
||||
}
|
||||
|
||||
let values = replace(&mut self.v, vec!());
|
||||
values.into_iter().enumerate().filter_map(filter)
|
||||
MoveItems { iter: values.into_iter().enumerate().filter_map(filter) }
|
||||
}
|
||||
|
||||
/// Return the number of elements in the map.
|
||||
@ -603,7 +605,7 @@ macro_rules! double_ended_iterator {
|
||||
}
|
||||
}
|
||||
|
||||
/// Forward iterator over a map.
|
||||
/// An iterator over the key-value pairs of a map.
|
||||
pub struct Entries<'a, V:'a> {
|
||||
front: uint,
|
||||
back: uint,
|
||||
@ -613,7 +615,7 @@ pub struct Entries<'a, V:'a> {
|
||||
iterator!(impl Entries -> (uint, &'a V), as_ref)
|
||||
double_ended_iterator!(impl Entries -> (uint, &'a V), as_ref)
|
||||
|
||||
/// Forward iterator over the key-value pairs of a map, with the
|
||||
/// An iterator over the key-value pairs of a map, with the
|
||||
/// values being mutable.
|
||||
pub struct MutEntries<'a, V:'a> {
|
||||
front: uint,
|
||||
@ -624,19 +626,50 @@ pub struct MutEntries<'a, V:'a> {
|
||||
iterator!(impl MutEntries -> (uint, &'a mut V), as_mut)
|
||||
double_ended_iterator!(impl MutEntries -> (uint, &'a mut V), as_mut)
|
||||
|
||||
/// Forward iterator over the keys of a map
|
||||
pub type Keys<'a, V> = iter::Map<(uint, &'a V), uint, Entries<'a, V>, fn((uint, &'a V)) -> uint>;
|
||||
/// An iterator over the keys of a map.
|
||||
pub struct Keys<'a, V: 'a> {
|
||||
iter: Map<(uint, &'a V), uint, Entries<'a, V>, fn((uint, &'a V)) -> uint>
|
||||
}
|
||||
|
||||
/// Forward iterator over the values of a map
|
||||
pub type Values<'a, V> =
|
||||
iter::Map<(uint, &'a V), &'a V, Entries<'a, V>, fn((uint, &'a V)) -> &'a V>;
|
||||
/// An iterator over the values of a map.
|
||||
pub struct Values<'a, V: 'a> {
|
||||
iter: Map<(uint, &'a V), &'a V, Entries<'a, V>, fn((uint, &'a V)) -> &'a V>
|
||||
}
|
||||
|
||||
/// Iterator over the key-value pairs of a map, the iterator consumes the map
|
||||
pub type MoveItems<V> = FilterMap<
|
||||
/// A consuming iterator over the key-value pairs of a map.
|
||||
pub struct MoveItems<V> {
|
||||
iter: FilterMap<
|
||||
(uint, Option<V>),
|
||||
(uint, V),
|
||||
Enumerate<vec::MoveItems<Option<V>>>,
|
||||
fn((uint, Option<V>)) -> Option<(uint, V)>>;
|
||||
fn((uint, Option<V>)) -> Option<(uint, V)>>
|
||||
}
|
||||
|
||||
impl<'a, V> Iterator<uint> for Keys<'a, V> {
|
||||
fn next(&mut self) -> Option<uint> { self.iter.next() }
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
|
||||
}
|
||||
impl<'a, V> DoubleEndedIterator<uint> for Keys<'a, V> {
|
||||
fn next_back(&mut self) -> Option<uint> { self.iter.next_back() }
|
||||
}
|
||||
|
||||
|
||||
impl<'a, V> Iterator<&'a V> for Values<'a, V> {
|
||||
fn next(&mut self) -> Option<(&'a V)> { self.iter.next() }
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
|
||||
}
|
||||
impl<'a, V> DoubleEndedIterator<&'a V> for Values<'a, V> {
|
||||
fn next_back(&mut self) -> Option<(&'a V)> { self.iter.next_back() }
|
||||
}
|
||||
|
||||
|
||||
impl<V> Iterator<(uint, V)> for MoveItems<V> {
|
||||
fn next(&mut self) -> Option<(uint, V)> { self.iter.next() }
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
|
||||
}
|
||||
impl<V> DoubleEndedIterator<(uint, V)> for MoveItems<V> {
|
||||
fn next_back(&mut self) -> Option<(uint, V)> { self.iter.next_back() }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_map {
|
||||
|
@ -15,7 +15,6 @@
|
||||
pub use self::Ordering::*;
|
||||
|
||||
use intrinsics;
|
||||
use std::kinds::marker;
|
||||
use cell::UnsafeCell;
|
||||
use kinds::Copy;
|
||||
|
||||
@ -23,28 +22,24 @@ use kinds::Copy;
|
||||
#[stable]
|
||||
pub struct AtomicBool {
|
||||
v: UnsafeCell<uint>,
|
||||
nocopy: marker::NoCopy
|
||||
}
|
||||
|
||||
/// A signed integer type which can be safely shared between threads.
|
||||
#[stable]
|
||||
pub struct AtomicInt {
|
||||
v: UnsafeCell<int>,
|
||||
nocopy: marker::NoCopy
|
||||
}
|
||||
|
||||
/// An unsigned integer type which can be safely shared between threads.
|
||||
#[stable]
|
||||
pub struct AtomicUint {
|
||||
v: UnsafeCell<uint>,
|
||||
nocopy: marker::NoCopy
|
||||
}
|
||||
|
||||
/// A raw pointer type which can be safely shared between threads.
|
||||
#[stable]
|
||||
pub struct AtomicPtr<T> {
|
||||
p: UnsafeCell<uint>,
|
||||
nocopy: marker::NoCopy
|
||||
}
|
||||
|
||||
/// Atomic memory orderings
|
||||
@ -87,15 +82,15 @@ impl Copy for Ordering {}
|
||||
/// An `AtomicBool` initialized to `false`.
|
||||
#[unstable = "may be renamed, pending conventions for static initalizers"]
|
||||
pub const INIT_ATOMIC_BOOL: AtomicBool =
|
||||
AtomicBool { v: UnsafeCell { value: 0 }, nocopy: marker::NoCopy };
|
||||
AtomicBool { v: UnsafeCell { value: 0 } };
|
||||
/// An `AtomicInt` initialized to `0`.
|
||||
#[unstable = "may be renamed, pending conventions for static initalizers"]
|
||||
pub const INIT_ATOMIC_INT: AtomicInt =
|
||||
AtomicInt { v: UnsafeCell { value: 0 }, nocopy: marker::NoCopy };
|
||||
AtomicInt { v: UnsafeCell { value: 0 } };
|
||||
/// An `AtomicUint` initialized to `0`.
|
||||
#[unstable = "may be renamed, pending conventions for static initalizers"]
|
||||
pub const INIT_ATOMIC_UINT: AtomicUint =
|
||||
AtomicUint { v: UnsafeCell { value: 0, }, nocopy: marker::NoCopy };
|
||||
AtomicUint { v: UnsafeCell { value: 0, } };
|
||||
|
||||
// NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly
|
||||
const UINT_TRUE: uint = -1;
|
||||
@ -115,7 +110,7 @@ impl AtomicBool {
|
||||
#[stable]
|
||||
pub fn new(v: bool) -> AtomicBool {
|
||||
let val = if v { UINT_TRUE } else { 0 };
|
||||
AtomicBool { v: UnsafeCell::new(val), nocopy: marker::NoCopy }
|
||||
AtomicBool { v: UnsafeCell::new(val) }
|
||||
}
|
||||
|
||||
/// Loads a value from the bool.
|
||||
@ -355,7 +350,7 @@ impl AtomicInt {
|
||||
#[inline]
|
||||
#[stable]
|
||||
pub fn new(v: int) -> AtomicInt {
|
||||
AtomicInt {v: UnsafeCell::new(v), nocopy: marker::NoCopy}
|
||||
AtomicInt {v: UnsafeCell::new(v)}
|
||||
}
|
||||
|
||||
/// Loads a value from the int.
|
||||
@ -541,7 +536,7 @@ impl AtomicUint {
|
||||
#[inline]
|
||||
#[stable]
|
||||
pub fn new(v: uint) -> AtomicUint {
|
||||
AtomicUint { v: UnsafeCell::new(v), nocopy: marker::NoCopy }
|
||||
AtomicUint { v: UnsafeCell::new(v) }
|
||||
}
|
||||
|
||||
/// Loads a value from the uint.
|
||||
@ -728,7 +723,7 @@ impl<T> AtomicPtr<T> {
|
||||
#[inline]
|
||||
#[stable]
|
||||
pub fn new(p: *mut T) -> AtomicPtr<T> {
|
||||
AtomicPtr { p: UnsafeCell::new(p as uint), nocopy: marker::NoCopy }
|
||||
AtomicPtr { p: UnsafeCell::new(p as uint) }
|
||||
}
|
||||
|
||||
/// Loads a value from the pointer.
|
||||
|
@ -215,8 +215,9 @@ impl<T:Copy> Clone for Cell<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable]
|
||||
#[stable]
|
||||
impl<T:Default + Copy> Default for Cell<T> {
|
||||
#[stable]
|
||||
fn default() -> Cell<T> {
|
||||
Cell::new(Default::default())
|
||||
}
|
||||
@ -234,7 +235,6 @@ impl<T:PartialEq + Copy> PartialEq for Cell<T> {
|
||||
pub struct RefCell<T> {
|
||||
value: UnsafeCell<T>,
|
||||
borrow: Cell<BorrowFlag>,
|
||||
nocopy: marker::NoCopy,
|
||||
noshare: marker::NoSync,
|
||||
}
|
||||
|
||||
@ -251,7 +251,6 @@ impl<T> RefCell<T> {
|
||||
RefCell {
|
||||
value: UnsafeCell::new(value),
|
||||
borrow: Cell::new(UNUSED),
|
||||
nocopy: marker::NoCopy,
|
||||
noshare: marker::NoSync,
|
||||
}
|
||||
}
|
||||
@ -349,8 +348,9 @@ impl<T: Clone> Clone for RefCell<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable]
|
||||
#[stable]
|
||||
impl<T:Default> Default for RefCell<T> {
|
||||
#[stable]
|
||||
fn default() -> RefCell<T> {
|
||||
RefCell::new(Default::default())
|
||||
}
|
||||
|
@ -15,11 +15,11 @@
|
||||
#![allow(non_snake_case)]
|
||||
#![doc(primitive = "char")]
|
||||
|
||||
use iter::Iterator;
|
||||
use mem::transmute;
|
||||
use ops::FnMut;
|
||||
use option::Option;
|
||||
use option::Option::{None, Some};
|
||||
use iter::{range_step, Iterator, RangeStep};
|
||||
use option::Option;
|
||||
use slice::SliceExt;
|
||||
|
||||
// UTF-8 ranges and tags for encoding characters
|
||||
@ -141,7 +141,7 @@ pub fn to_digit(c: char, radix: uint) -> Option<uint> {
|
||||
#[unstable = "pending decisions about costructors for primitives"]
|
||||
pub fn from_digit(num: uint, radix: uint) -> Option<char> {
|
||||
if radix > 36 {
|
||||
panic!("from_digit: radix is to high (maximum 36)");
|
||||
panic!("from_digit: radix is too high (maximum 36)");
|
||||
}
|
||||
if num < radix {
|
||||
unsafe {
|
||||
@ -156,15 +156,7 @@ pub fn from_digit(num: uint, radix: uint) -> Option<char> {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns the hexadecimal Unicode escape of a `char`
|
||||
///
|
||||
/// The rules are as follows:
|
||||
///
|
||||
/// - chars in [0,0xff] get 2-digit escapes: `\\xNN`
|
||||
/// - chars in [0x100,0xffff] get 4-digit escapes: `\\u{NNNN}`
|
||||
/// - chars above 0x10000 get 8-digit escapes: `\\u{{NNN}NNNNN}`
|
||||
///
|
||||
/// Deprecated, call the escape_unicode method instead.
|
||||
#[deprecated = "use the Char::escape_unicode method"]
|
||||
pub fn escape_unicode<F>(c: char, mut f: F) where F: FnMut(char) {
|
||||
for char in c.escape_unicode() {
|
||||
@ -172,18 +164,7 @@ pub fn escape_unicode<F>(c: char, mut f: F) where F: FnMut(char) {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Returns a 'default' ASCII and C++11-like literal escape of a `char`
|
||||
///
|
||||
/// The default is chosen with a bias toward producing literals that are
|
||||
/// legal in a variety of languages, including C++11 and similar C-family
|
||||
/// languages. The exact rules are:
|
||||
///
|
||||
/// - Tab, CR and LF are escaped as '\t', '\r' and '\n' respectively.
|
||||
/// - Single-quote, double-quote and backslash chars are backslash-escaped.
|
||||
/// - Any other chars in the range [0x20,0x7e] are not escaped.
|
||||
/// - Any other chars are given hex Unicode escapes; see `escape_unicode`.
|
||||
///
|
||||
/// Deprecated, call the escape_default method instead.
|
||||
#[deprecated = "use the Char::escape_default method"]
|
||||
pub fn escape_default<F>(c: char, mut f: F) where F: FnMut(char) {
|
||||
for c in c.escape_default() {
|
||||
@ -267,13 +248,11 @@ pub trait Char {
|
||||
/// Returns an iterator that yields the hexadecimal Unicode escape
|
||||
/// of a character, as `char`s.
|
||||
///
|
||||
/// The rules are as follows:
|
||||
///
|
||||
/// * Characters in [0,0xff] get 2-digit escapes: `\\xNN`
|
||||
/// * Characters in [0x100,0xffff] get 4-digit escapes: `\\u{NNNN}`.
|
||||
/// * Characters above 0x10000 get 8-digit escapes: `\\u{{NNN}NNNNN}`.
|
||||
/// All characters are escaped with Rust syntax of the form `\\u{NNNN}`
|
||||
/// where `NNNN` is the shortest hexadecimal representation of the code
|
||||
/// point.
|
||||
#[unstable = "pending error conventions, trait organization"]
|
||||
fn escape_unicode(self) -> UnicodeEscapedChars;
|
||||
fn escape_unicode(self) -> EscapeUnicode;
|
||||
|
||||
/// Returns an iterator that yields the 'default' ASCII and
|
||||
/// C++11-like literal escape of a character, as `char`s.
|
||||
@ -288,7 +267,7 @@ pub trait Char {
|
||||
/// * Any other chars in the range [0x20,0x7e] are not escaped.
|
||||
/// * Any other chars are given hex Unicode escapes; see `escape_unicode`.
|
||||
#[unstable = "pending error conventions, trait organization"]
|
||||
fn escape_default(self) -> DefaultEscapedChars;
|
||||
fn escape_default(self) -> EscapeDefault;
|
||||
|
||||
/// Returns the amount of bytes this character would need if encoded in
|
||||
/// UTF-8.
|
||||
@ -358,23 +337,23 @@ impl Char for char {
|
||||
fn from_u32(i: u32) -> Option<char> { from_u32(i) }
|
||||
|
||||
#[unstable = "pending error conventions, trait organization"]
|
||||
fn escape_unicode(self) -> UnicodeEscapedChars {
|
||||
UnicodeEscapedChars { c: self, state: UnicodeEscapedCharsState::Backslash }
|
||||
fn escape_unicode(self) -> EscapeUnicode {
|
||||
EscapeUnicode { c: self, state: EscapeUnicodeState::Backslash }
|
||||
}
|
||||
|
||||
#[unstable = "pending error conventions, trait organization"]
|
||||
fn escape_default(self) -> DefaultEscapedChars {
|
||||
fn escape_default(self) -> EscapeDefault {
|
||||
let init_state = match self {
|
||||
'\t' => DefaultEscapedCharsState::Backslash('t'),
|
||||
'\r' => DefaultEscapedCharsState::Backslash('r'),
|
||||
'\n' => DefaultEscapedCharsState::Backslash('n'),
|
||||
'\\' => DefaultEscapedCharsState::Backslash('\\'),
|
||||
'\'' => DefaultEscapedCharsState::Backslash('\''),
|
||||
'"' => DefaultEscapedCharsState::Backslash('"'),
|
||||
'\x20' ... '\x7e' => DefaultEscapedCharsState::Char(self),
|
||||
_ => DefaultEscapedCharsState::Unicode(self.escape_unicode())
|
||||
'\t' => EscapeDefaultState::Backslash('t'),
|
||||
'\r' => EscapeDefaultState::Backslash('r'),
|
||||
'\n' => EscapeDefaultState::Backslash('n'),
|
||||
'\\' => EscapeDefaultState::Backslash('\\'),
|
||||
'\'' => EscapeDefaultState::Backslash('\''),
|
||||
'"' => EscapeDefaultState::Backslash('"'),
|
||||
'\x20' ... '\x7e' => EscapeDefaultState::Char(self),
|
||||
_ => EscapeDefaultState::Unicode(self.escape_unicode())
|
||||
};
|
||||
DefaultEscapedChars { state: init_state }
|
||||
EscapeDefault { state: init_state }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
@ -451,72 +430,86 @@ impl Char for char {
|
||||
|
||||
/// An iterator over the characters that represent a `char`, as escaped by
|
||||
/// Rust's unicode escaping rules.
|
||||
pub struct UnicodeEscapedChars {
|
||||
pub struct EscapeUnicode {
|
||||
c: char,
|
||||
state: UnicodeEscapedCharsState
|
||||
state: EscapeUnicodeState
|
||||
}
|
||||
|
||||
enum UnicodeEscapedCharsState {
|
||||
enum EscapeUnicodeState {
|
||||
Backslash,
|
||||
Type,
|
||||
Value(RangeStep<i32>),
|
||||
LeftBrace,
|
||||
Value(uint),
|
||||
RightBrace,
|
||||
Done,
|
||||
}
|
||||
|
||||
impl Iterator<char> for UnicodeEscapedChars {
|
||||
impl Iterator<char> for EscapeUnicode {
|
||||
fn next(&mut self) -> Option<char> {
|
||||
match self.state {
|
||||
UnicodeEscapedCharsState::Backslash => {
|
||||
self.state = UnicodeEscapedCharsState::Type;
|
||||
EscapeUnicodeState::Backslash => {
|
||||
self.state = EscapeUnicodeState::Type;
|
||||
Some('\\')
|
||||
}
|
||||
UnicodeEscapedCharsState::Type => {
|
||||
let (typechar, pad) = if self.c <= '\x7f' { ('x', 2) }
|
||||
else if self.c <= '\u{ffff}' { ('u', 4) }
|
||||
else { ('U', 8) };
|
||||
self.state = UnicodeEscapedCharsState::Value(range_step(4 * (pad - 1), -1, -4i32));
|
||||
Some(typechar)
|
||||
EscapeUnicodeState::Type => {
|
||||
self.state = EscapeUnicodeState::LeftBrace;
|
||||
Some('u')
|
||||
}
|
||||
UnicodeEscapedCharsState::Value(ref mut range_step) => match range_step.next() {
|
||||
Some(offset) => {
|
||||
let offset = offset as uint;
|
||||
let v = match ((self.c as i32) >> offset) & 0xf {
|
||||
i @ 0 ... 9 => '0' as i32 + i,
|
||||
i => 'a' as i32 + (i - 10)
|
||||
};
|
||||
Some(unsafe { transmute(v) })
|
||||
EscapeUnicodeState::LeftBrace => {
|
||||
let mut n = 0u;
|
||||
while (self.c as u32) >> (4 * (n + 1)) != 0 {
|
||||
n += 1;
|
||||
}
|
||||
None => None
|
||||
self.state = EscapeUnicodeState::Value(n);
|
||||
Some('{')
|
||||
}
|
||||
EscapeUnicodeState::Value(offset) => {
|
||||
let v = match ((self.c as i32) >> (offset * 4)) & 0xf {
|
||||
i @ 0 ... 9 => '0' as i32 + i,
|
||||
i => 'a' as i32 + (i - 10)
|
||||
};
|
||||
if offset == 0 {
|
||||
self.state = EscapeUnicodeState::RightBrace;
|
||||
} else {
|
||||
self.state = EscapeUnicodeState::Value(offset - 1);
|
||||
}
|
||||
Some(unsafe { transmute(v) })
|
||||
}
|
||||
EscapeUnicodeState::RightBrace => {
|
||||
self.state = EscapeUnicodeState::Done;
|
||||
Some('}')
|
||||
}
|
||||
EscapeUnicodeState::Done => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over the characters that represent a `char`, escaped
|
||||
/// for maximum portability.
|
||||
pub struct DefaultEscapedChars {
|
||||
state: DefaultEscapedCharsState
|
||||
pub struct EscapeDefault {
|
||||
state: EscapeDefaultState
|
||||
}
|
||||
|
||||
enum DefaultEscapedCharsState {
|
||||
enum EscapeDefaultState {
|
||||
Backslash(char),
|
||||
Char(char),
|
||||
Done,
|
||||
Unicode(UnicodeEscapedChars),
|
||||
Unicode(EscapeUnicode),
|
||||
}
|
||||
|
||||
impl Iterator<char> for DefaultEscapedChars {
|
||||
impl Iterator<char> for EscapeDefault {
|
||||
fn next(&mut self) -> Option<char> {
|
||||
match self.state {
|
||||
DefaultEscapedCharsState::Backslash(c) => {
|
||||
self.state = DefaultEscapedCharsState::Char(c);
|
||||
EscapeDefaultState::Backslash(c) => {
|
||||
self.state = EscapeDefaultState::Char(c);
|
||||
Some('\\')
|
||||
}
|
||||
DefaultEscapedCharsState::Char(c) => {
|
||||
self.state = DefaultEscapedCharsState::Done;
|
||||
EscapeDefaultState::Char(c) => {
|
||||
self.state = EscapeDefaultState::Done;
|
||||
Some(c)
|
||||
}
|
||||
DefaultEscapedCharsState::Done => None,
|
||||
DefaultEscapedCharsState::Unicode(ref mut iter) => iter.next()
|
||||
EscapeDefaultState::Done => None,
|
||||
EscapeDefaultState::Unicode(ref mut iter) => iter.next()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,6 +97,7 @@
|
||||
/// bar: f32,
|
||||
/// }
|
||||
/// ```
|
||||
#[stable]
|
||||
pub trait Default {
|
||||
/// Returns the "default value" for a type.
|
||||
///
|
||||
@ -130,13 +131,16 @@ pub trait Default {
|
||||
/// fn default() -> Kind { Kind::A }
|
||||
/// }
|
||||
/// ```
|
||||
#[stable]
|
||||
fn default() -> Self;
|
||||
}
|
||||
|
||||
macro_rules! default_impl(
|
||||
($t:ty, $v:expr) => {
|
||||
#[stable]
|
||||
impl Default for $t {
|
||||
#[inline]
|
||||
#[stable]
|
||||
fn default() -> $t { $v }
|
||||
}
|
||||
}
|
||||
|
@ -203,8 +203,10 @@ impl Clone for SipState {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl Default for SipState {
|
||||
#[inline]
|
||||
#[stable]
|
||||
fn default() -> SipState {
|
||||
SipState::new()
|
||||
}
|
||||
|
@ -217,6 +217,7 @@ extern "rust-intrinsic" {
|
||||
///
|
||||
/// `forget` is unsafe because the caller is responsible for
|
||||
/// ensuring the argument is deallocated already.
|
||||
#[stable]
|
||||
pub fn forget<T>(_: T) -> ();
|
||||
|
||||
/// Unsafely transforms a value of one type into a value of another type.
|
||||
@ -232,6 +233,7 @@ extern "rust-intrinsic" {
|
||||
/// let v: &[u8] = unsafe { mem::transmute("L") };
|
||||
/// assert!(v == [76u8]);
|
||||
/// ```
|
||||
#[stable]
|
||||
pub fn transmute<T,U>(e: T) -> U;
|
||||
|
||||
/// Gives the address for the return value of the enclosing function.
|
||||
|
@ -110,8 +110,8 @@ pub trait Iterator<A> {
|
||||
#[unstable = "new convention for extension traits"]
|
||||
/// An extension trait providing numerous methods applicable to all iterators.
|
||||
pub trait IteratorExt<A>: Iterator<A> {
|
||||
/// Chain this iterator with another, returning a new iterator which will
|
||||
/// finish iterating over the current iterator, and then it will iterate
|
||||
/// Chain this iterator with another, returning a new iterator that will
|
||||
/// finish iterating over the current iterator, and then iterate
|
||||
/// over the other specified iterator.
|
||||
///
|
||||
/// # Example
|
||||
@ -130,7 +130,7 @@ pub trait IteratorExt<A>: Iterator<A> {
|
||||
Chain{a: self, b: other, flag: false}
|
||||
}
|
||||
|
||||
/// Creates an iterator which iterates over both this and the specified
|
||||
/// Creates an iterator that iterates over both this and the specified
|
||||
/// iterators simultaneously, yielding the two elements as pairs. When
|
||||
/// either iterator returns None, all further invocations of next() will
|
||||
/// return None.
|
||||
@ -151,7 +151,7 @@ pub trait IteratorExt<A>: Iterator<A> {
|
||||
Zip{a: self, b: other}
|
||||
}
|
||||
|
||||
/// Creates a new iterator which will apply the specified function to each
|
||||
/// Creates a new iterator that will apply the specified function to each
|
||||
/// element returned by the first, yielding the mapped element instead.
|
||||
///
|
||||
/// # Example
|
||||
@ -169,8 +169,8 @@ pub trait IteratorExt<A>: Iterator<A> {
|
||||
Map{iter: self, f: f}
|
||||
}
|
||||
|
||||
/// Creates an iterator which applies the predicate to each element returned
|
||||
/// by this iterator. Only elements which have the predicate evaluate to
|
||||
/// Creates an iterator that applies the predicate to each element returned
|
||||
/// by this iterator. Only elements that have the predicate evaluate to
|
||||
/// `true` will be yielded.
|
||||
///
|
||||
/// # Example
|
||||
@ -187,7 +187,7 @@ pub trait IteratorExt<A>: Iterator<A> {
|
||||
Filter{iter: self, predicate: predicate}
|
||||
}
|
||||
|
||||
/// Creates an iterator which both filters and maps elements.
|
||||
/// Creates an iterator that both filters and maps elements.
|
||||
/// If the specified function returns None, the element is skipped.
|
||||
/// Otherwise the option is unwrapped and the new value is yielded.
|
||||
///
|
||||
@ -205,7 +205,7 @@ pub trait IteratorExt<A>: Iterator<A> {
|
||||
FilterMap { iter: self, f: f }
|
||||
}
|
||||
|
||||
/// Creates an iterator which yields a pair of the value returned by this
|
||||
/// Creates an iterator that yields a pair of the value returned by this
|
||||
/// iterator plus the current index of iteration.
|
||||
///
|
||||
/// # Example
|
||||
@ -248,7 +248,7 @@ pub trait IteratorExt<A>: Iterator<A> {
|
||||
Peekable{iter: self, peeked: None}
|
||||
}
|
||||
|
||||
/// Creates an iterator which invokes the predicate on elements until it
|
||||
/// Creates an iterator that invokes the predicate on elements until it
|
||||
/// returns false. Once the predicate returns false, all further elements are
|
||||
/// yielded.
|
||||
///
|
||||
@ -268,7 +268,7 @@ pub trait IteratorExt<A>: Iterator<A> {
|
||||
SkipWhile{iter: self, flag: false, predicate: predicate}
|
||||
}
|
||||
|
||||
/// Creates an iterator which yields elements so long as the predicate
|
||||
/// Creates an iterator that yields elements so long as the predicate
|
||||
/// returns true. After the predicate returns false for the first time, no
|
||||
/// further elements will be yielded.
|
||||
///
|
||||
@ -287,8 +287,8 @@ pub trait IteratorExt<A>: Iterator<A> {
|
||||
TakeWhile{iter: self, flag: false, predicate: predicate}
|
||||
}
|
||||
|
||||
/// Creates an iterator which skips the first `n` elements of this iterator,
|
||||
/// and then it yields all further items.
|
||||
/// Creates an iterator that skips the first `n` elements of this iterator,
|
||||
/// and then yields all further items.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@ -305,8 +305,8 @@ pub trait IteratorExt<A>: Iterator<A> {
|
||||
Skip{iter: self, n: n}
|
||||
}
|
||||
|
||||
/// Creates an iterator which yields the first `n` elements of this
|
||||
/// iterator, and then it will always return None.
|
||||
/// Creates an iterator that yields the first `n` elements of this
|
||||
/// iterator, and then will always return None.
|
||||
///
|
||||
/// # Example
|
||||
///
|
||||
@ -324,7 +324,7 @@ pub trait IteratorExt<A>: Iterator<A> {
|
||||
Take{iter: self, n: n}
|
||||
}
|
||||
|
||||
/// Creates a new iterator which behaves in a similar fashion to fold.
|
||||
/// Creates a new iterator that behaves in a similar fashion to fold.
|
||||
/// There is a state which is passed between each iteration and can be
|
||||
/// mutated as necessary. The yielded values from the closure are yielded
|
||||
/// from the Scan instance when not None.
|
||||
@ -1223,7 +1223,7 @@ impl<A, T: Clone + RandomAccessIterator<A>> RandomAccessIterator<A> for Cycle<T>
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which strings two iterators together
|
||||
/// An iterator that strings two iterators together
|
||||
#[deriving(Clone)]
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
#[stable]
|
||||
@ -1297,7 +1297,7 @@ for Chain<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which iterates two other iterators simultaneously
|
||||
/// An iterator that iterates two other iterators simultaneously
|
||||
#[deriving(Clone)]
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
#[stable]
|
||||
@ -1380,7 +1380,7 @@ RandomAccessIterator<(A, B)> for Zip<T, U> {
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which maps the values of `iter` with `f`
|
||||
/// An iterator that maps the values of `iter` with `f`
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
#[stable]
|
||||
pub struct Map<A, B, I: Iterator<A>, F: FnMut(A) -> B> {
|
||||
@ -1388,6 +1388,19 @@ pub struct Map<A, B, I: Iterator<A>, F: FnMut(A) -> B> {
|
||||
f: F,
|
||||
}
|
||||
|
||||
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
|
||||
impl<A, B, I, F> Clone for Map<A, B, I, F> where
|
||||
I: Clone + Iterator<A>,
|
||||
F: Clone + FnMut(A) -> B,
|
||||
{
|
||||
fn clone(&self) -> Map<A, B, I, F> {
|
||||
Map {
|
||||
iter: self.iter.clone(),
|
||||
f: self.f.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, B, I, F> Map<A, B, I, F> where I: Iterator<A>, F: FnMut(A) -> B {
|
||||
#[inline]
|
||||
fn do_map(&mut self, elt: Option<A>) -> Option<B> {
|
||||
@ -1441,7 +1454,7 @@ impl<A, B, I, F> RandomAccessIterator<B> for Map<A, B, I, F> where
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which filters the elements of `iter` with `predicate`
|
||||
/// An iterator that filters the elements of `iter` with `predicate`
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
#[stable]
|
||||
pub struct Filter<A, I, P> where I: Iterator<A>, P: FnMut(&A) -> bool {
|
||||
@ -1449,6 +1462,19 @@ pub struct Filter<A, I, P> where I: Iterator<A>, P: FnMut(&A) -> bool {
|
||||
predicate: P,
|
||||
}
|
||||
|
||||
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
|
||||
impl<A, I, P> Clone for Filter<A, I, P> where
|
||||
I: Clone + Iterator<A>,
|
||||
P: Clone + FnMut(&A) -> bool,
|
||||
{
|
||||
fn clone(&self) -> Filter<A, I, P> {
|
||||
Filter {
|
||||
iter: self.iter.clone(),
|
||||
predicate: self.predicate.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable = "trait is unstable"]
|
||||
impl<A, I, P> Iterator<A> for Filter<A, I, P> where I: Iterator<A>, P: FnMut(&A) -> bool {
|
||||
#[inline]
|
||||
@ -1486,7 +1512,7 @@ impl<A, I, P> DoubleEndedIterator<A> for Filter<A, I, P> where
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which uses `f` to both filter and map elements from `iter`
|
||||
/// An iterator that uses `f` to both filter and map elements from `iter`
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
#[stable]
|
||||
pub struct FilterMap<A, B, I, F> where I: Iterator<A>, F: FnMut(A) -> Option<B> {
|
||||
@ -1494,6 +1520,19 @@ pub struct FilterMap<A, B, I, F> where I: Iterator<A>, F: FnMut(A) -> Option<B>
|
||||
f: F,
|
||||
}
|
||||
|
||||
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
|
||||
impl<A, B, I, F> Clone for FilterMap<A, B, I, F> where
|
||||
I: Clone + Iterator<A>,
|
||||
F: Clone + FnMut(A) -> Option<B>,
|
||||
{
|
||||
fn clone(&self) -> FilterMap<A, B, I, F> {
|
||||
FilterMap {
|
||||
iter: self.iter.clone(),
|
||||
f: self.f.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable = "trait is unstable"]
|
||||
impl<A, B, I, F> Iterator<B> for FilterMap<A, B, I, F> where
|
||||
I: Iterator<A>,
|
||||
@ -1534,7 +1573,7 @@ impl<A, B, I, F> DoubleEndedIterator<B> for FilterMap<A, B, I, F> where
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which yields the current count and the element during iteration
|
||||
/// An iterator that yields the current count and the element during iteration
|
||||
#[deriving(Clone)]
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
#[stable]
|
||||
@ -1648,7 +1687,7 @@ impl<'a, A, T: Iterator<A>> Peekable<A, T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which rejects elements while `predicate` is true
|
||||
/// An iterator that rejects elements while `predicate` is true
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
#[stable]
|
||||
pub struct SkipWhile<A, I, P> where I: Iterator<A>, P: FnMut(&A) -> bool {
|
||||
@ -1657,6 +1696,20 @@ pub struct SkipWhile<A, I, P> where I: Iterator<A>, P: FnMut(&A) -> bool {
|
||||
predicate: P,
|
||||
}
|
||||
|
||||
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
|
||||
impl<A, I, P> Clone for SkipWhile<A, I, P> where
|
||||
I: Clone + Iterator<A>,
|
||||
P: Clone + FnMut(&A) -> bool,
|
||||
{
|
||||
fn clone(&self) -> SkipWhile<A, I, P> {
|
||||
SkipWhile {
|
||||
iter: self.iter.clone(),
|
||||
flag: self.flag,
|
||||
predicate: self.predicate.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable = "trait is unstable"]
|
||||
impl<A, I, P> Iterator<A> for SkipWhile<A, I, P> where I: Iterator<A>, P: FnMut(&A) -> bool {
|
||||
#[inline]
|
||||
@ -1677,7 +1730,7 @@ impl<A, I, P> Iterator<A> for SkipWhile<A, I, P> where I: Iterator<A>, P: FnMut(
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which only accepts elements while `predicate` is true
|
||||
/// An iterator that only accepts elements while `predicate` is true
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
#[stable]
|
||||
pub struct TakeWhile<A, I, P> where I: Iterator<A>, P: FnMut(&A) -> bool {
|
||||
@ -1686,6 +1739,20 @@ pub struct TakeWhile<A, I, P> where I: Iterator<A>, P: FnMut(&A) -> bool {
|
||||
predicate: P,
|
||||
}
|
||||
|
||||
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
|
||||
impl<A, I, P> Clone for TakeWhile<A, I, P> where
|
||||
I: Clone + Iterator<A>,
|
||||
P: Clone + FnMut(&A) -> bool,
|
||||
{
|
||||
fn clone(&self) -> TakeWhile<A, I, P> {
|
||||
TakeWhile {
|
||||
iter: self.iter.clone(),
|
||||
flag: self.flag,
|
||||
predicate: self.predicate.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable = "trait is unstable"]
|
||||
impl<A, I, P> Iterator<A> for TakeWhile<A, I, P> where I: Iterator<A>, P: FnMut(&A) -> bool {
|
||||
#[inline]
|
||||
@ -1714,7 +1781,7 @@ impl<A, I, P> Iterator<A> for TakeWhile<A, I, P> where I: Iterator<A>, P: FnMut(
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which skips over `n` elements of `iter`.
|
||||
/// An iterator that skips over `n` elements of `iter`.
|
||||
#[deriving(Clone)]
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
#[stable]
|
||||
@ -1782,7 +1849,7 @@ impl<A, T: RandomAccessIterator<A>> RandomAccessIterator<A> for Skip<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which only iterates over the first `n` iterations of `iter`.
|
||||
/// An iterator that only iterates over the first `n` iterations of `iter`.
|
||||
#[deriving(Clone)]
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
#[stable]
|
||||
@ -1847,6 +1914,21 @@ pub struct Scan<A, B, I, St, F> where I: Iterator<A>, F: FnMut(&mut St, A) -> Op
|
||||
pub state: St,
|
||||
}
|
||||
|
||||
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
|
||||
impl<A, B, I, St, F> Clone for Scan<A, B, I, St, F> where
|
||||
I: Clone + Iterator<A>,
|
||||
St: Clone,
|
||||
F: Clone + FnMut(&mut St, A) -> Option<B>,
|
||||
{
|
||||
fn clone(&self) -> Scan<A, B, I, St, F> {
|
||||
Scan {
|
||||
iter: self.iter.clone(),
|
||||
f: self.f.clone(),
|
||||
state: self.state.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable = "trait is unstable"]
|
||||
impl<A, B, I, St, F> Iterator<B> for Scan<A, B, I, St, F> where
|
||||
I: Iterator<A>,
|
||||
@ -1876,6 +1958,22 @@ pub struct FlatMap<A, B, I, U, F> where I: Iterator<A>, U: Iterator<B>, F: FnMut
|
||||
backiter: Option<U>,
|
||||
}
|
||||
|
||||
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
|
||||
impl<A, B, I, U, F> Clone for FlatMap<A, B, I, U, F> where
|
||||
I: Clone + Iterator<A>,
|
||||
U: Clone + Iterator<B>,
|
||||
F: Clone + FnMut(A) -> U,
|
||||
{
|
||||
fn clone(&self) -> FlatMap<A, B, I, U, F> {
|
||||
FlatMap {
|
||||
iter: self.iter.clone(),
|
||||
f: self.f.clone(),
|
||||
frontiter: self.frontiter.clone(),
|
||||
backiter: self.backiter.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[unstable = "trait is unstable"]
|
||||
impl<A, B, I, U, F> Iterator<B> for FlatMap<A, B, I, U, F> where
|
||||
I: Iterator<A>,
|
||||
@ -2020,6 +2118,19 @@ pub struct Inspect<A, I, F> where I: Iterator<A>, F: FnMut(&A) {
|
||||
f: F,
|
||||
}
|
||||
|
||||
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
|
||||
impl<A, I, F> Clone for Inspect<A, I, F> where
|
||||
I: Clone + Iterator<A>,
|
||||
F: Clone + FnMut(&A),
|
||||
{
|
||||
fn clone(&self) -> Inspect<A, I, F> {
|
||||
Inspect {
|
||||
iter: self.iter.clone(),
|
||||
f: self.f.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A, I, F> Inspect<A, I, F> where I: Iterator<A>, F: FnMut(&A) {
|
||||
#[inline]
|
||||
fn do_inspect(&mut self, elt: Option<A>) -> Option<A> {
|
||||
@ -2075,7 +2186,7 @@ impl<A, I, F> RandomAccessIterator<A> for Inspect<A, I, F> where
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator which passes mutable state to a closure and yields the result.
|
||||
/// An iterator that passes mutable state to a closure and yields the result.
|
||||
///
|
||||
/// # Example: The Fibonacci Sequence
|
||||
///
|
||||
@ -2114,6 +2225,19 @@ pub struct Unfold<A, St, F> where F: FnMut(&mut St) -> Option<A> {
|
||||
pub state: St,
|
||||
}
|
||||
|
||||
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
|
||||
impl<A, St, F> Clone for Unfold<A, St, F> where
|
||||
F: Clone + FnMut(&mut St) -> Option<A>,
|
||||
St: Clone,
|
||||
{
|
||||
fn clone(&self) -> Unfold<A, St, F> {
|
||||
Unfold {
|
||||
f: self.f.clone(),
|
||||
state: self.state.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[experimental]
|
||||
impl<A, St, F> Unfold<A, St, F> where F: FnMut(&mut St) -> Option<A> {
|
||||
/// Creates a new iterator with the specified closure as the "iterator
|
||||
|
@ -259,13 +259,14 @@ pub mod marker {
|
||||
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct InvariantLifetime<'a>;
|
||||
|
||||
impl<'a> Copy for InvariantLifetime<'a> {}
|
||||
|
||||
/// A type which is considered "not sendable", meaning that it cannot
|
||||
/// be safely sent between tasks, even if it is owned. This is
|
||||
/// typically embedded in other types, such as `Gc`, to ensure that
|
||||
/// their instances remain thread-local.
|
||||
#[lang="no_send_bound"]
|
||||
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[allow(missing_copy_implementations)]
|
||||
#[deriving(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct NoSend;
|
||||
|
||||
/// A type which is considered "not POD", meaning that it is not
|
||||
@ -280,8 +281,7 @@ pub mod marker {
|
||||
/// its contents are not threadsafe, hence they cannot be
|
||||
/// shared between tasks.
|
||||
#[lang="no_sync_bound"]
|
||||
#[deriving(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
#[allow(missing_copy_implementations)]
|
||||
#[deriving(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct NoSync;
|
||||
|
||||
/// A type which is considered managed by the GC. This is typically
|
||||
|
@ -13,9 +13,13 @@
|
||||
//! This module contains functions for querying the size and alignment of
|
||||
//! types, initializing and manipulating memory.
|
||||
|
||||
#![stable]
|
||||
|
||||
use kinds::Sized;
|
||||
use intrinsics;
|
||||
use ptr;
|
||||
|
||||
#[stable]
|
||||
pub use intrinsics::transmute;
|
||||
|
||||
/// Moves a thing into the void.
|
||||
@ -29,6 +33,14 @@ pub use intrinsics::transmute;
|
||||
pub use intrinsics::forget;
|
||||
|
||||
/// Returns the size of a type in bytes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// assert_eq!(4, mem::size_of::<i32>());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable]
|
||||
pub fn size_of<T>() -> uint {
|
||||
@ -36,6 +48,14 @@ pub fn size_of<T>() -> uint {
|
||||
}
|
||||
|
||||
/// Returns the size of the type that `_val` points to in bytes.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// assert_eq!(4, mem::size_of_val(&5i32));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable]
|
||||
pub fn size_of_val<T>(_val: &T) -> uint {
|
||||
@ -44,16 +64,30 @@ pub fn size_of_val<T>(_val: &T) -> uint {
|
||||
|
||||
/// Returns the ABI-required minimum alignment of a type
|
||||
///
|
||||
/// This is the alignment used for struct fields. It may be smaller
|
||||
/// than the preferred alignment.
|
||||
/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// assert_eq!(4, mem::min_align_of::<i32>());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable]
|
||||
pub fn min_align_of<T>() -> uint {
|
||||
unsafe { intrinsics::min_align_of::<T>() }
|
||||
}
|
||||
|
||||
/// Returns the ABI-required minimum alignment of the type of the value that
|
||||
/// `_val` points to
|
||||
/// Returns the ABI-required minimum alignment of the type of the value that `_val` points to
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// assert_eq!(4, mem::min_align_of_val(&5i32));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable]
|
||||
pub fn min_align_of_val<T>(_val: &T) -> uint {
|
||||
@ -62,9 +96,16 @@ pub fn min_align_of_val<T>(_val: &T) -> uint {
|
||||
|
||||
/// Returns the alignment in memory for a type.
|
||||
///
|
||||
/// This function will return the alignment, in bytes, of a type in memory. If
|
||||
/// the alignment returned is adhered to, then the type is guaranteed to
|
||||
/// function properly.
|
||||
/// This function will return the alignment, in bytes, of a type in memory. If the alignment
|
||||
/// returned is adhered to, then the type is guaranteed to function properly.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// assert_eq!(4, mem::align_of::<i32>());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable]
|
||||
pub fn align_of<T>() -> uint {
|
||||
@ -77,9 +118,16 @@ pub fn align_of<T>() -> uint {
|
||||
|
||||
/// Returns the alignment of the type of the value that `_val` points to.
|
||||
///
|
||||
/// This is similar to `align_of`, but function will properly handle types such
|
||||
/// as trait objects (in the future), returning the alignment for an arbitrary
|
||||
/// value at runtime.
|
||||
/// This is similar to `align_of`, but function will properly handle types such as trait objects
|
||||
/// (in the future), returning the alignment for an arbitrary value at runtime.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// assert_eq!(4, mem::align_of_val(&5i32));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable]
|
||||
pub fn align_of_val<T>(_val: &T) -> uint {
|
||||
@ -88,15 +136,22 @@ pub fn align_of_val<T>(_val: &T) -> uint {
|
||||
|
||||
/// Create a value initialized to zero.
|
||||
///
|
||||
/// This function is similar to allocating space for a local variable and
|
||||
/// zeroing it out (an unsafe operation).
|
||||
/// This function is similar to allocating space for a local variable and zeroing it out (an unsafe
|
||||
/// operation).
|
||||
///
|
||||
/// Care must be taken when using this function, if the type `T` has a
|
||||
/// destructor and the value falls out of scope (due to unwinding or returning)
|
||||
/// before being initialized, then the destructor will run on zeroed
|
||||
/// data, likely leading to crashes.
|
||||
/// Care must be taken when using this function, if the type `T` has a destructor and the value
|
||||
/// falls out of scope (due to unwinding or returning) before being initialized, then the
|
||||
/// destructor will run on zeroed data, likely leading to crashes.
|
||||
///
|
||||
/// This is useful for FFI functions sometimes, but should generally be avoided.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// let x: int = unsafe { mem::zeroed() };
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable]
|
||||
pub unsafe fn zeroed<T>() -> T {
|
||||
@ -105,20 +160,41 @@ pub unsafe fn zeroed<T>() -> T {
|
||||
|
||||
/// Create an uninitialized value.
|
||||
///
|
||||
/// Care must be taken when using this function, if the type `T` has a
|
||||
/// destructor and the value falls out of scope (due to unwinding or returning)
|
||||
/// before being initialized, then the destructor will run on uninitialized
|
||||
/// data, likely leading to crashes.
|
||||
/// Care must be taken when using this function, if the type `T` has a destructor and the value
|
||||
/// falls out of scope (due to unwinding or returning) before being initialized, then the
|
||||
/// destructor will run on uninitialized data, likely leading to crashes.
|
||||
///
|
||||
/// This is useful for FFI functions sometimes, but should generally be avoided.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// let x: int = unsafe { mem::uninitialized() };
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable]
|
||||
pub unsafe fn uninitialized<T>() -> T {
|
||||
intrinsics::uninit()
|
||||
}
|
||||
|
||||
/// Swap the values at two mutable locations of the same type, without
|
||||
/// deinitialising or copying either one.
|
||||
/// Swap the values at two mutable locations of the same type, without deinitialising or copying
|
||||
/// either one.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// let x = &mut 5i;
|
||||
/// let y = &mut 42i;
|
||||
///
|
||||
/// mem::swap(x, y);
|
||||
///
|
||||
/// assert_eq!(42i, *x);
|
||||
/// assert_eq!(5i, *y);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable]
|
||||
pub fn swap<T>(x: &mut T, y: &mut T) {
|
||||
@ -137,13 +213,26 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
|
||||
}
|
||||
}
|
||||
|
||||
/// Replace the value at a mutable location with a new one, returning the old
|
||||
/// value, without deinitialising or copying either one.
|
||||
/// Replace the value at a mutable location with a new one, returning the old value, without
|
||||
/// deinitialising or copying either one.
|
||||
///
|
||||
/// This is primarily used for transferring and swapping ownership of a value
|
||||
/// in a mutable location. For example, this function allows consumption of
|
||||
/// one field of a struct by replacing it with another value. The normal approach
|
||||
/// doesn't always work:
|
||||
/// This is primarily used for transferring and swapping ownership of a value in a mutable
|
||||
/// location.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// A simple example:
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// let mut v: Vec<i32> = Vec::new();
|
||||
///
|
||||
/// mem::replace(&mut v, Vec::new());
|
||||
/// ```
|
||||
///
|
||||
/// This function allows consumption of one field of a struct by replacing it with another value.
|
||||
/// The normal approach doesn't always work:
|
||||
///
|
||||
/// ```rust,ignore
|
||||
/// struct Buffer<T> { buf: Vec<T> }
|
||||
@ -158,16 +247,16 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Note that `T` does not necessarily implement `Clone`, so it can't even
|
||||
/// clone and reset `self.buf`. But `replace` can be used to disassociate
|
||||
/// the original value of `self.buf` from `self`, allowing it to be returned:
|
||||
/// Note that `T` does not necessarily implement `Clone`, so it can't even clone and reset
|
||||
/// `self.buf`. But `replace` can be used to disassociate the original value of `self.buf` from
|
||||
/// `self`, allowing it to be returned:
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::mem;
|
||||
/// # struct Buffer<T> { buf: Vec<T> }
|
||||
/// impl<T> Buffer<T> {
|
||||
/// fn get_and_reset(&mut self) -> Vec<T> {
|
||||
/// use std::mem::replace;
|
||||
/// replace(&mut self.buf, Vec::new())
|
||||
/// mem::replace(&mut self.buf, Vec::new())
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
@ -180,10 +269,10 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
|
||||
|
||||
/// Disposes of a value.
|
||||
///
|
||||
/// This function can be used to destroy any value by allowing `drop` to take
|
||||
/// ownership of its argument.
|
||||
/// This function can be used to destroy any value by allowing `drop` to take ownership of its
|
||||
/// argument.
|
||||
///
|
||||
/// # Example
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::cell::RefCell;
|
||||
@ -192,6 +281,7 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
|
||||
///
|
||||
/// let mut mutable_borrow = x.borrow_mut();
|
||||
/// *mutable_borrow = 1;
|
||||
///
|
||||
/// drop(mutable_borrow); // relinquish the mutable borrow on this slot
|
||||
///
|
||||
/// let borrow = x.borrow();
|
||||
@ -201,18 +291,25 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
|
||||
#[stable]
|
||||
pub fn drop<T>(_x: T) { }
|
||||
|
||||
/// Interprets `src` as `&U`, and then reads `src` without moving the contained
|
||||
/// value.
|
||||
/// Interprets `src` as `&U`, and then reads `src` without moving the contained value.
|
||||
///
|
||||
/// This function will unsafely assume the pointer `src` is valid for
|
||||
/// `sizeof(U)` bytes by transmuting `&T` to `&U` and then reading the `&U`. It
|
||||
/// will also unsafely create a copy of the contained value instead of moving
|
||||
/// out of `src`.
|
||||
/// This function will unsafely assume the pointer `src` is valid for `sizeof(U)` bytes by
|
||||
/// transmuting `&T` to `&U` and then reading the `&U`. It will also unsafely create a copy of the
|
||||
/// contained value instead of moving out of `src`.
|
||||
///
|
||||
/// It is not a compile-time error if `T` and `U` have different sizes, but it
|
||||
/// is highly encouraged to only invoke this function where `T` and `U` have the
|
||||
/// same size. This function triggers undefined behavior if `U` is larger than
|
||||
/// `T`.
|
||||
/// It is not a compile-time error if `T` and `U` have different sizes, but it is highly encouraged
|
||||
/// to only invoke this function where `T` and `U` have the same size. This function triggers
|
||||
/// undefined behavior if `U` is larger than `T`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use std::mem;
|
||||
///
|
||||
/// let one = unsafe { mem::transmute_copy(&1i) };
|
||||
///
|
||||
/// assert_eq!(1u, one);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable]
|
||||
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
|
||||
@ -223,7 +320,8 @@ pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
|
||||
#[inline]
|
||||
#[unstable = "this function may be removed in the future due to its \
|
||||
questionable utility"]
|
||||
pub unsafe fn copy_lifetime<'a, S, T:'a>(_ptr: &'a S, ptr: &T) -> &'a T {
|
||||
pub unsafe fn copy_lifetime<'a, Sized? S, Sized? T: 'a>(_ptr: &'a S,
|
||||
ptr: &T) -> &'a T {
|
||||
transmute(ptr)
|
||||
}
|
||||
|
||||
@ -231,7 +329,8 @@ pub unsafe fn copy_lifetime<'a, S, T:'a>(_ptr: &'a S, ptr: &T) -> &'a T {
|
||||
#[inline]
|
||||
#[unstable = "this function may be removed in the future due to its \
|
||||
questionable utility"]
|
||||
pub unsafe fn copy_mut_lifetime<'a, S, T:'a>(_ptr: &'a mut S,
|
||||
ptr: &mut T) -> &'a mut T {
|
||||
pub unsafe fn copy_mut_lifetime<'a, Sized? S, Sized? T: 'a>(_ptr: &'a mut S,
|
||||
ptr: &mut T)
|
||||
-> &'a mut T {
|
||||
transmute(ptr)
|
||||
}
|
||||
|
@ -168,8 +168,10 @@ use ops::{Deref, FnOnce};
|
||||
#[stable]
|
||||
pub enum Option<T> {
|
||||
/// No value
|
||||
#[stable]
|
||||
None,
|
||||
/// Some value `T`
|
||||
#[stable]
|
||||
Some(T)
|
||||
}
|
||||
|
||||
@ -261,7 +263,7 @@ impl<T> Option<T> {
|
||||
/// assert_eq!(x, Some(42u));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for mut conventions"]
|
||||
#[stable]
|
||||
pub fn as_mut<'r>(&'r mut self) -> Option<&'r mut T> {
|
||||
match *self {
|
||||
Some(ref mut x) => Some(x),
|
||||
@ -321,7 +323,7 @@ impl<T> Option<T> {
|
||||
/// x.expect("the world is ending"); // panics with `world is ending`
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for conventions"]
|
||||
#[stable]
|
||||
pub fn expect(self, msg: &str) -> T {
|
||||
match self {
|
||||
Some(val) => val,
|
||||
@ -353,7 +355,7 @@ impl<T> Option<T> {
|
||||
/// assert_eq!(x.unwrap(), "air"); // fails
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for conventions"]
|
||||
#[stable]
|
||||
pub fn unwrap(self) -> T {
|
||||
match self {
|
||||
Some(val) => val,
|
||||
@ -370,7 +372,7 @@ impl<T> Option<T> {
|
||||
/// assert_eq!(None.unwrap_or("bike"), "bike");
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for conventions"]
|
||||
#[stable]
|
||||
pub fn unwrap_or(self, def: T) -> T {
|
||||
match self {
|
||||
Some(x) => x,
|
||||
@ -388,7 +390,7 @@ impl<T> Option<T> {
|
||||
/// assert_eq!(None.unwrap_or_else(|| 2 * k), 20u);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for conventions"]
|
||||
#[stable]
|
||||
pub fn unwrap_or_else<F: FnOnce() -> T>(self, f: F) -> T {
|
||||
match self {
|
||||
Some(x) => x,
|
||||
@ -412,7 +414,7 @@ impl<T> Option<T> {
|
||||
/// let num_as_int: Option<uint> = num_as_str.map(|n| n.len());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for unboxed closures"]
|
||||
#[stable]
|
||||
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
|
||||
match self {
|
||||
Some(x) => Some(f(x)),
|
||||
@ -432,7 +434,7 @@ impl<T> Option<T> {
|
||||
/// assert_eq!(x.map_or(42u, |v| v.len()), 42u);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for unboxed closures"]
|
||||
#[stable]
|
||||
pub fn map_or<U, F: FnOnce(T) -> U>(self, def: U, f: F) -> U {
|
||||
match self {
|
||||
Some(t) => f(t),
|
||||
@ -454,7 +456,7 @@ impl<T> Option<T> {
|
||||
/// assert_eq!(x.map_or_else(|| 2 * k, |v| v.len()), 42u);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for unboxed closures"]
|
||||
#[stable]
|
||||
pub fn map_or_else<U, D: FnOnce() -> U, F: FnOnce(T) -> U>(self, def: D, f: F) -> U {
|
||||
match self {
|
||||
Some(t) => f(t),
|
||||
@ -520,9 +522,9 @@ impl<T> Option<T> {
|
||||
/// assert_eq!(x.iter().next(), None);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for iterator conventions"]
|
||||
pub fn iter<'r>(&'r self) -> Item<&'r T> {
|
||||
Item{opt: self.as_ref()}
|
||||
#[stable]
|
||||
pub fn iter(&self) -> Iter<T> {
|
||||
Iter { inner: Item { opt: self.as_ref() } }
|
||||
}
|
||||
|
||||
/// Returns a mutable iterator over the possibly contained value.
|
||||
@ -542,8 +544,8 @@ impl<T> Option<T> {
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for iterator conventions"]
|
||||
pub fn iter_mut<'r>(&'r mut self) -> Item<&'r mut T> {
|
||||
Item{opt: self.as_mut()}
|
||||
pub fn iter_mut(&mut self) -> IterMut<T> {
|
||||
IterMut { inner: Item { opt: self.as_mut() } }
|
||||
}
|
||||
|
||||
/// Returns a consuming iterator over the possibly contained value.
|
||||
@ -560,9 +562,9 @@ impl<T> Option<T> {
|
||||
/// assert!(v.is_empty());
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for iterator conventions"]
|
||||
pub fn into_iter(self) -> Item<T> {
|
||||
Item{opt: self}
|
||||
#[stable]
|
||||
pub fn into_iter(self) -> IntoIter<T> {
|
||||
IntoIter { inner: Item { opt: self } }
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
@ -614,7 +616,7 @@ impl<T> Option<T> {
|
||||
/// assert_eq!(None.and_then(sq).and_then(sq), None);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for unboxed closures"]
|
||||
#[stable]
|
||||
pub fn and_then<U, F: FnOnce(T) -> Option<U>>(self, f: F) -> Option<U> {
|
||||
match self {
|
||||
Some(x) => f(x),
|
||||
@ -666,7 +668,7 @@ impl<T> Option<T> {
|
||||
/// assert_eq!(None.or_else(nobody), None);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for unboxed closures"]
|
||||
#[stable]
|
||||
pub fn or_else<F: FnOnce() -> Option<T>>(self, f: F) -> Option<T> {
|
||||
match self {
|
||||
Some(_) => self,
|
||||
@ -731,7 +733,7 @@ impl<T: Default> Option<T> {
|
||||
/// assert_eq!(0i, bad_year);
|
||||
/// ```
|
||||
#[inline]
|
||||
#[unstable = "waiting for conventions"]
|
||||
#[stable]
|
||||
pub fn unwrap_or_default(self) -> T {
|
||||
match self {
|
||||
Some(x) => x,
|
||||
@ -744,6 +746,7 @@ impl<T: Default> Option<T> {
|
||||
// Trait implementations
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#[unstable = "waiting on the stability of the trait itself"]
|
||||
impl<T> AsSlice<T> for Option<T> {
|
||||
/// Convert from `Option<T>` to `&[T]` (without copying)
|
||||
#[inline]
|
||||
@ -760,21 +763,18 @@ impl<T> AsSlice<T> for Option<T> {
|
||||
|
||||
#[stable]
|
||||
impl<T> Default for Option<T> {
|
||||
#[stable]
|
||||
#[inline]
|
||||
#[stable]
|
||||
fn default() -> Option<T> { None }
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// The Option Iterator
|
||||
// The Option Iterators
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// An `Option` iterator that yields either one or zero elements
|
||||
///
|
||||
/// The `Item` iterator is returned by the `iter`, `iter_mut` and `into_iter`
|
||||
/// methods on `Option`.
|
||||
#[deriving(Clone)]
|
||||
#[unstable = "waiting for iterator conventions"]
|
||||
pub struct Item<A> {
|
||||
struct Item<A> {
|
||||
opt: Option<A>
|
||||
}
|
||||
|
||||
@ -802,6 +802,66 @@ impl<A> DoubleEndedIterator<A> for Item<A> {
|
||||
|
||||
impl<A> ExactSizeIterator<A> for Item<A> {}
|
||||
|
||||
/// An iterator over a reference of the contained item in an Option.
|
||||
#[stable]
|
||||
pub struct Iter<'a, A: 'a> { inner: Item<&'a A> }
|
||||
|
||||
impl<'a, A> Iterator<&'a A> for Iter<'a, A> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'a A> { self.inner.next() }
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
impl<'a, A> DoubleEndedIterator<&'a A> for Iter<'a, A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<&'a A> { self.inner.next_back() }
|
||||
}
|
||||
|
||||
impl<'a, A> ExactSizeIterator<&'a A> for Iter<'a, A> {}
|
||||
|
||||
impl<'a, A> Clone for Iter<'a, A> {
|
||||
fn clone(&self) -> Iter<'a, A> {
|
||||
Iter { inner: self.inner.clone() }
|
||||
}
|
||||
}
|
||||
|
||||
/// An iterator over a mutable reference of the contained item in an Option.
|
||||
#[stable]
|
||||
pub struct IterMut<'a, A: 'a> { inner: Item<&'a mut A> }
|
||||
|
||||
impl<'a, A> Iterator<&'a mut A> for IterMut<'a, A> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<&'a mut A> { self.inner.next() }
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
impl<'a, A> DoubleEndedIterator<&'a mut A> for IterMut<'a, A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<&'a mut A> { self.inner.next_back() }
|
||||
}
|
||||
|
||||
impl<'a, A> ExactSizeIterator<&'a mut A> for IterMut<'a, A> {}
|
||||
|
||||
/// An iterator over the item contained inside an Option.
|
||||
#[stable]
|
||||
pub struct IntoIter<A> { inner: Item<A> }
|
||||
|
||||
impl<A> Iterator<A> for IntoIter<A> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<A> { self.inner.next() }
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
impl<A> DoubleEndedIterator<A> for IntoIter<A> {
|
||||
#[inline]
|
||||
fn next_back(&mut self) -> Option<A> { self.inner.next_back() }
|
||||
}
|
||||
|
||||
impl<A> ExactSizeIterator<A> for IntoIter<A> {}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// FromIterator
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
@ -826,6 +886,7 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
|
||||
/// assert!(res == Some(vec!(2u, 3u)));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[stable]
|
||||
fn from_iter<I: Iterator<Option<A>>>(iter: I) -> Option<V> {
|
||||
// FIXME(#11084): This could be replaced with Iterator::scan when this
|
||||
// performance bug is closed.
|
||||
@ -860,5 +921,6 @@ impl<A, V: FromIterator<A>> FromIterator<Option<A>> for Option<V> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<T:Copy> Copy for Option<T> {}
|
||||
|
||||
|
@ -292,13 +292,11 @@ impl<T> SliceExt<T> for [T] {
|
||||
if mem::size_of::<T>() == 0 {
|
||||
MutItems{ptr: p,
|
||||
end: (p as uint + self.len()) as *mut T,
|
||||
marker: marker::ContravariantLifetime::<'a>,
|
||||
marker2: marker::NoCopy}
|
||||
marker: marker::ContravariantLifetime::<'a>}
|
||||
} else {
|
||||
MutItems{ptr: p,
|
||||
end: p.offset(self.len() as int),
|
||||
marker: marker::ContravariantLifetime::<'a>,
|
||||
marker2: marker::NoCopy}
|
||||
marker: marker::ContravariantLifetime::<'a>}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -647,8 +645,9 @@ impl<'a, T, Sized? U: AsSlice<T>> AsSlice<T> for &'a mut U {
|
||||
fn as_slice(&self) -> &[T] { AsSlice::as_slice(*self) }
|
||||
}
|
||||
|
||||
#[unstable = "waiting for DST"]
|
||||
#[stable]
|
||||
impl<'a, T> Default for &'a [T] {
|
||||
#[stable]
|
||||
fn default() -> &'a [T] { &[] }
|
||||
}
|
||||
|
||||
@ -818,7 +817,6 @@ pub struct MutItems<'a, T: 'a> {
|
||||
ptr: *mut T,
|
||||
end: *mut T,
|
||||
marker: marker::ContravariantLifetime<'a>,
|
||||
marker2: marker::NoCopy
|
||||
}
|
||||
|
||||
#[experimental]
|
||||
@ -894,6 +892,17 @@ pub struct Splits<'a, T:'a, P> where P: FnMut(&T) -> bool {
|
||||
finished: bool
|
||||
}
|
||||
|
||||
// FIXME(#19839) Remove in favor of `#[deriving(Clone)]`
|
||||
impl<'a, T, P> Clone for Splits<'a, T, P> where P: Clone + FnMut(&T) -> bool {
|
||||
fn clone(&self) -> Splits<'a, T, P> {
|
||||
Splits {
|
||||
v: self.v,
|
||||
pred: self.pred.clone(),
|
||||
finished: self.finished,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[experimental = "needs review"]
|
||||
impl<'a, T, P> Iterator<&'a [T]> for Splits<'a, T, P> where P: FnMut(&T) -> bool {
|
||||
#[inline]
|
||||
|
@ -2349,7 +2349,9 @@ impl StrPrelude for str {
|
||||
fn len(&self) -> uint { self.repr().len }
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<'a> Default for &'a str {
|
||||
#[stable]
|
||||
fn default() -> &'a str { "" }
|
||||
}
|
||||
|
||||
|
@ -182,6 +182,7 @@ macro_rules! tuple_impls {
|
||||
|
||||
#[stable]
|
||||
impl<$($T:Default),+> Default for ($($T,)+) {
|
||||
#[stable]
|
||||
#[inline]
|
||||
fn default() -> ($($T,)+) {
|
||||
($({ let x: $T = Default::default(); x},)+)
|
||||
|
@ -135,38 +135,35 @@ fn test_escape_default() {
|
||||
let s = string('~');
|
||||
assert_eq!(s, "~");
|
||||
let s = string('\x00');
|
||||
assert_eq!(s, "\\x00");
|
||||
assert_eq!(s, "\\u{0}");
|
||||
let s = string('\x1f');
|
||||
assert_eq!(s, "\\x1f");
|
||||
assert_eq!(s, "\\u{1f}");
|
||||
let s = string('\x7f');
|
||||
assert_eq!(s, "\\x7f");
|
||||
let s = string('\u00ff');
|
||||
assert_eq!(s, "\\u00ff");
|
||||
let s = string('\u011b');
|
||||
assert_eq!(s, "\\u011b");
|
||||
let s = string('\U0001d4b6');
|
||||
assert_eq!(s, "\\U0001d4b6");
|
||||
assert_eq!(s, "\\u{7f}");
|
||||
let s = string('\u{ff}');
|
||||
assert_eq!(s, "\\u{ff}");
|
||||
let s = string('\u{11b}');
|
||||
assert_eq!(s, "\\u{11b}");
|
||||
let s = string('\u{1d4b6}');
|
||||
assert_eq!(s, "\\u{1d4b6}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_escape_unicode() {
|
||||
fn string(c: char) -> String {
|
||||
let mut result = String::new();
|
||||
escape_unicode(c, |c| { result.push(c); });
|
||||
return result;
|
||||
}
|
||||
fn string(c: char) -> String { c.escape_unicode().collect() }
|
||||
|
||||
let s = string('\x00');
|
||||
assert_eq!(s, "\\x00");
|
||||
assert_eq!(s, "\\u{0}");
|
||||
let s = string('\n');
|
||||
assert_eq!(s, "\\x0a");
|
||||
assert_eq!(s, "\\u{a}");
|
||||
let s = string(' ');
|
||||
assert_eq!(s, "\\x20");
|
||||
assert_eq!(s, "\\u{20}");
|
||||
let s = string('a');
|
||||
assert_eq!(s, "\\x61");
|
||||
let s = string('\u011b');
|
||||
assert_eq!(s, "\\u011b");
|
||||
let s = string('\U0001d4b6');
|
||||
assert_eq!(s, "\\U0001d4b6");
|
||||
assert_eq!(s, "\\u{61}");
|
||||
let s = string('\u{11b}');
|
||||
assert_eq!(s, "\\u{11b}");
|
||||
let s = string('\u{1d4b6}');
|
||||
assert_eq!(s, "\\u{1d4b6}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -15,32 +15,6 @@ fn test_clone() {
|
||||
assert_eq!(a, b);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_getters() {
|
||||
macro_rules! test_getter(
|
||||
($x:expr, $valN:ident, $refN:ident, $mutN:ident,
|
||||
$init:expr, $incr:expr, $result:expr) => ({
|
||||
assert_eq!($x.$valN(), $init);
|
||||
assert_eq!(*$x.$refN(), $init);
|
||||
*$x.$mutN() += $incr;
|
||||
assert_eq!(*$x.$refN(), $result);
|
||||
})
|
||||
)
|
||||
let mut x = (0u8, 1u16, 2u32, 3u64, 4u, 5i8, 6i16, 7i32, 8i64, 9i, 10f32, 11f64);
|
||||
test_getter!(x, val0, ref0, mut0, 0, 1, 1);
|
||||
test_getter!(x, val1, ref1, mut1, 1, 1, 2);
|
||||
test_getter!(x, val2, ref2, mut2, 2, 1, 3);
|
||||
test_getter!(x, val3, ref3, mut3, 3, 1, 4);
|
||||
test_getter!(x, val4, ref4, mut4, 4, 1, 5);
|
||||
test_getter!(x, val5, ref5, mut5, 5, 1, 6);
|
||||
test_getter!(x, val6, ref6, mut6, 6, 1, 7);
|
||||
test_getter!(x, val7, ref7, mut7, 7, 1, 8);
|
||||
test_getter!(x, val8, ref8, mut8, 8, 1, 9);
|
||||
test_getter!(x, val9, ref9, mut9, 9, 1, 10);
|
||||
test_getter!(x, val10, ref10, mut10, 10.0, 1.0, 11.0);
|
||||
test_getter!(x, val11, ref11, mut11, 11.0, 1.0, 12.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tuple_cmp() {
|
||||
let (small, big) = ((1u, 2u, 3u), (3u, 2u, 1u));
|
||||
|
@ -78,7 +78,7 @@
|
||||
//! ```
|
||||
|
||||
#![crate_name = "getopts"]
|
||||
#![experimental]
|
||||
#![experimental = "use the crates.io `getopts` library instead"]
|
||||
#![crate_type = "rlib"]
|
||||
#![crate_type = "dylib"]
|
||||
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
|
@ -421,6 +421,14 @@ pub trait Labeller<'a,N,E> {
|
||||
}
|
||||
|
||||
impl<'a> LabelText<'a> {
|
||||
pub fn label<S:IntoCow<'a, String, str>>(s: S) -> LabelText<'a> {
|
||||
LabelStr(s.into_cow())
|
||||
}
|
||||
|
||||
pub fn escaped<S:IntoCow<'a, String, str>>(s: S) -> LabelText<'a> {
|
||||
EscStr(s.into_cow())
|
||||
}
|
||||
|
||||
fn escape_char<F>(c: char, mut f: F) where F: FnMut(char) {
|
||||
match c {
|
||||
// not escaping \\, since Graphviz escString needs to
|
||||
@ -505,11 +513,29 @@ pub trait GraphWalk<'a, N, E> {
|
||||
fn target(&'a self, edge: &E) -> N;
|
||||
}
|
||||
|
||||
#[deriving(Copy, PartialEq, Eq, Show)]
|
||||
pub enum RenderOption {
|
||||
NoEdgeLabels,
|
||||
NoNodeLabels,
|
||||
}
|
||||
|
||||
/// Returns vec holding all the default render options.
|
||||
pub fn default_options() -> Vec<RenderOption> { vec![] }
|
||||
|
||||
/// Renders directed graph `g` into the writer `w` in DOT syntax.
|
||||
/// (Main entry point for the library.)
|
||||
/// (Simple wrapper around `render_opts` that passes a default set of options.)
|
||||
pub fn render<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Writer>(
|
||||
g: &'a G,
|
||||
w: &mut W) -> io::IoResult<()>
|
||||
w: &mut W) -> io::IoResult<()> {
|
||||
render_opts(g, w, &[])
|
||||
}
|
||||
|
||||
/// Renders directed graph `g` into the writer `w` in DOT syntax.
|
||||
/// (Main entry point for the library.)
|
||||
pub fn render_opts<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>, W:Writer>(
|
||||
g: &'a G,
|
||||
w: &mut W,
|
||||
options: &[RenderOption]) -> io::IoResult<()>
|
||||
{
|
||||
fn writeln<W:Writer>(w: &mut W, arg: &[&str]) -> io::IoResult<()> {
|
||||
for &s in arg.iter() { try!(w.write_str(s)); }
|
||||
@ -524,9 +550,13 @@ pub fn render<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>,
|
||||
for n in g.nodes().iter() {
|
||||
try!(indent(w));
|
||||
let id = g.node_id(n);
|
||||
let escaped = g.node_label(n).escape();
|
||||
try!(writeln(w, &[id.as_slice(),
|
||||
"[label=\"", escaped.as_slice(), "\"];"]));
|
||||
if options.contains(&RenderOption::NoNodeLabels) {
|
||||
try!(writeln(w, &[id.as_slice(), ";"]));
|
||||
} else {
|
||||
let escaped = g.node_label(n).escape();
|
||||
try!(writeln(w, &[id.as_slice(),
|
||||
"[label=\"", escaped.as_slice(), "\"];"]));
|
||||
}
|
||||
}
|
||||
|
||||
for e in g.edges().iter() {
|
||||
@ -536,8 +566,14 @@ pub fn render<'a, N:Clone+'a, E:Clone+'a, G:Labeller<'a,N,E>+GraphWalk<'a,N,E>,
|
||||
let target = g.target(e);
|
||||
let source_id = g.node_id(&source);
|
||||
let target_id = g.node_id(&target);
|
||||
try!(writeln(w, &[source_id.as_slice(), " -> ", target_id.as_slice(),
|
||||
"[label=\"", escaped_label.as_slice(), "\"];"]));
|
||||
if options.contains(&RenderOption::NoEdgeLabels) {
|
||||
try!(writeln(w, &[source_id.as_slice(),
|
||||
" -> ", target_id.as_slice(), ";"]));
|
||||
} else {
|
||||
try!(writeln(w, &[source_id.as_slice(),
|
||||
" -> ", target_id.as_slice(),
|
||||
"[label=\"", escaped_label.as_slice(), "\"];"]));
|
||||
}
|
||||
}
|
||||
|
||||
writeln(w, &["}"])
|
||||
|
@ -157,7 +157,7 @@
|
||||
//! if logging is disabled, none of the components of the log will be executed.
|
||||
|
||||
#![crate_name = "log"]
|
||||
#![experimental]
|
||||
#![experimental = "use the crates.io `log` library instead"]
|
||||
#![crate_type = "rlib"]
|
||||
#![crate_type = "dylib"]
|
||||
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -185,7 +185,7 @@ pub trait Rng {
|
||||
Rand::rand(self)
|
||||
}
|
||||
|
||||
/// Return an iterator which will yield an infinite number of randomly
|
||||
/// Return an iterator that will yield an infinite number of randomly
|
||||
/// generated items.
|
||||
///
|
||||
/// # Example
|
||||
|
@ -142,7 +142,9 @@ impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
|
||||
*rng = Default::default();
|
||||
}
|
||||
}
|
||||
#[stable]
|
||||
impl Default for ReseedWithDefault {
|
||||
#[stable]
|
||||
fn default() -> ReseedWithDefault { ReseedWithDefault }
|
||||
}
|
||||
|
||||
|
@ -499,8 +499,9 @@ pub mod reader {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
fn read_enum_variant<T, F>(&mut self, _: &[&str], f: F) -> DecodeResult<T> where
|
||||
F: FnOnce(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
|
||||
fn read_enum_variant<T, F>(&mut self, _: &[&str],
|
||||
mut f: F) -> DecodeResult<T>
|
||||
where F: FnMut(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
|
||||
{
|
||||
debug!("read_enum_variant()");
|
||||
let idx = try!(self._next_uint(EsEnumVid));
|
||||
@ -526,8 +527,9 @@ pub mod reader {
|
||||
f(self)
|
||||
}
|
||||
|
||||
fn read_enum_struct_variant<T, F>(&mut self, _: &[&str], f: F) -> DecodeResult<T> where
|
||||
F: FnOnce(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
|
||||
fn read_enum_struct_variant<T, F>(&mut self, _: &[&str],
|
||||
mut f: F) -> DecodeResult<T>
|
||||
where F: FnMut(&mut Decoder<'doc>, uint) -> DecodeResult<T>,
|
||||
{
|
||||
debug!("read_enum_struct_variant()");
|
||||
let idx = try!(self._next_uint(EsEnumVid));
|
||||
@ -610,8 +612,8 @@ pub mod reader {
|
||||
self.read_tuple_arg(idx, f)
|
||||
}
|
||||
|
||||
fn read_option<T, F>(&mut self, f: F) -> DecodeResult<T> where
|
||||
F: FnOnce(&mut Decoder<'doc>, bool) -> DecodeResult<T>,
|
||||
fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T> where
|
||||
F: FnMut(&mut Decoder<'doc>, bool) -> DecodeResult<T>,
|
||||
{
|
||||
debug!("read_option()");
|
||||
self.read_enum("Option", move |this| {
|
||||
|
@ -103,7 +103,9 @@
|
||||
//! let re = regex!(r"(\d{4})-(\d{2})-(\d{2})");
|
||||
//! let text = "2012-03-14, 2013-01-01 and 2014-07-05";
|
||||
//! for cap in re.captures_iter(text) {
|
||||
//! println!("Month: {} Day: {} Year: {}", cap.at(2), cap.at(3), cap.at(1));
|
||||
//! println!("Month: {} Day: {} Year: {}",
|
||||
//! cap.at(2).unwrap_or(""), cap.at(3).unwrap_or(""),
|
||||
//! cap.at(1).unwrap_or(""));
|
||||
//! }
|
||||
//! // Output:
|
||||
//! // Month: 03 Day: 14 Year: 2012
|
||||
@ -285,7 +287,7 @@
|
||||
//! # fn main() {
|
||||
//! let re = regex!(r"(?i)a+(?-i)b+");
|
||||
//! let cap = re.captures("AaAaAbbBBBb").unwrap();
|
||||
//! assert_eq!(cap.at(0), "AaAaAbb");
|
||||
//! assert_eq!(cap.at(0), Some("AaAaAbb"));
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
@ -362,7 +364,7 @@
|
||||
#![crate_name = "regex"]
|
||||
#![crate_type = "rlib"]
|
||||
#![crate_type = "dylib"]
|
||||
#![experimental]
|
||||
#![experimental = "use the crates.io `regex` library instead"]
|
||||
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "http://doc.rust-lang.org/nightly/",
|
||||
|
@ -273,9 +273,9 @@ impl Regex {
|
||||
/// let re = regex!(r"'([^']+)'\s+\((\d{4})\)");
|
||||
/// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
|
||||
/// let caps = re.captures(text).unwrap();
|
||||
/// assert_eq!(caps.at(1), "Citizen Kane");
|
||||
/// assert_eq!(caps.at(2), "1941");
|
||||
/// assert_eq!(caps.at(0), "'Citizen Kane' (1941)");
|
||||
/// assert_eq!(caps.at(1), Some("Citizen Kane"));
|
||||
/// assert_eq!(caps.at(2), Some("1941"));
|
||||
/// assert_eq!(caps.at(0), Some("'Citizen Kane' (1941)"));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
@ -291,9 +291,9 @@ impl Regex {
|
||||
/// let re = regex!(r"'(?P<title>[^']+)'\s+\((?P<year>\d{4})\)");
|
||||
/// let text = "Not my favorite movie: 'Citizen Kane' (1941).";
|
||||
/// let caps = re.captures(text).unwrap();
|
||||
/// assert_eq!(caps.name("title"), "Citizen Kane");
|
||||
/// assert_eq!(caps.name("year"), "1941");
|
||||
/// assert_eq!(caps.at(0), "'Citizen Kane' (1941)");
|
||||
/// assert_eq!(caps.name("title"), Some("Citizen Kane"));
|
||||
/// assert_eq!(caps.name("year"), Some("1941"));
|
||||
/// assert_eq!(caps.at(0), Some("'Citizen Kane' (1941)"));
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
@ -434,7 +434,7 @@ impl Regex {
|
||||
/// # use regex::Captures; fn main() {
|
||||
/// let re = regex!(r"([^,\s]+),\s+(\S+)");
|
||||
/// let result = re.replace("Springsteen, Bruce", |&: caps: &Captures| {
|
||||
/// format!("{} {}", caps.at(2), caps.at(1))
|
||||
/// format!("{} {}", caps.at(2).unwrap_or(""), caps.at(1).unwrap_or(""))
|
||||
/// });
|
||||
/// assert_eq!(result.as_slice(), "Bruce Springsteen");
|
||||
/// # }
|
||||
@ -712,27 +712,25 @@ impl<'t> Captures<'t> {
|
||||
Some((self.locs[s].unwrap(), self.locs[e].unwrap()))
|
||||
}
|
||||
|
||||
/// Returns the matched string for the capture group `i`.
|
||||
/// If `i` isn't a valid capture group or didn't match anything, then the
|
||||
/// empty string is returned.
|
||||
pub fn at(&self, i: uint) -> &'t str {
|
||||
/// Returns the matched string for the capture group `i`. If `i` isn't
|
||||
/// a valid capture group or didn't match anything, then `None` is
|
||||
/// returned.
|
||||
pub fn at(&self, i: uint) -> Option<&'t str> {
|
||||
match self.pos(i) {
|
||||
None => "",
|
||||
Some((s, e)) => {
|
||||
self.text.slice(s, e)
|
||||
}
|
||||
None => None,
|
||||
Some((s, e)) => Some(self.text.slice(s, e))
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the matched string for the capture group named `name`.
|
||||
/// If `name` isn't a valid capture group or didn't match anything, then
|
||||
/// the empty string is returned.
|
||||
pub fn name(&self, name: &str) -> &'t str {
|
||||
/// Returns the matched string for the capture group named `name`. If
|
||||
/// `name` isn't a valid capture group or didn't match anything, then
|
||||
/// `None` is returned.
|
||||
pub fn name(&self, name: &str) -> Option<&'t str> {
|
||||
match self.named {
|
||||
None => "",
|
||||
None => None,
|
||||
Some(ref h) => {
|
||||
match h.get(name) {
|
||||
None => "",
|
||||
None => None,
|
||||
Some(i) => self.at(*i),
|
||||
}
|
||||
}
|
||||
@ -769,11 +767,12 @@ impl<'t> Captures<'t> {
|
||||
// FIXME: Don't use regexes for this. It's completely unnecessary.
|
||||
let re = Regex::new(r"(^|[^$]|\b)\$(\w+)").unwrap();
|
||||
let text = re.replace_all(text, |&mut: refs: &Captures| -> String {
|
||||
let (pre, name) = (refs.at(1), refs.at(2));
|
||||
let pre = refs.at(1).unwrap_or("");
|
||||
let name = refs.at(2).unwrap_or("");
|
||||
format!("{}{}", pre,
|
||||
match from_str::<uint>(name.as_slice()) {
|
||||
None => self.name(name).to_string(),
|
||||
Some(i) => self.at(i).to_string(),
|
||||
None => self.name(name).unwrap_or("").to_string(),
|
||||
Some(i) => self.at(i).unwrap_or("").to_string(),
|
||||
})
|
||||
});
|
||||
let re = Regex::new(r"\$\$").unwrap();
|
||||
@ -802,7 +801,7 @@ impl<'t> Iterator<&'t str> for SubCaptures<'t> {
|
||||
fn next(&mut self) -> Option<&'t str> {
|
||||
if self.idx < self.caps.len() {
|
||||
self.idx += 1;
|
||||
Some(self.caps.at(self.idx - 1))
|
||||
Some(self.caps.at(self.idx - 1).unwrap_or(""))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -13,7 +13,7 @@
|
||||
|
||||
#![crate_name = "regex_macros"]
|
||||
#![crate_type = "dylib"]
|
||||
#![experimental]
|
||||
#![experimental = "use the crates.io `regex_macros` library instead"]
|
||||
#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
||||
|
@ -364,12 +364,12 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
|
||||
}
|
||||
}
|
||||
|
||||
fn encode_path<PI: Iterator<PathElem> + Clone>(rbml_w: &mut Encoder,
|
||||
mut path: PI) {
|
||||
fn encode_path<PI: Iterator<PathElem>>(rbml_w: &mut Encoder, path: PI) {
|
||||
let path = path.collect::<Vec<_>>();
|
||||
rbml_w.start_tag(tag_path);
|
||||
rbml_w.wr_tagged_u32(tag_path_len, path.clone().count() as u32);
|
||||
for pe in path {
|
||||
let tag = match pe {
|
||||
rbml_w.wr_tagged_u32(tag_path_len, path.len() as u32);
|
||||
for pe in path.iter() {
|
||||
let tag = match *pe {
|
||||
ast_map::PathMod(_) => tag_path_elem_mod,
|
||||
ast_map::PathName(_) => tag_path_elem_name
|
||||
};
|
||||
|
@ -462,15 +462,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
self.straightline(expr, pred, [r, l].iter().map(|&e| &**e))
|
||||
}
|
||||
|
||||
ast::ExprBox(Some(ref l), ref r) |
|
||||
ast::ExprIndex(ref l, ref r) |
|
||||
ast::ExprBinary(_, ref l, ref r) => { // NB: && and || handled earlier
|
||||
self.straightline(expr, pred, [l, r].iter().map(|&e| &**e))
|
||||
}
|
||||
|
||||
ast::ExprBox(ref p, ref e) => {
|
||||
self.straightline(expr, pred, [p, e].iter().map(|&e| &**e))
|
||||
}
|
||||
|
||||
ast::ExprBox(None, ref e) |
|
||||
ast::ExprAddrOf(_, ref e) |
|
||||
ast::ExprCast(ref e, _) |
|
||||
ast::ExprUnary(_, ref e) |
|
||||
|
@ -631,7 +631,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||
}
|
||||
|
||||
ast::ExprBox(ref place, ref base) => {
|
||||
self.consume_expr(&**place);
|
||||
match *place {
|
||||
Some(ref place) => self.consume_expr(&**place),
|
||||
None => {}
|
||||
}
|
||||
self.consume_expr(&**base);
|
||||
}
|
||||
|
||||
|
@ -552,17 +552,18 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
|
||||
b.repr(self.get_ref().infcx.tcx));
|
||||
|
||||
let mt_a = match *sty_a {
|
||||
ty::ty_rptr(_, mt) => mt,
|
||||
ty::ty_rptr(_, mt) | ty::ty_ptr(mt) => mt,
|
||||
_ => {
|
||||
return self.subtype(a, b);
|
||||
}
|
||||
};
|
||||
|
||||
// Check that the types which they point at are compatible.
|
||||
// Note that we don't adjust the mutability here. We cannot change
|
||||
// the mutability and the kind of pointer in a single coercion.
|
||||
let a_unsafe = ty::mk_ptr(self.get_ref().infcx.tcx, mt_a);
|
||||
let a_unsafe = ty::mk_ptr(self.get_ref().infcx.tcx, ty::mt{ mutbl: mutbl_b, ty: mt_a.ty });
|
||||
try!(self.subtype(a_unsafe, b));
|
||||
if !can_coerce_mutbls(mt_a.mutbl, mutbl_b) {
|
||||
return Err(ty::terr_mutability);
|
||||
}
|
||||
|
||||
// Although references and unsafe ptrs have the same
|
||||
// representation, we still register an AutoDerefRef so that
|
||||
|
@ -814,8 +814,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
self.region_vars.new_bound(debruijn)
|
||||
}
|
||||
|
||||
pub fn resolve_regions_and_report_errors(&self) {
|
||||
let errors = self.region_vars.resolve_regions();
|
||||
pub fn resolve_regions_and_report_errors(&self, subject_node_id: ast::NodeId) {
|
||||
let errors = self.region_vars.resolve_regions(subject_node_id);
|
||||
self.report_region_errors(&errors); // see error_reporting.rs
|
||||
}
|
||||
|
||||
|
227
src/librustc/middle/infer/region_inference/graphviz.rs
Normal file
227
src/librustc/middle/infer/region_inference/graphviz.rs
Normal file
@ -0,0 +1,227 @@
|
||||
// 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.
|
||||
|
||||
//! This module provides linkage between libgraphviz traits and
|
||||
//! `rustc::middle::typeck::infer::region_inference`, generating a
|
||||
//! rendering of the graph represented by the list of `Constraint`
|
||||
//! instances (which make up the edges of the graph), as well as the
|
||||
//! origin for each constraint (which are attached to the labels on
|
||||
//! each edge).
|
||||
|
||||
/// For clarity, rename the graphviz crate locally to dot.
|
||||
use graphviz as dot;
|
||||
|
||||
use middle::ty;
|
||||
use super::Constraint;
|
||||
use middle::infer::SubregionOrigin;
|
||||
use middle::infer::region_inference::RegionVarBindings;
|
||||
use session::config;
|
||||
use util::nodemap::{FnvHashMap, FnvHashSet};
|
||||
use util::ppaux::Repr;
|
||||
|
||||
use std::collections::hash_map::Vacant;
|
||||
use std::io::{mod, File};
|
||||
use std::os;
|
||||
use std::sync::atomic;
|
||||
use syntax::ast;
|
||||
|
||||
fn print_help_message() {
|
||||
println!("\
|
||||
-Z print-region-graph by default prints a region constraint graph for every \n\
|
||||
function body, to the path `/tmp/constraints.nodeXXX.dot`, where the XXX is \n\
|
||||
replaced with the node id of the function under analysis. \n\
|
||||
\n\
|
||||
To select one particular function body, set `RUST_REGION_GRAPH_NODE=XXX`, \n\
|
||||
where XXX is the node id desired. \n\
|
||||
\n\
|
||||
To generate output to some path other than the default \n\
|
||||
`/tmp/constraints.nodeXXX.dot`, set `RUST_REGION_GRAPH=/path/desired.dot`; \n\
|
||||
occurrences of the character `%` in the requested path will be replaced with\n\
|
||||
the node id of the function under analysis. \n\
|
||||
\n\
|
||||
(Since you requested help via RUST_REGION_GRAPH=help, no region constraint \n\
|
||||
graphs will be printed. \n\
|
||||
");
|
||||
}
|
||||
|
||||
pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a, 'tcx>,
|
||||
subject_node: ast::NodeId) {
|
||||
let tcx = region_vars.tcx;
|
||||
|
||||
if !region_vars.tcx.sess.debugging_opt(config::PRINT_REGION_GRAPH) {
|
||||
return;
|
||||
}
|
||||
|
||||
let requested_node : Option<ast::NodeId> =
|
||||
os::getenv("RUST_REGION_GRAPH_NODE").and_then(|s|from_str(s.as_slice()));
|
||||
|
||||
if requested_node.is_some() && requested_node != Some(subject_node) {
|
||||
return;
|
||||
}
|
||||
|
||||
let requested_output = os::getenv("RUST_REGION_GRAPH");
|
||||
debug!("requested_output: {} requested_node: {}",
|
||||
requested_output, requested_node);
|
||||
|
||||
let output_path = {
|
||||
let output_template = match requested_output {
|
||||
Some(ref s) if s.as_slice() == "help" => {
|
||||
static PRINTED_YET : atomic::AtomicBool = atomic::INIT_ATOMIC_BOOL;
|
||||
if !PRINTED_YET.load(atomic::SeqCst) {
|
||||
print_help_message();
|
||||
PRINTED_YET.store(true, atomic::SeqCst);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
Some(other_path) => other_path,
|
||||
None => "/tmp/constraints.node%.dot".to_string(),
|
||||
};
|
||||
|
||||
if output_template.len() == 0 {
|
||||
tcx.sess.bug("empty string provided as RUST_REGION_GRAPH");
|
||||
}
|
||||
|
||||
if output_template.contains_char('%') {
|
||||
let mut new_str = String::new();
|
||||
for c in output_template.chars() {
|
||||
if c == '%' {
|
||||
new_str.push_str(subject_node.to_string().as_slice());
|
||||
} else {
|
||||
new_str.push(c);
|
||||
}
|
||||
}
|
||||
new_str
|
||||
} else {
|
||||
output_template
|
||||
}
|
||||
};
|
||||
|
||||
let constraints = &*region_vars.constraints.borrow();
|
||||
match dump_region_constraints_to(tcx, constraints, output_path.as_slice()) {
|
||||
Ok(()) => {}
|
||||
Err(e) => {
|
||||
let msg = format!("io error dumping region constraints: {}", e);
|
||||
region_vars.tcx.sess.err(msg.as_slice())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ConstraintGraph<'a, 'tcx: 'a> {
|
||||
tcx: &'a ty::ctxt<'tcx>,
|
||||
graph_name: String,
|
||||
map: &'a FnvHashMap<Constraint, SubregionOrigin<'tcx>>,
|
||||
node_ids: FnvHashMap<Node, uint>,
|
||||
}
|
||||
|
||||
#[deriving(Clone, Hash, PartialEq, Eq, Show)]
|
||||
enum Node {
|
||||
RegionVid(ty::RegionVid),
|
||||
Region(ty::Region),
|
||||
}
|
||||
|
||||
type Edge = Constraint;
|
||||
|
||||
impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> {
|
||||
fn new(tcx: &'a ty::ctxt<'tcx>,
|
||||
name: String,
|
||||
map: &'a ConstraintMap<'tcx>) -> ConstraintGraph<'a, 'tcx> {
|
||||
let mut i = 0;
|
||||
let mut node_ids = FnvHashMap::new();
|
||||
{
|
||||
let add_node = |node| {
|
||||
if let Vacant(e) = node_ids.entry(node) {
|
||||
e.set(i);
|
||||
i += 1;
|
||||
}
|
||||
};
|
||||
|
||||
for (n1, n2) in map.keys().map(|c|constraint_to_nodes(c)) {
|
||||
add_node(n1);
|
||||
add_node(n2);
|
||||
}
|
||||
}
|
||||
|
||||
ConstraintGraph { tcx: tcx,
|
||||
graph_name: name,
|
||||
map: map,
|
||||
node_ids: node_ids }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> dot::Labeller<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> {
|
||||
fn graph_id(&self) -> dot::Id {
|
||||
dot::Id::new(self.graph_name.as_slice()).unwrap()
|
||||
}
|
||||
fn node_id(&self, n: &Node) -> dot::Id {
|
||||
dot::Id::new(format!("node_{}", self.node_ids.get(n).unwrap())).unwrap()
|
||||
}
|
||||
fn node_label(&self, n: &Node) -> dot::LabelText {
|
||||
match *n {
|
||||
Node::RegionVid(n_vid) =>
|
||||
dot::LabelText::label(format!("{}", n_vid)),
|
||||
Node::Region(n_rgn) =>
|
||||
dot::LabelText::label(format!("{}", n_rgn.repr(self.tcx))),
|
||||
}
|
||||
}
|
||||
fn edge_label(&self, e: &Edge) -> dot::LabelText {
|
||||
dot::LabelText::label(format!("{}", self.map.get(e).unwrap().repr(self.tcx)))
|
||||
}
|
||||
}
|
||||
|
||||
fn constraint_to_nodes(c: &Constraint) -> (Node, Node) {
|
||||
match *c {
|
||||
Constraint::ConstrainVarSubVar(rv_1, rv_2) => (Node::RegionVid(rv_1),
|
||||
Node::RegionVid(rv_2)),
|
||||
Constraint::ConstrainRegSubVar(r_1, rv_2) => (Node::Region(r_1),
|
||||
Node::RegionVid(rv_2)),
|
||||
Constraint::ConstrainVarSubReg(rv_1, r_2) => (Node::RegionVid(rv_1),
|
||||
Node::Region(r_2)),
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> dot::GraphWalk<'a, Node, Edge> for ConstraintGraph<'a, 'tcx> {
|
||||
fn nodes(&self) -> dot::Nodes<Node> {
|
||||
let mut set = FnvHashSet::new();
|
||||
for constraint in self.map.keys() {
|
||||
let (n1, n2) = constraint_to_nodes(constraint);
|
||||
set.insert(n1);
|
||||
set.insert(n2);
|
||||
}
|
||||
debug!("constraint graph has {} nodes", set.len());
|
||||
set.into_iter().collect()
|
||||
}
|
||||
fn edges(&self) -> dot::Edges<Edge> {
|
||||
debug!("constraint graph has {} edges", self.map.len());
|
||||
self.map.keys().map(|e|*e).collect()
|
||||
}
|
||||
fn source(&self, edge: &Edge) -> Node {
|
||||
let (n1, _) = constraint_to_nodes(edge);
|
||||
debug!("edge {} has source {}", edge, n1);
|
||||
n1
|
||||
}
|
||||
fn target(&self, edge: &Edge) -> Node {
|
||||
let (_, n2) = constraint_to_nodes(edge);
|
||||
debug!("edge {} has target {}", edge, n2);
|
||||
n2
|
||||
}
|
||||
}
|
||||
|
||||
pub type ConstraintMap<'tcx> = FnvHashMap<Constraint, SubregionOrigin<'tcx>>;
|
||||
|
||||
fn dump_region_constraints_to<'a, 'tcx:'a >(tcx: &'a ty::ctxt<'tcx>,
|
||||
map: &ConstraintMap<'tcx>,
|
||||
path: &str) -> io::IoResult<()> {
|
||||
debug!("dump_region_constraints map (len: {}) path: {}", map.len(), path);
|
||||
let g = ConstraintGraph::new(tcx, format!("region_constraints"), map);
|
||||
let mut f = File::create(&Path::new(path));
|
||||
debug!("dump_region_constraints calling render");
|
||||
dot::render(&g, &mut f)
|
||||
}
|
@ -37,9 +37,10 @@ use std::uint;
|
||||
use syntax::ast;
|
||||
|
||||
mod doc;
|
||||
mod graphviz;
|
||||
|
||||
// A constraint that influences the inference process.
|
||||
#[deriving(PartialEq, Eq, Hash)]
|
||||
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
|
||||
pub enum Constraint {
|
||||
// One region variable is subregion of another
|
||||
ConstrainVarSubVar(RegionVid, RegionVid),
|
||||
@ -706,10 +707,10 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
|
||||
/// fixed-point iteration to find region values which satisfy all
|
||||
/// constraints, assuming such values can be found; if they cannot,
|
||||
/// errors are reported.
|
||||
pub fn resolve_regions(&self) -> Vec<RegionResolutionError<'tcx>> {
|
||||
pub fn resolve_regions(&self, subject_node: ast::NodeId) -> Vec<RegionResolutionError<'tcx>> {
|
||||
debug!("RegionVarBindings: resolve_regions()");
|
||||
let mut errors = vec!();
|
||||
let v = self.infer_variable_values(&mut errors);
|
||||
let v = self.infer_variable_values(&mut errors, subject_node);
|
||||
*self.values.borrow_mut() = Some(v);
|
||||
errors
|
||||
}
|
||||
@ -958,14 +959,15 @@ type RegionGraph = graph::Graph<(), Constraint>;
|
||||
|
||||
impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
|
||||
fn infer_variable_values(&self,
|
||||
errors: &mut Vec<RegionResolutionError<'tcx>>)
|
||||
-> Vec<VarValue>
|
||||
errors: &mut Vec<RegionResolutionError<'tcx>>,
|
||||
subject: ast::NodeId) -> Vec<VarValue>
|
||||
{
|
||||
let mut var_data = self.construct_var_data();
|
||||
|
||||
// Dorky hack to cause `dump_constraints` to only get called
|
||||
// if debug mode is enabled:
|
||||
debug!("----() End constraint listing {}---", self.dump_constraints());
|
||||
graphviz::maybe_print_constraints_for(self, subject);
|
||||
|
||||
self.expansion(var_data.as_mut_slice());
|
||||
self.contraction(var_data.as_mut_slice());
|
||||
|
@ -1199,7 +1199,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
|
||||
ast::ExprIndex(ref l, ref r) |
|
||||
ast::ExprBinary(_, ref l, ref r) |
|
||||
ast::ExprBox(ref l, ref r) => {
|
||||
ast::ExprBox(Some(ref l), ref r) => {
|
||||
let r_succ = self.propagate_through_expr(&**r, succ);
|
||||
self.propagate_through_expr(&**l, r_succ)
|
||||
}
|
||||
@ -1210,6 +1210,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
|
||||
self.propagate_through_expr(&**e1, succ)
|
||||
}
|
||||
|
||||
ast::ExprBox(None, ref e) |
|
||||
ast::ExprAddrOf(_, ref e) |
|
||||
ast::ExprCast(ref e, _) |
|
||||
ast::ExprUnary(_, ref e) |
|
||||
|
@ -1209,6 +1209,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
// is reserve judgement and then intertwine this
|
||||
// analysis with closure inference.
|
||||
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
|
||||
|
||||
// Unboxed closures shouldn't be
|
||||
// implicitly copyable
|
||||
if bound == ty::BoundCopy {
|
||||
return Ok(ParameterBuiltin);
|
||||
}
|
||||
|
||||
match self.tcx().freevars.borrow().get(&def_id.node) {
|
||||
None => {
|
||||
// No upvars.
|
||||
|
@ -4320,12 +4320,13 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
|
||||
|
||||
ast::ExprLit(_) | // Note: LitStr is carved out above
|
||||
ast::ExprUnary(..) |
|
||||
ast::ExprBox(None, _) |
|
||||
ast::ExprAddrOf(..) |
|
||||
ast::ExprBinary(..) => {
|
||||
RvalueDatumExpr
|
||||
}
|
||||
|
||||
ast::ExprBox(ref place, _) => {
|
||||
ast::ExprBox(Some(ref place), _) => {
|
||||
// Special case `Box<T>` for now:
|
||||
let definition = match tcx.def_map.borrow().get(&place.id) {
|
||||
Some(&def) => def,
|
||||
@ -5825,126 +5826,153 @@ pub fn trait_item_of_item(tcx: &ctxt, def_id: ast::DefId)
|
||||
/// context it's calculated within. This is used by the `type_id` intrinsic.
|
||||
pub fn hash_crate_independent(tcx: &ctxt, ty: Ty, svh: &Svh) -> u64 {
|
||||
let mut state = sip::SipState::new();
|
||||
macro_rules! byte( ($b:expr) => { ($b as u8).hash(&mut state) } );
|
||||
macro_rules! hash( ($e:expr) => { $e.hash(&mut state) } );
|
||||
helper(tcx, ty, svh, &mut state);
|
||||
return state.result();
|
||||
|
||||
let region = |_state: &mut sip::SipState, r: Region| {
|
||||
match r {
|
||||
ReStatic => {}
|
||||
fn helper(tcx: &ctxt, ty: Ty, svh: &Svh, state: &mut sip::SipState) {
|
||||
macro_rules! byte( ($b:expr) => { ($b as u8).hash(state) } );
|
||||
macro_rules! hash( ($e:expr) => { $e.hash(state) } );
|
||||
|
||||
ReEmpty |
|
||||
ReEarlyBound(..) |
|
||||
ReLateBound(..) |
|
||||
ReFree(..) |
|
||||
ReScope(..) |
|
||||
ReInfer(..) => {
|
||||
tcx.sess.bug("non-static region found when hashing a type")
|
||||
}
|
||||
}
|
||||
};
|
||||
let did = |state: &mut sip::SipState, did: DefId| {
|
||||
let h = if ast_util::is_local(did) {
|
||||
svh.clone()
|
||||
} else {
|
||||
tcx.sess.cstore.get_crate_hash(did.krate)
|
||||
};
|
||||
h.as_str().hash(state);
|
||||
did.node.hash(state);
|
||||
};
|
||||
let mt = |state: &mut sip::SipState, mt: mt| {
|
||||
mt.mutbl.hash(state);
|
||||
};
|
||||
ty::walk_ty(ty, |ty| {
|
||||
match ty.sty {
|
||||
ty_bool => byte!(2),
|
||||
ty_char => byte!(3),
|
||||
ty_int(i) => {
|
||||
byte!(4);
|
||||
hash!(i);
|
||||
}
|
||||
ty_uint(u) => {
|
||||
byte!(5);
|
||||
hash!(u);
|
||||
}
|
||||
ty_float(f) => {
|
||||
byte!(6);
|
||||
hash!(f);
|
||||
}
|
||||
ty_str => {
|
||||
byte!(7);
|
||||
}
|
||||
ty_enum(d, _) => {
|
||||
byte!(8);
|
||||
did(&mut state, d);
|
||||
}
|
||||
ty_uniq(_) => {
|
||||
byte!(9);
|
||||
}
|
||||
ty_vec(_, Some(n)) => {
|
||||
byte!(10);
|
||||
n.hash(&mut state);
|
||||
}
|
||||
ty_vec(_, None) => {
|
||||
byte!(11);
|
||||
}
|
||||
ty_ptr(m) => {
|
||||
byte!(12);
|
||||
mt(&mut state, m);
|
||||
}
|
||||
ty_rptr(r, m) => {
|
||||
byte!(13);
|
||||
region(&mut state, r);
|
||||
mt(&mut state, m);
|
||||
}
|
||||
ty_bare_fn(ref b) => {
|
||||
byte!(14);
|
||||
hash!(b.unsafety);
|
||||
hash!(b.abi);
|
||||
}
|
||||
ty_closure(ref c) => {
|
||||
byte!(15);
|
||||
hash!(c.unsafety);
|
||||
hash!(c.onceness);
|
||||
hash!(c.bounds);
|
||||
match c.store {
|
||||
UniqTraitStore => byte!(0),
|
||||
RegionTraitStore(r, m) => {
|
||||
byte!(1)
|
||||
region(&mut state, r);
|
||||
assert_eq!(m, ast::MutMutable);
|
||||
}
|
||||
let region = |state: &mut sip::SipState, r: Region| {
|
||||
match r {
|
||||
ReStatic => {}
|
||||
ReLateBound(db, BrAnon(i)) => {
|
||||
db.hash(state);
|
||||
i.hash(state);
|
||||
}
|
||||
ReEmpty |
|
||||
ReEarlyBound(..) |
|
||||
ReLateBound(..) |
|
||||
ReFree(..) |
|
||||
ReScope(..) |
|
||||
ReInfer(..) => {
|
||||
tcx.sess.bug("unexpected region found when hashing a type")
|
||||
}
|
||||
}
|
||||
ty_trait(box TyTrait { ref principal, bounds }) => {
|
||||
byte!(17);
|
||||
did(&mut state, principal.def_id);
|
||||
hash!(bounds);
|
||||
};
|
||||
let did = |state: &mut sip::SipState, did: DefId| {
|
||||
let h = if ast_util::is_local(did) {
|
||||
svh.clone()
|
||||
} else {
|
||||
tcx.sess.cstore.get_crate_hash(did.krate)
|
||||
};
|
||||
h.as_str().hash(state);
|
||||
did.node.hash(state);
|
||||
};
|
||||
let mt = |state: &mut sip::SipState, mt: mt| {
|
||||
mt.mutbl.hash(state);
|
||||
};
|
||||
let fn_sig = |state: &mut sip::SipState, sig: &FnSig| {
|
||||
let sig = anonymize_late_bound_regions(tcx, sig);
|
||||
for a in sig.inputs.iter() { helper(tcx, *a, svh, state); }
|
||||
if let ty::FnConverging(output) = sig.output {
|
||||
helper(tcx, output, svh, state);
|
||||
}
|
||||
ty_struct(d, _) => {
|
||||
byte!(18);
|
||||
did(&mut state, d);
|
||||
}
|
||||
ty_tup(ref inner) => {
|
||||
byte!(19);
|
||||
hash!(inner.len());
|
||||
}
|
||||
ty_param(p) => {
|
||||
byte!(20);
|
||||
hash!(p.idx);
|
||||
did(&mut state, p.def_id);
|
||||
}
|
||||
ty_open(_) => byte!(22),
|
||||
ty_infer(_) => unreachable!(),
|
||||
ty_err => byte!(23),
|
||||
ty_unboxed_closure(d, r, _) => {
|
||||
byte!(24);
|
||||
did(&mut state, d);
|
||||
region(&mut state, r);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
maybe_walk_ty(ty, |ty| {
|
||||
match ty.sty {
|
||||
ty_bool => byte!(2),
|
||||
ty_char => byte!(3),
|
||||
ty_int(i) => {
|
||||
byte!(4);
|
||||
hash!(i);
|
||||
}
|
||||
ty_uint(u) => {
|
||||
byte!(5);
|
||||
hash!(u);
|
||||
}
|
||||
ty_float(f) => {
|
||||
byte!(6);
|
||||
hash!(f);
|
||||
}
|
||||
ty_str => {
|
||||
byte!(7);
|
||||
}
|
||||
ty_enum(d, _) => {
|
||||
byte!(8);
|
||||
did(state, d);
|
||||
}
|
||||
ty_uniq(_) => {
|
||||
byte!(9);
|
||||
}
|
||||
ty_vec(_, Some(n)) => {
|
||||
byte!(10);
|
||||
n.hash(state);
|
||||
}
|
||||
ty_vec(_, None) => {
|
||||
byte!(11);
|
||||
}
|
||||
ty_ptr(m) => {
|
||||
byte!(12);
|
||||
mt(state, m);
|
||||
}
|
||||
ty_rptr(r, m) => {
|
||||
byte!(13);
|
||||
region(state, r);
|
||||
mt(state, m);
|
||||
}
|
||||
ty_bare_fn(ref b) => {
|
||||
byte!(14);
|
||||
hash!(b.unsafety);
|
||||
hash!(b.abi);
|
||||
fn_sig(state, &b.sig);
|
||||
return false;
|
||||
}
|
||||
ty_closure(ref c) => {
|
||||
byte!(15);
|
||||
hash!(c.unsafety);
|
||||
hash!(c.onceness);
|
||||
hash!(c.bounds);
|
||||
match c.store {
|
||||
UniqTraitStore => byte!(0),
|
||||
RegionTraitStore(r, m) => {
|
||||
byte!(1);
|
||||
region(state, r);
|
||||
assert_eq!(m, ast::MutMutable);
|
||||
}
|
||||
}
|
||||
|
||||
state.result()
|
||||
fn_sig(state, &c.sig);
|
||||
|
||||
return false;
|
||||
}
|
||||
ty_trait(box TyTrait { ref principal, bounds }) => {
|
||||
byte!(17);
|
||||
did(state, principal.def_id);
|
||||
hash!(bounds);
|
||||
|
||||
let principal = anonymize_late_bound_regions(tcx, principal);
|
||||
for subty in principal.substs.types.iter() {
|
||||
helper(tcx, *subty, svh, state);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
ty_struct(d, _) => {
|
||||
byte!(18);
|
||||
did(state, d);
|
||||
}
|
||||
ty_tup(ref inner) => {
|
||||
byte!(19);
|
||||
hash!(inner.len());
|
||||
}
|
||||
ty_param(p) => {
|
||||
byte!(20);
|
||||
hash!(p.idx);
|
||||
did(state, p.def_id);
|
||||
}
|
||||
ty_open(_) => byte!(22),
|
||||
ty_infer(_) => unreachable!(),
|
||||
ty_err => byte!(23),
|
||||
ty_unboxed_closure(d, r, _) => {
|
||||
byte!(24);
|
||||
did(state, d);
|
||||
region(state, r);
|
||||
}
|
||||
}
|
||||
true
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl Variance {
|
||||
@ -6284,6 +6312,23 @@ pub fn erase_late_bound_regions<'tcx, HR>(
|
||||
replace_late_bound_regions(tcx, value, |_, _| ty::ReStatic).0
|
||||
}
|
||||
|
||||
/// Rewrite any late-bound regions so that they are anonymous. Region numbers are
|
||||
/// assigned starting at 1 and increasing monotonically in the order traversed
|
||||
/// by the fold operation.
|
||||
///
|
||||
/// The chief purpose of this function is to canonicalize regions so that two
|
||||
/// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become
|
||||
/// structurally identical. For example, `for<'a, 'b> fn(&'a int, &'b int)` and
|
||||
/// `for<'a, 'b> fn(&'b int, &'a int)` will become identical after anonymization.
|
||||
pub fn anonymize_late_bound_regions<'tcx, HR>(tcx: &ctxt<'tcx>, sig: &HR) -> HR
|
||||
where HR: HigherRankedFoldable<'tcx> {
|
||||
let mut counter = 0;
|
||||
replace_late_bound_regions(tcx, sig, |_, db| {
|
||||
counter += 1;
|
||||
ReLateBound(db, BrAnon(counter))
|
||||
}).0
|
||||
}
|
||||
|
||||
/// Replaces the late-bound-regions in `value` that are bound by `value`.
|
||||
pub fn replace_late_bound_regions<'tcx, HR, F>(
|
||||
tcx: &ty::ctxt<'tcx>,
|
||||
|
@ -276,7 +276,8 @@ debugging_opts!(
|
||||
FLOWGRAPH_PRINT_MOVES,
|
||||
FLOWGRAPH_PRINT_ASSIGNS,
|
||||
FLOWGRAPH_PRINT_ALL,
|
||||
PRINT_SYSROOT
|
||||
PRINT_SYSROOT,
|
||||
PRINT_REGION_GRAPH
|
||||
]
|
||||
0
|
||||
)
|
||||
@ -322,7 +323,10 @@ pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
|
||||
("flowgraph-print-all", "Include all dataflow analysis data in \
|
||||
--pretty flowgraph output", FLOWGRAPH_PRINT_ALL),
|
||||
("print-sysroot", "Print the sysroot as used by this rustc invocation",
|
||||
PRINT_SYSROOT)]
|
||||
PRINT_SYSROOT),
|
||||
("print-region-graph", "Prints region inference graph. \
|
||||
Use with RUST_REGION_GRAPH=help for more info",
|
||||
PRINT_REGION_GRAPH)]
|
||||
}
|
||||
|
||||
#[deriving(Clone)]
|
||||
|
@ -428,17 +428,19 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
|
||||
ty_enum(did, ref substs) | ty_struct(did, ref substs) => {
|
||||
let base = ty::item_path_str(cx, did);
|
||||
let generics = ty::lookup_item_type(cx, did).generics;
|
||||
parameterized(cx, base.as_slice(), substs, &generics)
|
||||
parameterized(cx, base.as_slice(), substs, &generics, did)
|
||||
}
|
||||
ty_trait(box ty::TyTrait {
|
||||
ref principal, ref bounds
|
||||
}) => {
|
||||
let base = ty::item_path_str(cx, principal.def_id);
|
||||
let trait_def = ty::lookup_trait_def(cx, principal.def_id);
|
||||
let did = trait_def.trait_ref.def_id;
|
||||
let ty = parameterized(cx, base.as_slice(),
|
||||
&principal.substs, &trait_def.generics);
|
||||
&principal.substs, &trait_def.generics,
|
||||
did);
|
||||
let bound_str = bounds.user_string(cx);
|
||||
let bound_sep = if bound_str.is_empty() { "" } else { "+" };
|
||||
let bound_sep = if bound_str.is_empty() { "" } else { " + " };
|
||||
format!("{}{}{}",
|
||||
ty,
|
||||
bound_sep,
|
||||
@ -484,7 +486,8 @@ pub fn explicit_self_category_to_str(category: &ty::ExplicitSelfCategory)
|
||||
pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
|
||||
base: &str,
|
||||
substs: &subst::Substs<'tcx>,
|
||||
generics: &ty::Generics<'tcx>)
|
||||
generics: &ty::Generics<'tcx>,
|
||||
did: ast::DefId)
|
||||
-> String
|
||||
{
|
||||
if cx.sess.verbose() {
|
||||
@ -537,7 +540,12 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
|
||||
strs.push(ty_to_string(cx, *t))
|
||||
}
|
||||
|
||||
if strs.len() > 0u {
|
||||
if cx.lang_items.fn_trait_kind(did).is_some() {
|
||||
format!("{}({}){}",
|
||||
base,
|
||||
strs[0][1 .. strs[0].len() - (strs[0].ends_with(",)") as uint+1)],
|
||||
if &*strs[1] == "()" { String::new() } else { format!(" -> {}", strs[1]) })
|
||||
} else if strs.len() > 0 {
|
||||
format!("{}<{}>", base, strs.connect(", "))
|
||||
} else {
|
||||
format!("{}", base)
|
||||
@ -743,7 +751,7 @@ impl<'tcx> Repr<'tcx> for ty::TraitRef<'tcx> {
|
||||
let trait_def = ty::lookup_trait_def(tcx, self.def_id);
|
||||
format!("<{} : {}>",
|
||||
self.substs.self_ty().repr(tcx),
|
||||
parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics))
|
||||
parameterized(tcx, base.as_slice(), &self.substs, &trait_def.generics, self.def_id))
|
||||
}
|
||||
}
|
||||
|
||||
@ -1116,7 +1124,7 @@ impl<'tcx> UserString<'tcx> for ty::ParamBounds<'tcx> {
|
||||
for n in self.trait_bounds.iter() {
|
||||
result.push(n.user_string(tcx));
|
||||
}
|
||||
result.connect("+")
|
||||
result.connect(" + ")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1189,7 +1197,8 @@ impl<'tcx> UserString<'tcx> for ty::TraitRef<'tcx> {
|
||||
};
|
||||
|
||||
let trait_def = ty::lookup_trait_def(tcx, self.def_id);
|
||||
parameterized(tcx, base.as_slice(), &trait_ref.substs, &trait_def.generics)
|
||||
let did = trait_def.trait_ref.def_id;
|
||||
parameterized(tcx, base.as_slice(), &trait_ref.substs, &trait_def.generics, did)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,6 @@
|
||||
//! those changes.
|
||||
use self::UndoLog::*;
|
||||
|
||||
use std::kinds::marker;
|
||||
use std::mem;
|
||||
|
||||
#[deriving(PartialEq)]
|
||||
@ -47,10 +46,9 @@ pub struct SnapshotVec<T,U,D> {
|
||||
delegate: D
|
||||
}
|
||||
|
||||
// Snapshots are tokens that should be created/consumed linearly.
|
||||
#[allow(missing_copy_implementations)]
|
||||
pub struct Snapshot {
|
||||
// Snapshots are tokens that should be created/consumed linearly.
|
||||
marker: marker::NoCopy,
|
||||
|
||||
// Length of the undo log at the time the snapshot was taken.
|
||||
length: uint,
|
||||
}
|
||||
@ -112,8 +110,7 @@ impl<T,U,D:SnapshotVecDelegate<T,U>> SnapshotVec<T,U,D> {
|
||||
pub fn start_snapshot(&mut self) -> Snapshot {
|
||||
let length = self.undo_log.len();
|
||||
self.undo_log.push(OpenSnapshot);
|
||||
Snapshot { length: length,
|
||||
marker: marker::NoCopy }
|
||||
Snapshot { length: length }
|
||||
}
|
||||
|
||||
fn assert_open_snapshot(&self, snapshot: &Snapshot) {
|
||||
|
@ -16,8 +16,8 @@
|
||||
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
|
||||
html_root_url = "http://doc.rust-lang.org/nightly/")]
|
||||
|
||||
#![feature(default_type_params, globs, if_let, import_shadowing, macro_rules, phase, quote)]
|
||||
#![feature(slicing_syntax, tuple_indexing, unsafe_destructor)]
|
||||
#![feature(default_type_params, globs, import_shadowing, macro_rules, phase, quote)]
|
||||
#![feature(slicing_syntax, unsafe_destructor)]
|
||||
#![feature(rustc_diagnostic_macros)]
|
||||
#![feature(unboxed_closures)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
@ -325,7 +325,7 @@ impl FromStr for UserIdentifiedItem {
|
||||
}
|
||||
|
||||
enum NodesMatchingUII<'a, 'ast: 'a> {
|
||||
NodesMatchingDirect(option::Item<ast::NodeId>),
|
||||
NodesMatchingDirect(option::IntoIter<ast::NodeId>),
|
||||
NodesMatchingSuffix(ast_map::NodesMatchingSuffix<'a, 'ast, String>),
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ fn test_env<F>(source_string: &str,
|
||||
stability_index);
|
||||
let infcx = infer::new_infer_ctxt(&tcx);
|
||||
body(Env { infcx: &infcx });
|
||||
infcx.resolve_regions_and_report_errors();
|
||||
infcx.resolve_regions_and_report_errors(ast::CRATE_NODE_ID);
|
||||
assert_eq!(tcx.sess.err_count(), expected_err_count);
|
||||
}
|
||||
|
||||
|
@ -3472,7 +3472,8 @@ fn populate_scope_map(cx: &CrateContext,
|
||||
walk_expr(cx, &**sub_exp, scope_stack, scope_map),
|
||||
|
||||
ast::ExprBox(ref place, ref sub_expr) => {
|
||||
walk_expr(cx, &**place, scope_stack, scope_map);
|
||||
place.as_ref().map(
|
||||
|e| walk_expr(cx, &**e, scope_stack, scope_map));
|
||||
walk_expr(cx, &**sub_expr, scope_stack, scope_map);
|
||||
}
|
||||
|
||||
|
@ -1188,7 +1188,7 @@ fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
|
||||
// Finally, resolve all regions. This catches wily misuses of lifetime
|
||||
// parameters.
|
||||
infcx.resolve_regions_and_report_errors();
|
||||
infcx.resolve_regions_and_report_errors(impl_m_body_id);
|
||||
|
||||
/// Check that region bounds on impl method are the same as those on the trait. In principle,
|
||||
/// it could be ok for there to be fewer region bounds on the impl method, but this leads to an
|
||||
@ -3662,22 +3662,25 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
let tcx = fcx.ccx.tcx;
|
||||
let id = expr.id;
|
||||
match expr.node {
|
||||
ast::ExprBox(ref place, ref subexpr) => {
|
||||
check_expr(fcx, &**place);
|
||||
ast::ExprBox(ref opt_place, ref subexpr) => {
|
||||
opt_place.as_ref().map(|place|check_expr(fcx, &**place));
|
||||
check_expr(fcx, &**subexpr);
|
||||
|
||||
let mut checked = false;
|
||||
if let ast::ExprPath(ref path) = place.node {
|
||||
// FIXME(pcwalton): For now we hardcode the two permissible
|
||||
// places: the exchange heap and the managed heap.
|
||||
let definition = lookup_def(fcx, path.span, place.id);
|
||||
let def_id = definition.def_id();
|
||||
let referent_ty = fcx.expr_ty(&**subexpr);
|
||||
if tcx.lang_items.exchange_heap() == Some(def_id) {
|
||||
fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
|
||||
checked = true
|
||||
opt_place.as_ref().map(|place| match place.node {
|
||||
ast::ExprPath(ref path) => {
|
||||
// FIXME(pcwalton): For now we hardcode the two permissible
|
||||
// places: the exchange heap and the managed heap.
|
||||
let definition = lookup_def(fcx, path.span, place.id);
|
||||
let def_id = definition.def_id();
|
||||
let referent_ty = fcx.expr_ty(&**subexpr);
|
||||
if tcx.lang_items.exchange_heap() == Some(def_id) {
|
||||
fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
|
||||
checked = true
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
});
|
||||
|
||||
if !checked {
|
||||
span_err!(tcx.sess, expr.span, E0066,
|
||||
|
@ -139,27 +139,31 @@ use syntax::visit::Visitor;
|
||||
use std::cell::{RefCell};
|
||||
use std::collections::hash_map::{Vacant, Occupied};
|
||||
|
||||
use self::RepeatingScope::Repeating;
|
||||
use self::SubjectNode::Subject;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// PUBLIC ENTRY POINTS
|
||||
|
||||
pub fn regionck_expr(fcx: &FnCtxt, e: &ast::Expr) {
|
||||
let mut rcx = Rcx::new(fcx, e.id);
|
||||
let mut rcx = Rcx::new(fcx, Repeating(e.id), Subject(e.id));
|
||||
if fcx.err_count_since_creation() == 0 {
|
||||
// regionck assumes typeck succeeded
|
||||
rcx.visit_expr(e);
|
||||
rcx.visit_region_obligations(e.id);
|
||||
}
|
||||
fcx.infcx().resolve_regions_and_report_errors();
|
||||
rcx.resolve_regions_and_report_errors();
|
||||
}
|
||||
|
||||
pub fn regionck_item(fcx: &FnCtxt, item: &ast::Item) {
|
||||
let mut rcx = Rcx::new(fcx, item.id);
|
||||
let mut rcx = Rcx::new(fcx, Repeating(item.id), Subject(item.id));
|
||||
rcx.visit_region_obligations(item.id);
|
||||
fcx.infcx().resolve_regions_and_report_errors();
|
||||
rcx.resolve_regions_and_report_errors();
|
||||
}
|
||||
|
||||
pub fn regionck_fn(fcx: &FnCtxt, id: ast::NodeId, decl: &ast::FnDecl, blk: &ast::Block) {
|
||||
let mut rcx = Rcx::new(fcx, blk.id);
|
||||
let mut rcx = Rcx::new(fcx, Repeating(blk.id), Subject(id));
|
||||
if fcx.err_count_since_creation() == 0 {
|
||||
// regionck assumes typeck succeeded
|
||||
rcx.visit_fn_body(id, decl, blk);
|
||||
@ -169,7 +173,7 @@ pub fn regionck_fn(fcx: &FnCtxt, id: ast::NodeId, decl: &ast::FnDecl, blk: &ast:
|
||||
// particularly around closure bounds.
|
||||
vtable::select_all_fcx_obligations_or_error(fcx);
|
||||
|
||||
fcx.infcx().resolve_regions_and_report_errors();
|
||||
rcx.resolve_regions_and_report_errors();
|
||||
}
|
||||
|
||||
/// Checks that the types in `component_tys` are well-formed. This will add constraints into the
|
||||
@ -177,7 +181,7 @@ pub fn regionck_fn(fcx: &FnCtxt, id: ast::NodeId, decl: &ast::FnDecl, blk: &ast:
|
||||
pub fn regionck_ensure_component_tys_wf<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
span: Span,
|
||||
component_tys: &[Ty<'tcx>]) {
|
||||
let mut rcx = Rcx::new(fcx, 0);
|
||||
let mut rcx = Rcx::new(fcx, Repeating(0), SubjectNode::None);
|
||||
for &component_ty in component_tys.iter() {
|
||||
// Check that each type outlives the empty region. Since the
|
||||
// empty region is a subregion of all others, this can't fail
|
||||
@ -225,6 +229,9 @@ pub struct Rcx<'a, 'tcx: 'a> {
|
||||
// id of innermost fn or loop
|
||||
repeating_scope: ast::NodeId,
|
||||
|
||||
// id of AST node being analyzed (the subject of the analysis).
|
||||
subject: SubjectNode,
|
||||
|
||||
// Possible region links we will establish if an upvar
|
||||
// turns out to be unique/mutable
|
||||
maybe_links: MaybeLinkMap<'tcx>
|
||||
@ -251,11 +258,17 @@ fn region_of_def(fcx: &FnCtxt, def: def::Def) -> ty::Region {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum RepeatingScope { Repeating(ast::NodeId) }
|
||||
pub enum SubjectNode { Subject(ast::NodeId), None }
|
||||
|
||||
impl<'a, 'tcx> Rcx<'a, 'tcx> {
|
||||
pub fn new(fcx: &'a FnCtxt<'a, 'tcx>,
|
||||
initial_repeating_scope: ast::NodeId) -> Rcx<'a, 'tcx> {
|
||||
initial_repeating_scope: RepeatingScope,
|
||||
subject: SubjectNode) -> Rcx<'a, 'tcx> {
|
||||
let Repeating(initial_repeating_scope) = initial_repeating_scope;
|
||||
Rcx { fcx: fcx,
|
||||
repeating_scope: initial_repeating_scope,
|
||||
subject: subject,
|
||||
region_param_pairs: Vec::new(),
|
||||
maybe_links: RefCell::new(FnvHashMap::new()) }
|
||||
}
|
||||
@ -425,6 +438,18 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
|
||||
|
||||
debug!("<< relate_free_regions");
|
||||
}
|
||||
|
||||
fn resolve_regions_and_report_errors(&self) {
|
||||
let subject_node_id = match self.subject {
|
||||
Subject(s) => s,
|
||||
SubjectNode::None => {
|
||||
self.tcx().sess.bug("cannot resolve_regions_and_report_errors \
|
||||
without subject node");
|
||||
}
|
||||
};
|
||||
|
||||
self.fcx.infcx().resolve_regions_and_report_errors(subject_node_id);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'fcx, 'tcx> mc::Typer<'tcx> for Rcx<'fcx, 'tcx> {
|
||||
|
@ -2237,6 +2237,6 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
|
||||
format!("mismatched self type: expected `{}`",
|
||||
ppaux::ty_to_string(crate_context.tcx, required_type))
|
||||
}));
|
||||
infcx.resolve_regions_and_report_errors();
|
||||
infcx.resolve_regions_and_report_errors(body_id);
|
||||
}
|
||||
}
|
||||
|
@ -128,5 +128,5 @@ pub mod shouldnt_be_public {
|
||||
|
||||
#[cfg(not(test))]
|
||||
mod std {
|
||||
pub use core::{fmt, option, cmp};
|
||||
pub use core::{fmt, option, cmp, kinds};
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ use libc;
|
||||
|
||||
#[cfg(any(not(target_arch = "arm"), target_os = "ios"))]
|
||||
#[repr(C)]
|
||||
#[deriving(Copy)]
|
||||
pub enum _Unwind_Action {
|
||||
_UA_SEARCH_PHASE = 1,
|
||||
_UA_CLEANUP_PHASE = 2,
|
||||
|
@ -20,7 +20,6 @@ use alloc::boxed::Box;
|
||||
use core::any::Any;
|
||||
use core::atomic::{AtomicUint, SeqCst};
|
||||
use core::iter::{IteratorExt, Take};
|
||||
use core::kinds::marker;
|
||||
use core::ops::FnOnce;
|
||||
use core::mem;
|
||||
use core::ops::FnMut;
|
||||
@ -95,7 +94,6 @@ pub enum BlockedTask {
|
||||
/// Per-task state related to task death, killing, panic, etc.
|
||||
pub struct Death {
|
||||
pub on_exit: Option<Thunk<Result>>,
|
||||
marker: marker::NoCopy,
|
||||
}
|
||||
|
||||
pub struct BlockedTasks {
|
||||
@ -499,7 +497,7 @@ impl BlockedTask {
|
||||
|
||||
impl Death {
|
||||
pub fn new() -> Death {
|
||||
Death { on_exit: None, marker: marker::NoCopy }
|
||||
Death { on_exit: None }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -367,8 +367,8 @@ fn escape_str(writer: &mut io::Writer, v: &str) -> Result<(), io::IoError> {
|
||||
|
||||
fn escape_char(writer: &mut io::Writer, v: char) -> Result<(), io::IoError> {
|
||||
let mut buf = [0, .. 4];
|
||||
v.encode_utf8(&mut buf);
|
||||
escape_bytes(writer, &mut buf)
|
||||
let len = v.encode_utf8(&mut buf).unwrap();
|
||||
escape_bytes(writer, buf[mut ..len])
|
||||
}
|
||||
|
||||
fn spaces(wr: &mut io::Writer, mut n: uint) -> Result<(), io::IoError> {
|
||||
@ -2082,8 +2082,9 @@ impl ::Decoder<DecoderError> for Decoder {
|
||||
f(self)
|
||||
}
|
||||
|
||||
fn read_enum_variant<T, F>(&mut self, names: &[&str], f: F) -> DecodeResult<T> where
|
||||
F: FnOnce(&mut Decoder, uint) -> DecodeResult<T>,
|
||||
fn read_enum_variant<T, F>(&mut self, names: &[&str],
|
||||
mut f: F) -> DecodeResult<T>
|
||||
where F: FnMut(&mut Decoder, uint) -> DecodeResult<T>,
|
||||
{
|
||||
debug!("read_enum_variant(names={})", names);
|
||||
let name = match self.pop() {
|
||||
@ -2133,7 +2134,7 @@ impl ::Decoder<DecoderError> for Decoder {
|
||||
}
|
||||
|
||||
fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> DecodeResult<T> where
|
||||
F: FnOnce(&mut Decoder, uint) -> DecodeResult<T>,
|
||||
F: FnMut(&mut Decoder, uint) -> DecodeResult<T>,
|
||||
{
|
||||
debug!("read_enum_struct_variant(names={})", names);
|
||||
self.read_enum_variant(names, f)
|
||||
@ -2230,8 +2231,8 @@ impl ::Decoder<DecoderError> for Decoder {
|
||||
self.read_tuple_arg(idx, f)
|
||||
}
|
||||
|
||||
fn read_option<T, F>(&mut self, f: F) -> DecodeResult<T> where
|
||||
F: FnOnce(&mut Decoder, bool) -> DecodeResult<T>,
|
||||
fn read_option<T, F>(&mut self, mut f: F) -> DecodeResult<T> where
|
||||
F: FnMut(&mut Decoder, bool) -> DecodeResult<T>,
|
||||
{
|
||||
debug!("read_option()");
|
||||
match self.pop() {
|
||||
@ -2729,37 +2730,39 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
macro_rules! check_encoder_for_simple(
|
||||
($value:expr, $expected:expr) => ({
|
||||
let s = with_str_writer(|writer| {
|
||||
let mut encoder = Encoder::new(writer);
|
||||
$value.encode(&mut encoder).unwrap();
|
||||
});
|
||||
assert_eq!(s, $expected);
|
||||
|
||||
let s = with_str_writer(|writer| {
|
||||
let mut encoder = PrettyEncoder::new(writer);
|
||||
$value.encode(&mut encoder).unwrap();
|
||||
});
|
||||
assert_eq!(s, $expected);
|
||||
})
|
||||
)
|
||||
|
||||
#[test]
|
||||
fn test_write_some() {
|
||||
let value = Some("jodhpurs".into_string());
|
||||
let s = with_str_writer(|writer| {
|
||||
let mut encoder = Encoder::new(writer);
|
||||
value.encode(&mut encoder).unwrap();
|
||||
});
|
||||
assert_eq!(s, "\"jodhpurs\"");
|
||||
|
||||
let value = Some("jodhpurs".into_string());
|
||||
let s = with_str_writer(|writer| {
|
||||
let mut encoder = PrettyEncoder::new(writer);
|
||||
value.encode(&mut encoder).unwrap();
|
||||
});
|
||||
assert_eq!(s, "\"jodhpurs\"");
|
||||
check_encoder_for_simple!(Some("jodhpurs".to_string()), "\"jodhpurs\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_write_none() {
|
||||
let value: Option<string::String> = None;
|
||||
let s = with_str_writer(|writer| {
|
||||
let mut encoder = Encoder::new(writer);
|
||||
value.encode(&mut encoder).unwrap();
|
||||
});
|
||||
assert_eq!(s, "null");
|
||||
check_encoder_for_simple!(None::<string::String>, "null");
|
||||
}
|
||||
|
||||
let s = with_str_writer(|writer| {
|
||||
let mut encoder = Encoder::new(writer);
|
||||
value.encode(&mut encoder).unwrap();
|
||||
});
|
||||
assert_eq!(s, "null");
|
||||
#[test]
|
||||
fn test_write_char() {
|
||||
check_encoder_for_simple!('a', "\"a\"");
|
||||
check_encoder_for_simple!('\t', "\"\\t\"");
|
||||
check_encoder_for_simple!('\u00a0', "\"\u00a0\"");
|
||||
check_encoder_for_simple!('\uabcd', "\"\uabcd\"");
|
||||
check_encoder_for_simple!('\U0010ffff', "\"\U0010ffff\"");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -120,12 +120,12 @@ pub trait Decoder<E> {
|
||||
F: FnOnce(&mut Self) -> Result<T, E>;
|
||||
|
||||
fn read_enum_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, E> where
|
||||
F: FnOnce(&mut Self, uint) -> Result<T, E>;
|
||||
F: FnMut(&mut Self, uint) -> Result<T, E>;
|
||||
fn read_enum_variant_arg<T, F>(&mut self, a_idx: uint, f: F) -> Result<T, E> where
|
||||
F: FnOnce(&mut Self) -> Result<T, E>;
|
||||
|
||||
fn read_enum_struct_variant<T, F>(&mut self, names: &[&str], f: F) -> Result<T, E> where
|
||||
F: FnOnce(&mut Self, uint) -> Result<T, E>;
|
||||
F: FnMut(&mut Self, uint) -> Result<T, E>;
|
||||
fn read_enum_struct_variant_field<T, F>(&mut self,
|
||||
&f_name: &str,
|
||||
f_idx: uint,
|
||||
@ -154,7 +154,7 @@ pub trait Decoder<E> {
|
||||
|
||||
// Specialized types:
|
||||
fn read_option<T, F>(&mut self, f: F) -> Result<T, E> where
|
||||
F: FnOnce(&mut Self, bool) -> Result<T, E>;
|
||||
F: FnMut(&mut Self, bool) -> Result<T, E>;
|
||||
|
||||
fn read_seq<T, F>(&mut self, f: F) -> Result<T, E> where
|
||||
F: FnOnce(&mut Self, uint) -> Result<T, E>;
|
||||
|
@ -20,7 +20,7 @@ use cmp::{max, Eq, Equiv, PartialEq};
|
||||
use default::Default;
|
||||
use fmt::{mod, Show};
|
||||
use hash::{Hash, Hasher, RandomSipHasher};
|
||||
use iter::{mod, Iterator, IteratorExt, FromIterator, Extend};
|
||||
use iter::{mod, Iterator, IteratorExt, FromIterator, Extend, Map};
|
||||
use kinds::Sized;
|
||||
use mem::{mod, replace};
|
||||
use num::{Int, UnsignedInt};
|
||||
@ -297,7 +297,7 @@ pub struct HashMap<K, V, H = RandomSipHasher> {
|
||||
|
||||
/// Search for a pre-hashed key.
|
||||
fn search_hashed<K, V, M, F>(table: M,
|
||||
hash: &SafeHash,
|
||||
hash: SafeHash,
|
||||
mut is_match: F)
|
||||
-> SearchResult<K, V, M> where
|
||||
M: Deref<RawTable<K, V>>,
|
||||
@ -320,14 +320,9 @@ fn search_hashed<K, V, M, F>(table: M,
|
||||
}
|
||||
|
||||
// If the hash doesn't match, it can't be this one..
|
||||
if *hash == full.hash() {
|
||||
let matched = {
|
||||
let (k, _) = full.read();
|
||||
is_match(k)
|
||||
};
|
||||
|
||||
if hash == full.hash() {
|
||||
// If the key doesn't match, it can't be this one..
|
||||
if matched {
|
||||
if is_match(full.read().0) {
|
||||
return FoundExisting(full);
|
||||
}
|
||||
}
|
||||
@ -353,7 +348,7 @@ fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
|
||||
}
|
||||
|
||||
// Now we've done all our shifting. Return the value we grabbed earlier.
|
||||
return (retkey, retval);
|
||||
(retkey, retval)
|
||||
}
|
||||
|
||||
/// Perform robin hood bucket stealing at the given `bucket`. You must
|
||||
@ -389,10 +384,11 @@ fn robin_hood<'a, K: 'a, V: 'a>(mut bucket: FullBucketMut<'a, K, V>,
|
||||
let b = bucket.put(old_hash, old_key, old_val);
|
||||
// Now that it's stolen, just read the value's pointer
|
||||
// right out of the table!
|
||||
let (_, v) = Bucket::at_index(b.into_table(), starting_index).peek()
|
||||
.expect_full()
|
||||
.into_mut_refs();
|
||||
return v;
|
||||
return Bucket::at_index(b.into_table(), starting_index)
|
||||
.peek()
|
||||
.expect_full()
|
||||
.into_mut_refs()
|
||||
.1;
|
||||
},
|
||||
table::Full(bucket) => bucket
|
||||
};
|
||||
@ -441,14 +437,14 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
fn search_equiv<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a self, q: &Q)
|
||||
-> Option<FullBucketImm<'a, K, V>> {
|
||||
let hash = self.make_hash(q);
|
||||
search_hashed(&self.table, &hash, |k| q.equiv(k)).into_option()
|
||||
search_hashed(&self.table, hash, |k| q.equiv(k)).into_option()
|
||||
}
|
||||
|
||||
#[allow(deprecated)]
|
||||
fn search_equiv_mut<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a mut self, q: &Q)
|
||||
-> Option<FullBucketMut<'a, K, V>> {
|
||||
let hash = self.make_hash(q);
|
||||
search_hashed(&mut self.table, &hash, |k| q.equiv(k)).into_option()
|
||||
search_hashed(&mut self.table, hash, |k| q.equiv(k)).into_option()
|
||||
}
|
||||
|
||||
/// Search for a key, yielding the index if it's found in the hashtable.
|
||||
@ -458,7 +454,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
where Q: BorrowFrom<K> + Eq + Hash<S>
|
||||
{
|
||||
let hash = self.make_hash(q);
|
||||
search_hashed(&self.table, &hash, |k| q.eq(BorrowFrom::borrow_from(k)))
|
||||
search_hashed(&self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k)))
|
||||
.into_option()
|
||||
}
|
||||
|
||||
@ -466,14 +462,14 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
where Q: BorrowFrom<K> + Eq + Hash<S>
|
||||
{
|
||||
let hash = self.make_hash(q);
|
||||
search_hashed(&mut self.table, &hash, |k| q.eq(BorrowFrom::borrow_from(k)))
|
||||
search_hashed(&mut self.table, hash, |k| q.eq(BorrowFrom::borrow_from(k)))
|
||||
.into_option()
|
||||
}
|
||||
|
||||
// The caller should ensure that invariants by Robin Hood Hashing hold.
|
||||
fn insert_hashed_ordered(&mut self, hash: SafeHash, k: K, v: V) {
|
||||
let cap = self.table.capacity();
|
||||
let mut buckets = Bucket::new(&mut self.table, &hash);
|
||||
let mut buckets = Bucket::new(&mut self.table, hash);
|
||||
let ib = buckets.index();
|
||||
|
||||
while buckets.index() != ib + cap {
|
||||
@ -762,26 +758,22 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
{
|
||||
// Worst case, we'll find one empty bucket among `size + 1` buckets.
|
||||
let size = self.table.size();
|
||||
let mut probe = Bucket::new(&mut self.table, &hash);
|
||||
let mut probe = Bucket::new(&mut self.table, hash);
|
||||
let ib = probe.index();
|
||||
|
||||
loop {
|
||||
let mut bucket = match probe.peek() {
|
||||
Empty(bucket) => {
|
||||
// Found a hole!
|
||||
let bucket = bucket.put(hash, k, v);
|
||||
let (_, val) = bucket.into_mut_refs();
|
||||
return val;
|
||||
},
|
||||
return bucket.put(hash, k, v).into_mut_refs().1;
|
||||
}
|
||||
Full(bucket) => bucket
|
||||
};
|
||||
|
||||
// hash matches?
|
||||
if bucket.hash() == hash {
|
||||
let found_match = {
|
||||
let (bucket_k, _) = bucket.read_mut();
|
||||
k == *bucket_k
|
||||
};
|
||||
if found_match {
|
||||
// key matches?
|
||||
if k == *bucket.read_mut().0 {
|
||||
let (bucket_k, bucket_v) = bucket.into_mut_refs();
|
||||
debug_assert!(k == *bucket_k);
|
||||
// Key already exists. Get its reference.
|
||||
@ -811,13 +803,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
/// Deprecated: use `get` and `BorrowFrom` instead.
|
||||
#[deprecated = "use get and BorrowFrom instead"]
|
||||
pub fn find_equiv<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
|
||||
match self.search_equiv(k) {
|
||||
None => None,
|
||||
Some(bucket) => {
|
||||
let (_, v_ref) = bucket.into_refs();
|
||||
Some(v_ref)
|
||||
}
|
||||
}
|
||||
self.search_equiv(k).map(|bucket| bucket.into_refs().1)
|
||||
}
|
||||
|
||||
/// Deprecated: use `remove` and `BorrowFrom` instead.
|
||||
@ -829,13 +815,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
|
||||
self.reserve(1);
|
||||
|
||||
match self.search_equiv_mut(k) {
|
||||
Some(bucket) => {
|
||||
let (_k, val) = pop_internal(bucket);
|
||||
Some(val)
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
self.search_equiv_mut(k).map(|bucket| pop_internal(bucket).1)
|
||||
}
|
||||
|
||||
/// An iterator visiting all keys in arbitrary order.
|
||||
@ -859,7 +839,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
pub fn keys(&self) -> Keys<K, V> {
|
||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||
|
||||
self.iter().map(first)
|
||||
Keys { inner: self.iter().map(first) }
|
||||
}
|
||||
|
||||
/// An iterator visiting all values in arbitrary order.
|
||||
@ -883,7 +863,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
pub fn values(&self) -> Values<K, V> {
|
||||
fn second<A, B>((_, b): (A, B)) -> B { b }
|
||||
|
||||
self.iter().map(second)
|
||||
Values { inner: self.iter().map(second) }
|
||||
}
|
||||
|
||||
/// An iterator visiting all key-value pairs in arbitrary order.
|
||||
@ -1022,11 +1002,8 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
|
||||
while buckets.index() != cap {
|
||||
buckets = match buckets.peek() {
|
||||
Empty(b) => b.next(),
|
||||
Full(full) => {
|
||||
let (b, _, _) = full.take();
|
||||
b.next()
|
||||
}
|
||||
Empty(b) => b.next(),
|
||||
Full(full) => full.take().0.next(),
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -1057,10 +1034,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
pub fn get<Sized? Q>(&self, k: &Q) -> Option<&V>
|
||||
where Q: Hash<S> + Eq + BorrowFrom<K>
|
||||
{
|
||||
self.search(k).map(|bucket| {
|
||||
let (_, v) = bucket.into_refs();
|
||||
v
|
||||
})
|
||||
self.search(k).map(|bucket| bucket.into_refs().1)
|
||||
}
|
||||
|
||||
/// Returns true if the map contains a value for the specified key.
|
||||
@ -1115,13 +1089,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
pub fn get_mut<Sized? Q>(&mut self, k: &Q) -> Option<&mut V>
|
||||
where Q: Hash<S> + Eq + BorrowFrom<K>
|
||||
{
|
||||
match self.search_mut(k) {
|
||||
Some(bucket) => {
|
||||
let (_, v) = bucket.into_mut_refs();
|
||||
Some(v)
|
||||
}
|
||||
_ => None
|
||||
}
|
||||
self.search_mut(k).map(|bucket| bucket.into_mut_refs().1)
|
||||
}
|
||||
|
||||
/// Deprecated: Renamed to `insert`.
|
||||
@ -1189,10 +1157,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
|
||||
return None
|
||||
}
|
||||
|
||||
self.search_mut(k).map(|bucket| {
|
||||
let (_k, val) = pop_internal(bucket);
|
||||
val
|
||||
})
|
||||
self.search_mut(k).map(|bucket| pop_internal(bucket).1)
|
||||
}
|
||||
}
|
||||
|
||||
@ -1200,7 +1165,7 @@ fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHas
|
||||
-> Entry<'a, K, V> {
|
||||
// Worst case, we'll find one empty bucket among `size + 1` buckets.
|
||||
let size = table.size();
|
||||
let mut probe = Bucket::new(table, &hash);
|
||||
let mut probe = Bucket::new(table, hash);
|
||||
let ib = probe.index();
|
||||
|
||||
loop {
|
||||
@ -1216,13 +1181,10 @@ fn search_entry_hashed<'a, K: Eq, V>(table: &'a mut RawTable<K,V>, hash: SafeHas
|
||||
Full(bucket) => bucket
|
||||
};
|
||||
|
||||
// hash matches?
|
||||
if bucket.hash() == hash {
|
||||
let is_eq = {
|
||||
let (bucket_k, _) = bucket.read();
|
||||
k == *bucket_k
|
||||
};
|
||||
|
||||
if is_eq {
|
||||
// key matches?
|
||||
if k == *bucket.read().0 {
|
||||
return Occupied(OccupiedEntry{
|
||||
elem: bucket,
|
||||
});
|
||||
@ -1288,7 +1250,9 @@ impl<K: Eq + Hash<S> + Show, V: Show, S, H: Hasher<S>> Show for HashMap<K, V, H>
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H> {
|
||||
#[stable]
|
||||
fn default() -> HashMap<K, V, H> {
|
||||
HashMap::with_hasher(Default::default())
|
||||
}
|
||||
@ -1308,10 +1272,7 @@ impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> IndexMut<Q, V> for HashMap<K
|
||||
{
|
||||
#[inline]
|
||||
fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V {
|
||||
match self.get_mut(index) {
|
||||
Some(v) => v,
|
||||
None => panic!("no entry found for key")
|
||||
}
|
||||
self.get_mut(index).expect("no entry found for key")
|
||||
}
|
||||
}
|
||||
|
||||
@ -1335,6 +1296,16 @@ pub struct MoveEntries<K, V> {
|
||||
>
|
||||
}
|
||||
|
||||
/// HashMap keys iterator
|
||||
pub struct Keys<'a, K: 'a, V: 'a> {
|
||||
inner: Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>
|
||||
}
|
||||
|
||||
/// HashMap values iterator
|
||||
pub struct Values<'a, K: 'a, V: 'a> {
|
||||
inner: Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
|
||||
}
|
||||
|
||||
/// A view into a single occupied location in a HashMap
|
||||
pub struct OccupiedEntry<'a, K:'a, V:'a> {
|
||||
elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
|
||||
@ -1365,56 +1336,45 @@ enum VacantEntryState<K, V, M> {
|
||||
}
|
||||
|
||||
impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<(&'a K, &'a V)> {
|
||||
self.inner.next()
|
||||
}
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
#[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() }
|
||||
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
impl<'a, K, V> Iterator<(&'a K, &'a mut V)> for MutEntries<'a, K, V> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
|
||||
self.inner.next()
|
||||
}
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
#[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() }
|
||||
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
impl<K, V> Iterator<(K, V)> for MoveEntries<K, V> {
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<(K, V)> {
|
||||
self.inner.next()
|
||||
}
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (uint, Option<uint>) {
|
||||
self.inner.size_hint()
|
||||
}
|
||||
#[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
|
||||
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
impl<'a, K, V> Iterator<&'a K> for Keys<'a, K, V> {
|
||||
#[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
|
||||
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
impl<'a, K, V> Iterator<&'a V> for Values<'a, K, V> {
|
||||
#[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
|
||||
#[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
|
||||
}
|
||||
|
||||
impl<'a, K, V> OccupiedEntry<'a, K, V> {
|
||||
/// Gets a reference to the value in the entry
|
||||
pub fn get(&self) -> &V {
|
||||
let (_, v) = self.elem.read();
|
||||
v
|
||||
self.elem.read().1
|
||||
}
|
||||
|
||||
/// Gets a mutable reference to the value in the entry
|
||||
pub fn get_mut(&mut self) -> &mut V {
|
||||
let (_, v) = self.elem.read_mut();
|
||||
v
|
||||
self.elem.read_mut().1
|
||||
}
|
||||
|
||||
/// Converts the OccupiedEntry into a mutable reference to the value in the entry
|
||||
/// with a lifetime bound to the map itself
|
||||
pub fn into_mut(self) -> &'a mut V {
|
||||
let (_, v) = self.elem.into_mut_refs();
|
||||
v
|
||||
self.elem.into_mut_refs().1
|
||||
}
|
||||
|
||||
/// Sets the value of the entry, and returns the entry's old value
|
||||
@ -1426,8 +1386,7 @@ impl<'a, K, V> OccupiedEntry<'a, K, V> {
|
||||
|
||||
/// Takes the value out of the entry, and returns it
|
||||
pub fn take(self) -> V {
|
||||
let (_, v) = pop_internal(self.elem);
|
||||
v
|
||||
pop_internal(self.elem).1
|
||||
}
|
||||
}
|
||||
|
||||
@ -1440,25 +1399,15 @@ impl<'a, K, V> VacantEntry<'a, K, V> {
|
||||
robin_hood(bucket, ib, self.hash, self.key, value)
|
||||
}
|
||||
NoElem(bucket) => {
|
||||
let full = bucket.put(self.hash, self.key, value);
|
||||
let (_, v) = full.into_mut_refs();
|
||||
v
|
||||
bucket.put(self.hash, self.key, value).into_mut_refs().1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// HashMap keys iterator
|
||||
pub type Keys<'a, K, V> =
|
||||
iter::Map<(&'a K, &'a V), &'a K, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a K>;
|
||||
|
||||
/// HashMap values iterator
|
||||
pub type Values<'a, K, V> =
|
||||
iter::Map<(&'a K, &'a V), &'a V, Entries<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>;
|
||||
|
||||
impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> FromIterator<(K, V)> for HashMap<K, V, H> {
|
||||
fn from_iter<T: Iterator<(K, V)>>(iter: T) -> HashMap<K, V, H> {
|
||||
let (lower, _) = iter.size_hint();
|
||||
let lower = iter.size_hint().0;
|
||||
let mut map = HashMap::with_capacity_and_hasher(lower, Default::default());
|
||||
map.extend(iter);
|
||||
map
|
||||
|
@ -17,12 +17,11 @@ use default::Default;
|
||||
use fmt::Show;
|
||||
use fmt;
|
||||
use hash::{Hash, Hasher, RandomSipHasher};
|
||||
use iter::{Iterator, IteratorExt, FromIterator, FilterMap, Chain, Repeat, Zip, Extend, repeat};
|
||||
use iter;
|
||||
use iter::{Iterator, IteratorExt, FromIterator, Map, FilterMap, Chain, Repeat, Zip, Extend, repeat};
|
||||
use option::Option::{Some, None, mod};
|
||||
use result::Result::{Ok, Err};
|
||||
|
||||
use super::map::{HashMap, Entries, MoveEntries, INITIAL_CAPACITY};
|
||||
use super::map::{HashMap, MoveEntries, Keys, INITIAL_CAPACITY};
|
||||
|
||||
// FIXME(conventions): implement BitOr, BitAnd, BitXor, and Sub
|
||||
|
||||
@ -252,7 +251,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
|
||||
/// ```
|
||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||
pub fn iter<'a>(&'a self) -> SetItems<'a, T> {
|
||||
self.map.keys()
|
||||
SetItems { iter: self.map.keys() }
|
||||
}
|
||||
|
||||
/// Creates a consuming iterator, that is, one that moves each value out
|
||||
@ -279,7 +278,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
|
||||
pub fn into_iter(self) -> SetMoveItems<T> {
|
||||
fn first<A, B>((a, _): (A, B)) -> A { a }
|
||||
|
||||
self.map.into_iter().map(first)
|
||||
SetMoveItems { iter: self.map.into_iter().map(first) }
|
||||
}
|
||||
|
||||
/// Visit the values representing the difference.
|
||||
@ -312,7 +311,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
|
||||
if !other.contains(elt) { Some(elt) } else { None }
|
||||
}
|
||||
|
||||
repeat(other).zip(self.iter()).filter_map(filter)
|
||||
SetAlgebraItems { iter: repeat(other).zip(self.iter()).filter_map(filter) }
|
||||
}
|
||||
|
||||
/// Visit the values representing the symmetric difference.
|
||||
@ -337,8 +336,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
|
||||
/// ```
|
||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||
pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
|
||||
-> Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>> {
|
||||
self.difference(other).chain(other.difference(self))
|
||||
-> SymDifferenceItems<'a, T, H> {
|
||||
SymDifferenceItems { iter: self.difference(other).chain(other.difference(self)) }
|
||||
}
|
||||
|
||||
/// Visit the values representing the intersection.
|
||||
@ -366,7 +365,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
|
||||
if other.contains(elt) { Some(elt) } else { None }
|
||||
}
|
||||
|
||||
repeat(other).zip(self.iter()).filter_map(filter)
|
||||
SetAlgebraItems { iter: repeat(other).zip(self.iter()).filter_map(filter) }
|
||||
}
|
||||
|
||||
/// Visit the values representing the union.
|
||||
@ -387,9 +386,8 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
|
||||
/// assert_eq!(diff, [1i, 2, 3, 4].iter().map(|&x| x).collect());
|
||||
/// ```
|
||||
#[unstable = "matches collection reform specification, waiting for dust to settle"]
|
||||
pub fn union<'a>(&'a self, other: &'a HashSet<T, H>)
|
||||
-> Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>> {
|
||||
self.iter().chain(other.difference(self))
|
||||
pub fn union<'a>(&'a self, other: &'a HashSet<T, H>) -> UnionItems<'a, T, H> {
|
||||
UnionItems { iter: self.iter().chain(other.difference(self)) }
|
||||
}
|
||||
|
||||
/// Return the number of elements in the set
|
||||
@ -595,7 +593,7 @@ impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
|
||||
|
||||
impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> FromIterator<T> for HashSet<T, H> {
|
||||
fn from_iter<I: Iterator<T>>(iter: I) -> HashSet<T, H> {
|
||||
let (lower, _) = iter.size_hint();
|
||||
let lower = iter.size_hint().0;
|
||||
let mut set = HashSet::with_capacity_and_hasher(lower, Default::default());
|
||||
set.extend(iter);
|
||||
set
|
||||
@ -610,28 +608,70 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Extend<T> for HashSet<T, H> {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl<T: Eq + Hash<S>, S, H: Hasher<S> + Default> Default for HashSet<T, H> {
|
||||
#[stable]
|
||||
fn default() -> HashSet<T, H> {
|
||||
HashSet::with_hasher(Default::default())
|
||||
}
|
||||
}
|
||||
|
||||
/// HashSet iterator
|
||||
pub type SetItems<'a, K> =
|
||||
iter::Map<(&'a K, &'a ()), &'a K, Entries<'a, K, ()>, fn((&'a K, &'a ())) -> &'a K>;
|
||||
pub struct SetItems<'a, K: 'a> {
|
||||
iter: Keys<'a, K, ()>
|
||||
}
|
||||
|
||||
/// HashSet move iterator
|
||||
pub type SetMoveItems<K> = iter::Map<(K, ()), K, MoveEntries<K, ()>, fn((K, ())) -> K>;
|
||||
pub struct SetMoveItems<K> {
|
||||
iter: Map<(K, ()), K, MoveEntries<K, ()>, fn((K, ())) -> K>
|
||||
}
|
||||
|
||||
// `Repeat` is used to feed the filter closure an explicit capture
|
||||
// of a reference to the other set
|
||||
/// Set operations iterator
|
||||
pub type SetAlgebraItems<'a, T, H> = FilterMap<
|
||||
(&'a HashSet<T, H>, &'a T),
|
||||
&'a T,
|
||||
Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>,
|
||||
for<'b> fn((&HashSet<T, H>, &'b T)) -> Option<&'b T>,
|
||||
>;
|
||||
/// Set operations iterator, used directly for intersection and difference
|
||||
pub struct SetAlgebraItems<'a, T: 'a, H: 'a> {
|
||||
iter: FilterMap<
|
||||
(&'a HashSet<T, H>, &'a T),
|
||||
&'a T,
|
||||
Zip<Repeat<&'a HashSet<T, H>>, SetItems<'a, T>>,
|
||||
for<'b> fn((&HashSet<T, H>, &'b T)) -> Option<&'b T>,
|
||||
>
|
||||
}
|
||||
|
||||
/// Symmetric difference iterator.
|
||||
pub struct SymDifferenceItems<'a, T: 'a, H: 'a> {
|
||||
iter: Chain<SetAlgebraItems<'a, T, H>, SetAlgebraItems<'a, T, H>>
|
||||
}
|
||||
|
||||
/// Set union iterator.
|
||||
pub struct UnionItems<'a, T: 'a, H: 'a> {
|
||||
iter: Chain<SetItems<'a, T>, SetAlgebraItems<'a, T, H>>
|
||||
}
|
||||
|
||||
impl<'a, K> Iterator<&'a K> for SetItems<'a, K> {
|
||||
fn next(&mut self) -> Option<&'a K> { self.iter.next() }
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
impl<K> Iterator<K> for SetMoveItems<K> {
|
||||
fn next(&mut self) -> Option<K> { self.iter.next() }
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
impl<'a, T, H> Iterator<&'a T> for SetAlgebraItems<'a, T, H> {
|
||||
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
impl<'a, T, H> Iterator<&'a T> for SymDifferenceItems<'a, T, H> {
|
||||
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
impl<'a, T, H> Iterator<&'a T> for UnionItems<'a, T, H> {
|
||||
fn next(&mut self) -> Option<&'a T> { self.iter.next() }
|
||||
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_set {
|
||||
|
@ -124,7 +124,7 @@ struct GapThenFull<K, V, M> {
|
||||
|
||||
/// A hash that is not zero, since we use a hash of zero to represent empty
|
||||
/// buckets.
|
||||
#[deriving(PartialEq)]
|
||||
#[deriving(PartialEq, Copy)]
|
||||
pub struct SafeHash {
|
||||
hash: u64,
|
||||
}
|
||||
@ -211,7 +211,7 @@ impl<K, V, M> Bucket<K, V, M> {
|
||||
}
|
||||
|
||||
impl<K, V, M: Deref<RawTable<K, V>>> Bucket<K, V, M> {
|
||||
pub fn new(table: M, hash: &SafeHash) -> Bucket<K, V, M> {
|
||||
pub fn new(table: M, hash: SafeHash) -> Bucket<K, V, M> {
|
||||
Bucket::at_index(table, hash.inspect() as uint)
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@
|
||||
//! Shared usage:
|
||||
//!
|
||||
//! ```
|
||||
//! // Create a shared channel which can be sent along from many tasks
|
||||
//! // Create a shared channel that can be sent along from many tasks
|
||||
//! // where tx is the sending half (tx for transmission), and rx is the receiving
|
||||
//! // half (rx for receiving).
|
||||
//! let (tx, rx) = channel();
|
||||
@ -176,7 +176,7 @@
|
||||
// The choice of implementation of all channels is to be built on lock-free data
|
||||
// structures. The channels themselves are then consequently also lock-free data
|
||||
// structures. As always with lock-free code, this is a very "here be dragons"
|
||||
// territory, especially because I'm unaware of any academic papers which have
|
||||
// territory, especially because I'm unaware of any academic papers that have
|
||||
// gone into great length about channels of these flavors.
|
||||
//
|
||||
// ## Flavors of channels
|
||||
@ -190,7 +190,7 @@
|
||||
// They contain as few atomics as possible and involve one and
|
||||
// exactly one allocation.
|
||||
// * Streams - these channels are optimized for the non-shared use case. They
|
||||
// use a different concurrent queue which is more tailored for this
|
||||
// use a different concurrent queue that is more tailored for this
|
||||
// use case. The initial allocation of this flavor of channel is not
|
||||
// optimized.
|
||||
// * Shared - this is the most general form of channel that this module offers,
|
||||
@ -205,7 +205,7 @@
|
||||
// shared and concurrent queue holding all of the actual data.
|
||||
//
|
||||
// With two flavors of channels, two flavors of queues are also used. We have
|
||||
// chosen to use queues from a well-known author which are abbreviated as SPSC
|
||||
// chosen to use queues from a well-known author that are abbreviated as SPSC
|
||||
// and MPSC (single producer, single consumer and multiple producer, single
|
||||
// consumer). SPSC queues are used for streams while MPSC queues are used for
|
||||
// shared channels.
|
||||
@ -309,7 +309,7 @@
|
||||
//
|
||||
// Sadly this current implementation requires multiple allocations, so I have
|
||||
// seen the throughput of select() be much worse than it should be. I do not
|
||||
// believe that there is anything fundamental which needs to change about these
|
||||
// believe that there is anything fundamental that needs to change about these
|
||||
// channels, however, in order to support a more efficient select().
|
||||
//
|
||||
// # Conclusion
|
||||
@ -910,7 +910,7 @@ impl<T: Send> Receiver<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an iterator which will block waiting for messages, but never
|
||||
/// Returns an iterator that will block waiting for messages, but never
|
||||
/// `panic!`. It will return `None` when the channel has hung up.
|
||||
#[unstable]
|
||||
pub fn iter<'a>(&'a self) -> Messages<'a, T> {
|
||||
|
@ -95,7 +95,9 @@ impl Hasher<sip::SipState> for RandomSipHasher {
|
||||
}
|
||||
}
|
||||
|
||||
#[stable]
|
||||
impl Default for RandomSipHasher {
|
||||
#[stable]
|
||||
#[inline]
|
||||
fn default() -> RandomSipHasher {
|
||||
RandomSipHasher::new()
|
||||
|
@ -200,7 +200,7 @@ impl File {
|
||||
.update_desc("couldn't create file")
|
||||
}
|
||||
|
||||
/// Returns the original path which was used to open this file.
|
||||
/// Returns the original path that was used to open this file.
|
||||
pub fn path<'a>(&'a self) -> &'a Path {
|
||||
&self.path
|
||||
}
|
||||
@ -215,7 +215,7 @@ impl File {
|
||||
}
|
||||
|
||||
/// This function is similar to `fsync`, except that it may not synchronize
|
||||
/// file metadata to the filesystem. This is intended for use case which
|
||||
/// file metadata to the filesystem. This is intended for use cases that
|
||||
/// must synchronize content, but don't need the metadata on disk. The goal
|
||||
/// of this method is to reduce disk operations.
|
||||
pub fn datasync(&mut self) -> IoResult<()> {
|
||||
@ -456,7 +456,7 @@ pub fn symlink(src: &Path, dst: &Path) -> IoResult<()> {
|
||||
/// # Error
|
||||
///
|
||||
/// This function will return an error on failure. Failure conditions include
|
||||
/// reading a file that does not exist or reading a file which is not a symlink.
|
||||
/// reading a file that does not exist or reading a file that is not a symlink.
|
||||
pub fn readlink(path: &Path) -> IoResult<Path> {
|
||||
fs_imp::readlink(path)
|
||||
.update_err("couldn't resolve symlink for path", |e|
|
||||
@ -546,7 +546,7 @@ pub fn readdir(path: &Path) -> IoResult<Vec<Path>> {
|
||||
|e| format!("{}; path={}", e, path.display()))
|
||||
}
|
||||
|
||||
/// Returns an iterator which will recursively walk the directory structure
|
||||
/// Returns an iterator that will recursively walk the directory structure
|
||||
/// rooted at `path`. The path given will not be iterated over, and this will
|
||||
/// perform iteration in some top-down order. The contents of unreadable
|
||||
/// subdirectories are ignored.
|
||||
@ -557,7 +557,7 @@ pub fn walk_dir(path: &Path) -> IoResult<Directories> {
|
||||
})
|
||||
}
|
||||
|
||||
/// An iterator which walks over a directory
|
||||
/// An iterator that walks over a directory
|
||||
pub struct Directories {
|
||||
stack: Vec<Path>,
|
||||
}
|
||||
|
@ -1911,7 +1911,9 @@ bitflags! {
|
||||
}
|
||||
|
||||
|
||||
#[stable]
|
||||
impl Default for FilePermission {
|
||||
#[stable]
|
||||
#[inline]
|
||||
fn default() -> FilePermission { FilePermission::empty() }
|
||||
}
|
||||
|
@ -557,11 +557,12 @@ mod test {
|
||||
let addr1 = next_test_ip4();
|
||||
let addr2 = next_test_ip4();
|
||||
let mut a = UdpSocket::bind(addr1).unwrap();
|
||||
let a2 = UdpSocket::bind(addr2).unwrap();
|
||||
|
||||
let (tx, rx) = channel();
|
||||
let (tx2, rx2) = channel();
|
||||
spawn(move|| {
|
||||
let mut a = UdpSocket::bind(addr2).unwrap();
|
||||
let mut a = a2;
|
||||
assert_eq!(a.recv_from(&mut [0]), Ok((1, addr1)));
|
||||
assert_eq!(a.send_to(&[0], addr1), Ok(()));
|
||||
rx.recv();
|
||||
|
@ -41,6 +41,7 @@ use option::Option;
|
||||
use option::Option::{Some, None};
|
||||
use ops::{Deref, DerefMut, FnOnce};
|
||||
use result::Result::{Ok, Err};
|
||||
use rt;
|
||||
use rustrt;
|
||||
use rustrt::local::Local;
|
||||
use rustrt::task::Task;
|
||||
@ -224,6 +225,12 @@ pub fn stdin() -> StdinReader {
|
||||
inner: Arc::new(Mutex::new(stdin))
|
||||
};
|
||||
STDIN = mem::transmute(box stdin);
|
||||
|
||||
// Make sure to free it at exit
|
||||
rt::at_exit(|| {
|
||||
mem::transmute::<_, Box<StdinReader>>(STDIN);
|
||||
STDIN = 0 as *const _;
|
||||
});
|
||||
});
|
||||
|
||||
(*STDIN).clone()
|
||||
|
@ -117,7 +117,8 @@ mod imp {
|
||||
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
|
||||
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
|
||||
/// service provider with the `PROV_RSA_FULL` type.
|
||||
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
|
||||
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
|
||||
///
|
||||
/// This does not block.
|
||||
pub struct OsRng {
|
||||
inner: OsRngInner,
|
||||
@ -184,10 +185,13 @@ mod imp {
|
||||
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
|
||||
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
|
||||
/// service provider with the `PROV_RSA_FULL` type.
|
||||
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
|
||||
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
|
||||
///
|
||||
/// This does not block.
|
||||
#[allow(missing_copy_implementations)]
|
||||
pub struct OsRng {
|
||||
marker: marker::NoCopy
|
||||
// dummy field to ensure that this struct cannot be constructed outside of this module
|
||||
_dummy: (),
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
@ -205,7 +209,7 @@ mod imp {
|
||||
impl OsRng {
|
||||
/// Create a new `OsRng`.
|
||||
pub fn new() -> IoResult<OsRng> {
|
||||
Ok(OsRng {marker: marker::NoCopy} )
|
||||
Ok(OsRng { _dummy: () })
|
||||
}
|
||||
}
|
||||
|
||||
@ -254,7 +258,8 @@ mod imp {
|
||||
/// `/dev/urandom`, or from `getrandom(2)` system call if available.
|
||||
/// - Windows: calls `CryptGenRandom`, using the default cryptographic
|
||||
/// service provider with the `PROV_RSA_FULL` type.
|
||||
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed
|
||||
/// - iOS: calls SecRandomCopyBytes as /dev/(u)random is sandboxed.
|
||||
///
|
||||
/// This does not block.
|
||||
pub struct OsRng {
|
||||
hcryptprov: HCRYPTPROV
|
||||
|
@ -58,7 +58,6 @@
|
||||
|
||||
use prelude::*;
|
||||
|
||||
use kinds::marker;
|
||||
use rustrt::exclusive::Exclusive;
|
||||
use sync::atomic::{mod, AtomicUint};
|
||||
use sync::{Once, ONCE_INIT};
|
||||
@ -100,7 +99,6 @@ pub struct StaticKey {
|
||||
/// Inner contents of `StaticKey`, created by the `INIT_INNER` constant.
|
||||
pub struct StaticKeyInner {
|
||||
key: AtomicUint,
|
||||
nc: marker::NoCopy,
|
||||
}
|
||||
|
||||
/// A type for a safely managed OS-based TLS slot.
|
||||
@ -141,7 +139,6 @@ pub const INIT: StaticKey = StaticKey {
|
||||
/// This value allows specific configuration of the destructor for a TLS key.
|
||||
pub const INIT_INNER: StaticKeyInner = StaticKeyInner {
|
||||
key: atomic::INIT_ATOMIC_UINT,
|
||||
nc: marker::NoCopy,
|
||||
};
|
||||
|
||||
static INIT_KEYS: Once = ONCE_INIT;
|
||||
|
@ -49,7 +49,7 @@ use boxed::Box;
|
||||
use comm::channel;
|
||||
use core::ops::FnOnce;
|
||||
use io::{Writer, stdio};
|
||||
use kinds::{Send, marker};
|
||||
use kinds::Send;
|
||||
use option::Option;
|
||||
use option::Option::{None, Some};
|
||||
use result::Result;
|
||||
@ -83,7 +83,6 @@ pub struct TaskBuilder {
|
||||
stderr: Option<Box<Writer + Send>>,
|
||||
// Optionally wrap the eventual task body
|
||||
gen_body: Option<Thunk<Thunk, Thunk>>,
|
||||
nocopy: marker::NoCopy,
|
||||
}
|
||||
|
||||
impl TaskBuilder {
|
||||
@ -96,7 +95,6 @@ impl TaskBuilder {
|
||||
stdout: None,
|
||||
stderr: None,
|
||||
gen_body: None,
|
||||
nocopy: marker::NoCopy,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -137,7 +135,7 @@ impl TaskBuilder {
|
||||
on_exit: Option<Thunk<task::Result>>)
|
||||
{
|
||||
let TaskBuilder {
|
||||
name, stack_size, stdout, stderr, mut gen_body, nocopy: _
|
||||
name, stack_size, stdout, stderr, mut gen_body
|
||||
} = self;
|
||||
|
||||
let f = match gen_body.take() {
|
||||
|
@ -185,7 +185,6 @@ macro_rules! __thread_local_inner(
|
||||
inner: ::std::cell::UnsafeCell { value: $init },
|
||||
dtor_registered: ::std::cell::UnsafeCell { value: false },
|
||||
dtor_running: ::std::cell::UnsafeCell { value: false },
|
||||
marker: ::std::kinds::marker::NoCopy,
|
||||
}
|
||||
};
|
||||
|
||||
@ -247,7 +246,6 @@ mod imp {
|
||||
|
||||
use cell::UnsafeCell;
|
||||
use intrinsics;
|
||||
use kinds::marker;
|
||||
use ptr;
|
||||
|
||||
#[doc(hidden)]
|
||||
@ -264,9 +262,6 @@ mod imp {
|
||||
// these variables are thread-local, not global.
|
||||
pub dtor_registered: UnsafeCell<bool>, // should be Cell
|
||||
pub dtor_running: UnsafeCell<bool>, // should be Cell
|
||||
|
||||
// These shouldn't be copied around.
|
||||
pub marker: marker::NoCopy,
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
|
@ -696,7 +696,7 @@ pub struct Expr {
|
||||
#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
|
||||
pub enum Expr_ {
|
||||
/// First expr is the place; second expr is the value.
|
||||
ExprBox(P<Expr>, P<Expr>),
|
||||
ExprBox(Option<P<Expr>>, P<Expr>),
|
||||
ExprVec(Vec<P<Expr>>),
|
||||
ExprCall(P<Expr>, Vec<P<Expr>>),
|
||||
ExprMethodCall(SpannedIdent, Vec<P<Ty>>, Vec<P<Expr>>),
|
||||
|
@ -388,7 +388,7 @@ impl<'a> TraitDef<'a> {
|
||||
methods: Vec<P<ast::Method>>) -> P<ast::Item> {
|
||||
let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
|
||||
|
||||
let Generics { mut lifetimes, ty_params, where_clause: _ } =
|
||||
let Generics { mut lifetimes, ty_params, mut where_clause } =
|
||||
self.generics.to_generics(cx, self.span, type_ident, generics);
|
||||
let mut ty_params = ty_params.into_vec();
|
||||
|
||||
@ -420,13 +420,33 @@ impl<'a> TraitDef<'a> {
|
||||
ty_param.unbound.clone(),
|
||||
None)
|
||||
}));
|
||||
|
||||
// and similarly for where clauses
|
||||
where_clause.predicates.extend(generics.where_clause.predicates.iter().map(|clause| {
|
||||
match *clause {
|
||||
ast::WherePredicate::BoundPredicate(ref wb) => {
|
||||
ast::WherePredicate::BoundPredicate(ast::WhereBoundPredicate {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: self.span,
|
||||
ident: wb.ident,
|
||||
bounds: OwnedSlice::from_vec(wb.bounds.iter().map(|b| b.clone()).collect())
|
||||
})
|
||||
}
|
||||
ast::WherePredicate::EqPredicate(ref we) => {
|
||||
ast::WherePredicate::EqPredicate(ast::WhereEqPredicate {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
span: self.span,
|
||||
path: we.path.clone(),
|
||||
ty: we.ty.clone()
|
||||
})
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
let trait_generics = Generics {
|
||||
lifetimes: lifetimes,
|
||||
ty_params: OwnedSlice::from_vec(ty_params),
|
||||
where_clause: ast::WhereClause {
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
predicates: Vec::new(),
|
||||
},
|
||||
where_clause: where_clause
|
||||
};
|
||||
|
||||
// Create the reference to the trait.
|
||||
|
@ -70,8 +70,28 @@ pub fn expand_meta_deriving(cx: &mut ExtCtxt,
|
||||
|
||||
"Hash" => expand!(hash::expand_deriving_hash),
|
||||
|
||||
"Encodable" => expand!(encodable::expand_deriving_encodable),
|
||||
"Decodable" => expand!(decodable::expand_deriving_decodable),
|
||||
"RustcEncodable" => {
|
||||
expand!(encodable::expand_deriving_encodable)
|
||||
}
|
||||
"RustcDecodable" => {
|
||||
expand!(decodable::expand_deriving_decodable)
|
||||
}
|
||||
"Encodable" => {
|
||||
// NOTE: uncomment after a stage0 snap
|
||||
// cx.span_warn(titem.span,
|
||||
// "deriving(Encodable) is deprecated \
|
||||
// in favor of deriving(RustcEncodable)");
|
||||
|
||||
expand!(encodable::expand_deriving_encodable)
|
||||
}
|
||||
"Decodable" => {
|
||||
// NOTE: uncomment after a stage0 snap
|
||||
// cx.span_warn(titem.span,
|
||||
// "deriving(Decodable) is deprecated \
|
||||
// in favor of deriving(RustcDecodable)");
|
||||
|
||||
expand!(decodable::expand_deriving_decodable)
|
||||
}
|
||||
|
||||
"PartialEq" => expand!(eq::expand_deriving_eq),
|
||||
"Eq" => expand!(totaleq::expand_deriving_totaleq),
|
||||
|
@ -1282,7 +1282,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
|
||||
id: folder.new_id(id),
|
||||
node: match node {
|
||||
ExprBox(p, e) => {
|
||||
ExprBox(folder.fold_expr(p), folder.fold_expr(e))
|
||||
ExprBox(p.map(|e|folder.fold_expr(e)), folder.fold_expr(e))
|
||||
}
|
||||
ExprVec(exprs) => {
|
||||
ExprVec(exprs.move_map(|x| folder.fold_expr(x)))
|
||||
|
@ -2888,7 +2888,7 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
let subexpression = self.parse_prefix_expr();
|
||||
hi = subexpression.span.hi;
|
||||
ex = ExprBox(place, subexpression);
|
||||
ex = ExprBox(Some(place), subexpression);
|
||||
return self.mk_expr(lo, hi, ex);
|
||||
}
|
||||
}
|
||||
@ -2896,6 +2896,9 @@ impl<'a> Parser<'a> {
|
||||
// Otherwise, we use the unique pointer default.
|
||||
let subexpression = self.parse_prefix_expr();
|
||||
hi = subexpression.span.hi;
|
||||
// FIXME (pnkfelix): After working out kinks with box
|
||||
// desugaring, should be `ExprBox(None, subexpression)`
|
||||
// instead.
|
||||
ex = self.mk_unary(UnUniq, subexpression);
|
||||
}
|
||||
_ => return self.parse_dot_or_call_expr()
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user