auto merge of #19958 : alexcrichton/rust/rollup, r=alexcrichton

This commit is contained in:
bors 2014-12-17 21:33:15 +00:00
commit 22a9f250b5
115 changed files with 2330 additions and 1466 deletions

3
.gitmodules vendored
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 '{}'",

View File

@ -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.");

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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:

View File

@ -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}

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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());

View File

@ -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()) }
}

View File

@ -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 [] }
}

View File

@ -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())
}

View File

@ -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() }
}

View File

@ -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() }
}

View File

@ -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.

View File

@ -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
}
}
}

View File

@ -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 {

View File

@ -192,8 +192,10 @@ impl<T> DList<T> {
}
}
#[stable]
impl<T> Default for DList<T> {
#[inline]
#[stable]
fn default() -> DList<T> { DList::new() }
}

View File

@ -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);
}
}

View File

@ -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]

View File

@ -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());

View File

@ -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() }
}

View File

@ -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() }
}

View File

@ -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() }
}

View File

@ -69,8 +69,10 @@ impl Show for TrieSet {
}
}
#[stable]
impl Default for TrieSet {
#[inline]
#[stable]
fn default() -> TrieSet { TrieSet::new() }
}

View File

@ -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();

View File

@ -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 {

View File

@ -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.

View File

@ -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())
}

View File

@ -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()
}
}
}

View File

@ -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 }
}
}

View File

@ -203,8 +203,10 @@ impl Clone for SipState {
}
}
#[stable]
impl Default for SipState {
#[inline]
#[stable]
fn default() -> SipState {
SipState::new()
}

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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)
}

View File

@ -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> {}

View File

@ -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]

View File

@ -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 { "" }
}

View File

@ -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},)+)

View File

@ -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]

View File

@ -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));

View File

@ -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",

View File

@ -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, &["}"])

View File

@ -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",

View File

@ -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

View File

@ -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 }
}

View File

@ -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| {

View File

@ -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/",

View File

@ -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
}

View File

@ -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/")]

View File

@ -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
};

View File

@ -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) |

View File

@ -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);
}

View File

@ -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

View File

@ -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
}

View 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)
}

View File

@ -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());

View File

@ -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) |

View File

@ -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.

View File

@ -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>,

View File

@ -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)]

View File

@ -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)
}
}

View File

@ -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) {

View File

@ -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)]

View File

@ -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>),
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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,

View File

@ -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> {

View File

@ -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);
}
}

View File

@ -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};
}

View File

@ -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,

View File

@ -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 }
}
}

View File

@ -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]

View File

@ -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>;

View File

@ -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

View File

@ -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 {

View File

@ -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)
}

View File

@ -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> {

View File

@ -95,7 +95,9 @@ impl Hasher<sip::SipState> for RandomSipHasher {
}
}
#[stable]
impl Default for RandomSipHasher {
#[stable]
#[inline]
fn default() -> RandomSipHasher {
RandomSipHasher::new()

View File

@ -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>,
}

View File

@ -1911,7 +1911,9 @@ bitflags! {
}
#[stable]
impl Default for FilePermission {
#[stable]
#[inline]
fn default() -> FilePermission { FilePermission::empty() }
}

View File

@ -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();

View File

@ -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()

View File

@ -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

View File

@ -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;

View File

@ -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() {

View File

@ -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)]

View File

@ -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>>),

View File

@ -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.

View File

@ -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),

View File

@ -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)))

View File

@ -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