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

This commit is contained in:
bors 2014-12-30 08:02:39 +00:00
commit d2368c3c11
210 changed files with 2805 additions and 1625 deletions

View File

@ -99,7 +99,7 @@
# This is hardly all there is to know of The Rust Build System's
# mysteries. The tale continues on the wiki[1][2].
#
# [1]: https://github.com/rust-lang/rust/wiki/Note-build-system
# [1]: https://github.com/rust-lang/rust/wiki/Note-getting-started-developing-Rust
# [2]: https://github.com/rust-lang/rust/wiki/Note-testsuite
#
# If you really feel like getting your hands dirty, then:

View File

@ -23,6 +23,8 @@
# * dist-docs - Stage docs for upload
PKG_NAME := $(CFG_PACKAGE_NAME)
DOC_PKG_NAME := rust-docs-$(CFG_PACKAGE_VERS)
MINGW_PKG_NAME := rust-mingw-$(CFG_PACKAGE_VERS)
# License suitable for displaying in a popup
LICENSE.txt: $(S)COPYRIGHT $(S)LICENSE-APACHE $(S)LICENSE-MIT
@ -229,10 +231,20 @@ dist-install-dir-$(1): prepare-base-dir-$(1) docs compiler-docs
$$(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)[ ! -d doc ] || cp -r doc $$(PREPARE_DEST_DIR)
$$(Q)mkdir -p $$(PREPARE_DEST_DIR)/share/doc/rust
$$(Q)$$(PREPARE_MAN_CMD) $$(S)COPYRIGHT $$(PREPARE_DEST_DIR)/share/doc/rust
$$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-APACHE $$(PREPARE_DEST_DIR)/share/doc/rust
$$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-MIT $$(PREPARE_DEST_DIR)/share/doc/rust
$$(Q)$$(PREPARE_MAN_CMD) $$(S)README.md $$(PREPARE_DEST_DIR)/share/doc/rust
dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1)
@$(call E, build: $$@)
# Copy essential gcc components into installer
ifdef CFG_WINDOWSY_$(1)
$$(Q)rm -Rf dist/win-rust-gcc-$(1)
$$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py tmp/dist/$$(PKG_NAME)-$(1)-image dist/win-rust-gcc-$(1) $(1)
$$(Q)cp -r $$(S)src/etc/third-party tmp/dist/$$(PKG_NAME)-$(1)-image/share/doc/
endif
$$(Q)$$(S)src/rust-installer/gen-installer.sh \
--product-name=Rust \
--verify-bin=rustc \
@ -242,9 +254,50 @@ dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1)
--work-dir=tmp/dist \
--output-dir=dist \
--non-installed-prefixes=$$(NON_INSTALLED_PREFIXES) \
--package-name=$$(PKG_NAME)-$(1)
--package-name=$$(PKG_NAME)-$(1) \
--component-name=rustc \
--legacy-manifest-dirs=rustlib,cargo
$$(Q)rm -R tmp/dist/$$(PKG_NAME)-$(1)-image
dist-doc-install-dir-$(1): docs compiler-docs
$$(Q)mkdir -p tmp/dist/$$(DOC_PKG_NAME)-$(1)-image/share/doc/rust
$$(Q)cp -r doc tmp/dist/$$(DOC_PKG_NAME)-$(1)-image/share/doc/rust/html
dist/$$(DOC_PKG_NAME)-$(1).tar.gz: dist-doc-install-dir-$(1)
@$(call E, build: $$@)
$$(Q)$$(S)src/rust-installer/gen-installer.sh \
--product-name=Rust-Documentation \
--rel-manifest-dir=rustlib \
--success-message=Rust-documentation-is-installed. \
--image-dir=tmp/dist/$$(DOC_PKG_NAME)-$(1)-image \
--work-dir=tmp/dist \
--output-dir=dist \
--package-name=$$(DOC_PKG_NAME)-$(1) \
--component-name=rust-docs \
--legacy-manifest-dirs=rustlib,cargo \
--bulk-dirs=share/doc/rust/html
$$(Q)rm -R tmp/dist/$$(DOC_PKG_NAME)-$(1)-image
dist-mingw-install-dir-$(1):
$$(Q)mkdir -p tmp/dist/rust-mingw-tmp-$(1)-image
$$(Q)rm -Rf tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image
$$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py \
tmp/dist/rust-mingw-tmp-$(1)-image tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image $(1)
dist/$$(MINGW_PKG_NAME)-$(1).tar.gz: dist-mingw-install-dir-$(1)
@$(call E, build: $$@)
$$(Q)$$(S)src/rust-installer/gen-installer.sh \
--product-name=Rust-MinGW \
--rel-manifest-dir=rustlib \
--success-message=Rust-MinGW-is-installed. \
--image-dir=tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image \
--work-dir=tmp/dist \
--output-dir=dist \
--package-name=$$(MINGW_PKG_NAME)-$(1) \
--component-name=rust-mingw \
--legacy-manifest-dirs=rustlib,cargo
$$(Q)rm -R tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image
endef
ifneq ($(CFG_ENABLE_DIST_HOST_ONLY),)
@ -257,7 +310,16 @@ endif
dist-install-dirs: $(foreach host,$(CFG_HOST),dist-install-dir-$(host))
dist-tar-bins: $(foreach host,$(CFG_HOST),dist/$(PKG_NAME)-$(host).tar.gz)
ifdef CFG_WINDOWSY_$(CFG_BUILD)
MAYBE_MINGW_TARBALLS=$(foreach host,$(CFG_HOST),dist/$(MINGW_PKG_NAME)-$(host).tar.gz)
endif
ifeq ($(CFG_DISABLE_DOCS),)
MAYBE_DOC_TARBALLS=$(foreach host,$(CFG_HOST),dist/$(DOC_PKG_NAME)-$(host).tar.gz)
endif
dist-tar-bins: $(foreach host,$(CFG_HOST),dist/$(PKG_NAME)-$(host).tar.gz) \
$(MAYBE_DOC_TARBALLS) $(MAYBE_MINGW_TARBALLS)
# Just try to run the compiler for the build host
distcheck-tar-bins: dist-tar-bins
@ -289,27 +351,20 @@ distcheck-docs: dist-docs
# Primary targets (dist, distcheck)
######################################################################
ifdef CFG_WINDOWSY_$(CFG_BUILD)
dist: dist-win dist-tar-bins
distcheck: distcheck-win
$(Q)rm -Rf tmp/distcheck
@echo
@echo -----------------------------------------------
@echo "Rust ready for distribution (see ./dist)"
@echo -----------------------------------------------
else
MAYBE_DIST_TAR_SRC=dist-tar-src
MAYBE_DISTCHECK_TAR_SRC=distcheck-tar-src
# FIXME #13224: On OS X don't produce tarballs simply because --exclude-vcs don't work.
# This is a huge hack because I just don't have time to figure out another solution.
ifeq ($(CFG_OSTYPE), apple-darwin)
MAYBE_DIST_TAR_SRC=
MAYBE_DISTCHECK_TAR_SRC=
else
MAYBE_DIST_TAR_SRC=dist-tar-src
MAYBE_DISTCHECK_TAR_SRC=distcheck-tar-src
endif
# Don't bother with source tarballs on windows just because we historically haven't.
ifeq ($(CFG_OSTYPE), pc-windows-gnu)
MAYBE_DIST_TAR_SRC=
MAYBE_DISTCHECK_TAR_SRC=
endif
ifneq ($(CFG_DISABLE_DOCS),)
@ -320,15 +375,13 @@ MAYBE_DIST_DOCS=dist-docs
MAYBE_DISTCHECK_DOCS=distcheck-docs
endif
dist: $(MAYBE_DIST_TAR_SRC) dist-osx dist-tar-bins $(MAYBE_DIST_DOCS)
dist: $(MAYBE_DIST_TAR_SRC) dist-osx dist-win dist-tar-bins $(MAYBE_DIST_DOCS)
distcheck: $(MAYBE_DISTCHECK_TAR_SRC) distcheck-osx distcheck-tar-bins $(MAYBE_DISTCHECK_DOCS)
distcheck: $(MAYBE_DISTCHECK_TAR_SRC) distcheck-osx distcheck-win distcheck-tar-bins $(MAYBE_DISTCHECK_DOCS)
$(Q)rm -Rf tmp/distcheck
@echo
@echo -----------------------------------------------
@echo "Rust ready for distribution (see ./dist)"
@echo -----------------------------------------------
endif
.PHONY: dist distcheck

View File

@ -31,7 +31,7 @@ $(BG):
$(Q)mkdir -p $(BG)
$(BG)RustLexer.class: $(BG) $(SG)RustLexer.g4
$(Q)$(CFG_ANTLR4) -o $(B)grammar $(SG)RustLexer.g4
$(Q)$(CFG_ANTLR4) -o $(BG) $(SG)RustLexer.g4
$(Q)$(CFG_JAVAC) -d $(BG) $(BG)RustLexer.java
check-build-lexer-verifier: $(BG)verify

View File

@ -20,6 +20,9 @@ ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
$(Q)sudo -u "$$SUDO_USER" $(MAKE) prepare_install
else
$(Q)$(MAKE) prepare_install
endif
ifeq ($(CFG_DISABLE_DOCS),)
$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(DOC_PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)" "$(MAYBE_DISABLE_VERIFY)"
endif
$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)" "$(MAYBE_DISABLE_VERIFY)"
# Remove tmp files because it's a decent amount of disk space
@ -33,6 +36,9 @@ ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
$(Q)sudo -u "$$SUDO_USER" $(MAKE) prepare_uninstall
else
$(Q)$(MAKE) prepare_uninstall
endif
ifeq ($(CFG_DISABLE_DOCS),)
$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(DOC_PKG_NAME)-$(CFG_BUILD)/install.sh --uninstall --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
endif
$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(PKG_NAME)-$(CFG_BUILD)/install.sh --uninstall --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
# Remove tmp files because it's a decent amount of disk space

View File

@ -74,14 +74,6 @@ endif
TEST_LOG_FILE=tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).log
TEST_OK_FILE=tmp/check-stage$(1)-T-$(2)-H-$(3)-$(4).ok
# If we're sharding the testsuite between parallel testers,
# pass this argument along to the compiletest and crate test
# invocations.
ifdef TEST_SHARD
CTEST_TESTARGS += --test-shard=$(TEST_SHARD)
CRATE_TEST_EXTRA_ARGS += --test-shard=$(TEST_SHARD)
endif
define DEF_TARGET_COMMANDS
ifdef CFG_UNIXY_$(1)
@ -297,6 +289,7 @@ tidy:
| grep '^$(S)src/doc' -v \
| grep '^$(S)src/compiler-rt' -v \
| grep '^$(S)src/libbacktrace' -v \
| grep '^$(S)src/rust-installer' -v \
| xargs $(CFG_PYTHON) $(S)src/etc/check-binaries.py
endif

View File

@ -1,6 +1,6 @@
% The Rust Tasks and Communication Guide
% The Rust Threads and Communication Guide
**NOTE** This guide is badly out of date an needs to be rewritten.
**NOTE** This guide is badly out of date and needs to be rewritten.
# Introduction
@ -9,36 +9,36 @@ primitives. This guide will describe the concurrency model in Rust, how it
relates to the Rust type system, and introduce the fundamental library
abstractions for constructing concurrent programs.
Tasks provide failure isolation and recovery. When a fatal error occurs in Rust
Threads provide failure isolation and recovery. When a fatal error occurs in Rust
code as a result of an explicit call to `panic!()`, an assertion failure, or
another invalid operation, the runtime system destroys the entire task. Unlike
another invalid operation, the runtime system destroys the entire thread. Unlike
in languages such as Java and C++, there is no way to `catch` an exception.
Instead, tasks may monitor each other to see if they panic.
Instead, threads may monitor each other to see if they panic.
Tasks use Rust's type system to provide strong memory safety guarantees. In
particular, the type system guarantees that tasks cannot induce a data race
Threads use Rust's type system to provide strong memory safety guarantees. In
particular, the type system guarantees that threads cannot induce a data race
from shared mutable state.
# Basics
At its simplest, creating a task is a matter of calling the `spawn` function
with a closure argument. `spawn` executes the closure in the new task.
At its simplest, creating a thread is a matter of calling the `spawn` function
with a closure argument. `spawn` executes the closure in the new thread.
```{rust,ignore}
# use std::task::spawn;
# use std::thread::spawn;
// Print something profound in a different task using a named function
fn print_message() { println!("I am running in a different task!"); }
// Print something profound in a different thread using a named function
fn print_message() { println!("I am running in a different thread!"); }
spawn(print_message);
// Alternatively, use a `move ||` expression instead of a named function.
// `||` expressions evaluate to an unnamed closure. The `move` keyword
// indicates that the closure should take ownership of any variables it
// touches.
spawn(move || println!("I am also running in a different task!"));
spawn(move || println!("I am also running in a different thread!"));
```
In Rust, a task is not a concept that appears in the language semantics.
In Rust, a thread is not a concept that appears in the language semantics.
Instead, Rust's type system provides all the tools necessary to implement safe
concurrency: particularly, ownership. The language leaves the implementation
details to the standard library.
@ -49,26 +49,26 @@ argument a closure (of type `F`) that it will run exactly once. This
closure is limited to capturing `Send`-able data from its environment
(that is, data which is deeply owned). Limiting the closure to `Send`
ensures that `spawn` can safely move the entire closure and all its
associated state into an entirely different task for execution.
associated state into an entirely different thread for execution.
```{rust,ignore}
# use std::task::spawn;
# fn generate_task_number() -> int { 0 }
# use std::thread::spawn;
# fn generate_thread_number() -> int { 0 }
// Generate some state locally
let child_task_number = generate_task_number();
let child_thread_number = generate_thread_number();
spawn(move || {
// Capture it in the remote task. The `move` keyword indicates
// that this closure should move `child_task_number` into its
// Capture it in the remote thread. The `move` keyword indicates
// that this closure should move `child_thread_number` into its
// environment, rather than capturing a reference into the
// enclosing stack frame.
println!("I am child number {}", child_task_number);
println!("I am child number {}", child_thread_number);
});
```
## Communication
Now that we have spawned a new task, it would be nice if we could communicate
Now that we have spawned a new thread, it would be nice if we could communicate
with it. For this, we use *channels*. A channel is simply a pair of endpoints:
one for sending messages and another for receiving messages.
@ -78,7 +78,7 @@ of a channel, and a **receiver** is the receiving endpoint. Consider the followi
example of calculating two results concurrently:
```{rust,ignore}
# use std::task::spawn;
# use std::thread::spawn;
let (tx, rx): (Sender<int>, Receiver<int>) = channel();
@ -102,12 +102,12 @@ into its component parts).
let (tx, rx): (Sender<int>, Receiver<int>) = channel();
```
The child task will use the sender to send data to the parent task, which will
The child thread will use the sender to send data to the parent thread, which will
wait to receive the data on the receiver. The next statement spawns the child
task.
thread.
```{rust,ignore}
# use std::task::spawn;
# use std::thread::spawn;
# fn some_expensive_computation() -> int { 42 }
# let (tx, rx) = channel();
spawn(move || {
@ -116,10 +116,10 @@ spawn(move || {
});
```
Notice that the creation of the task closure transfers `tx` to the child task
Notice that the creation of the thread closure transfers `tx` to the child thread
implicitly: the closure captures `tx` in its environment. Both `Sender` and
`Receiver` are sendable types and may be captured into tasks or otherwise
transferred between them. In the example, the child task runs an expensive
`Receiver` are sendable types and may be captured into threads or otherwise
transferred between them. In the example, the child thread runs an expensive
computation, then sends the result over the captured channel.
Finally, the parent continues with some other expensive computation, then waits
@ -137,7 +137,7 @@ The `Sender` and `Receiver` pair created by `channel` enables efficient
communication between a single sender and a single receiver, but multiple
senders cannot use a single `Sender` value, and multiple receivers cannot use a
single `Receiver` value. What if our example needed to compute multiple
results across a number of tasks? The following program is ill-typed:
results across a number of threads? The following program is ill-typed:
```{rust,ignore}
# fn some_expensive_computation() -> int { 42 }
@ -160,7 +160,7 @@ Instead we can clone the `tx`, which allows for multiple senders.
let (tx, rx) = channel();
for init_val in range(0u, 3) {
// Create a new channel handle to distribute to the child task
// Create a new channel handle to distribute to the child thread
let child_tx = tx.clone();
spawn(move || {
child_tx.send(some_expensive_computation(init_val));
@ -172,7 +172,7 @@ let result = rx.recv() + rx.recv() + rx.recv();
```
Cloning a `Sender` produces a new handle to the same channel, allowing multiple
tasks to send data to a single receiver. It upgrades the channel internally in
threads to send data to a single receiver. It upgrades the channel internally in
order to allow this functionality, which means that channels that are not
cloned can avoid the overhead required to handle multiple senders. But this
fact has no bearing on the channel's usage: the upgrade is transparent.
@ -182,9 +182,9 @@ simply use three `Sender` pairs, but it serves to illustrate the point. For
reference, written with multiple streams, it might look like the example below.
```{rust,ignore}
# use std::task::spawn;
# use std::thread::spawn;
// Create a vector of ports, one for each child task
// Create a vector of ports, one for each child thread
let rxs = Vec::from_fn(3, |init_val| {
let (tx, rx) = channel();
spawn(move || {
@ -256,18 +256,18 @@ fn main() {
## Sharing without copying: Arc
To share data between tasks, a first approach would be to only use channel as
To share data between threads, a first approach would be to only use channel as
we have seen previously. A copy of the data to share would then be made for
each task. In some cases, this would add up to a significant amount of wasted
each thread. In some cases, this would add up to a significant amount of wasted
memory and would require copying the same data more than necessary.
To tackle this issue, one can use an Atomically Reference Counted wrapper
(`Arc`) as implemented in the `sync` library of Rust. With an Arc, the data
will no longer be copied for each task. The Arc acts as a reference to the
will no longer be copied for each thread. The Arc acts as a reference to the
shared data and only this reference is shared and cloned.
Here is a small example showing how to use Arcs. We wish to run concurrently
several computations on a single large vector of floats. Each task needs the
several computations on a single large vector of floats. Each thread needs the
full vector to perform its duty.
```{rust,ignore}
@ -284,10 +284,10 @@ fn main() {
let numbers_arc = Arc::new(numbers);
for num in range(1u, 10) {
let task_numbers = numbers_arc.clone();
let thread_numbers = numbers_arc.clone();
spawn(move || {
println!("{}-norm = {}", num, pnorm(task_numbers.as_slice(), num));
println!("{}-norm = {}", num, pnorm(thread_numbers.as_slice(), num));
});
}
}
@ -306,8 +306,8 @@ let numbers_arc = Arc::new(numbers);
# }
```
and a clone is captured for each task via a procedure. This only copies
the wrapper and not its contents. Within the task's procedure, the captured
and a clone is captured for each thread via a procedure. This only copies
the wrapper and not its contents. Within the thread's procedure, the captured
Arc reference can be used as a shared reference to the underlying vector as
if it were local.
@ -319,29 +319,29 @@ if it were local.
# let numbers=Vec::from_fn(1000000, |_| rand::random::<f64>());
# let numbers_arc = Arc::new(numbers);
# let num = 4;
let task_numbers = numbers_arc.clone();
let thread_numbers = numbers_arc.clone();
spawn(move || {
// Capture task_numbers and use it as if it was the underlying vector
println!("{}-norm = {}", num, pnorm(task_numbers.as_slice(), num));
// Capture thread_numbers and use it as if it was the underlying vector
println!("{}-norm = {}", num, pnorm(thread_numbers.as_slice(), num));
});
# }
```
# Handling task panics
# Handling thread panics
Rust has a built-in mechanism for raising exceptions. The `panic!()` macro
(which can also be written with an error string as an argument: `panic!(
~reason)`) and the `assert!` construct (which effectively calls `panic!()` if a
boolean expression is false) are both ways to raise exceptions. When a task
raises an exception, the task unwinds its stack—running destructors and
boolean expression is false) are both ways to raise exceptions. When a thread
raises an exception, the thread unwinds its stack—running destructors and
freeing memory along the way—and then exits. Unlike exceptions in C++,
exceptions in Rust are unrecoverable within a single task: once a task panics,
exceptions in Rust are unrecoverable within a single thread: once a thread panics,
there is no way to "catch" the exception.
While it isn't possible for a task to recover from panicking, tasks may notify
While it isn't possible for a thread to recover from panicking, threads may notify
each other if they panic. The simplest way of handling a panic is with the
`try` function, which is similar to `spawn`, but immediately blocks and waits
for the child task to finish. `try` returns a value of type
for the child thread to finish. `try` returns a value of type
`Result<T, Box<Any + Send>>`. `Result` is an `enum` type with two variants:
`Ok` and `Err`. In this case, because the type arguments to `Result` are `int`
and `()`, callers can pattern-match on a result to check whether it's an `Ok`
@ -364,14 +364,14 @@ assert!(result.is_err());
Unlike `spawn`, the function spawned using `try` may return a value, which
`try` will dutifully propagate back to the caller in a [`Result`] enum. If the
child task terminates successfully, `try` will return an `Ok` result; if the
child task panics, `try` will return an `Error` result.
child thread terminates successfully, `try` will return an `Ok` result; if the
child thread panics, `try` will return an `Error` result.
[`Result`]: std/result/index.html
> *Note:* A panicked task does not currently produce a useful error
> *Note:* A panicked thread does not currently produce a useful error
> value (`try` always returns `Err(())`). In the
> future, it may be possible for tasks to intercept the value passed to
> future, it may be possible for threads to intercept the value passed to
> `panic!()`.
But not all panics are created equal. In some cases you might need to abort
@ -379,4 +379,4 @@ the entire program (perhaps you're writing an assert which, if it trips,
indicates an unrecoverable logic error); in other cases you might want to
contain the panic at a certain boundary (perhaps a small piece of input from
the outside world, which you happen to be processing in parallel, is malformed
such that the processing task cannot proceed).
such that the processing thread cannot proceed).

View File

@ -23,11 +23,16 @@ Linux or a Mac, all you need to do is this (note that you don't need to type
in the `$`s, they just indicate the start of each command):
```bash
$ curl -s https://static.rust-lang.org/rustup.sh | sudo sh
curl -L https://static.rust-lang.org/rustup.sh | sudo sh
```
(If you're concerned about `curl | sudo sh`, please keep reading. Disclaimer
below.)
If you're concerned about the [potential insecurity](http://curlpipesh.tumblr.com/) of using `curl | sudo sh`,
please keep reading and see our disclaimer below. And feel free to use a two-step version of the installation and examine our installation script:
```bash
curl -L https://static.rust-lang.org/rustup.sh -O
sudo sh rustup.sh
```
If you're on Windows, please download either the [32-bit
installer](https://static.rust-lang.org/dist/rust-nightly-i686-pc-windows-gnu.exe)
@ -482,7 +487,7 @@ src/main.rs:2 let x;
Giving it a type will compile, though:
```{ignore}
```{rust}
let x: int;
```
@ -1044,7 +1049,9 @@ struct Point(int, int, int);
These two will not be equal, even if they have the same values:
```{rust,ignore}
```{rust}
# struct Color(int, int, int);
# struct Point(int, int, int);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
```
@ -1604,10 +1611,6 @@ 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`:
@ -1895,7 +1898,7 @@ authors = ["Your Name <you@example.com>"]
Cargo gets this information from your environment. If it's not correct, go ahead
and fix that.
Finally, Cargo generated a hello, world for us. Check out `src/main.rs`:
Finally, Cargo generated a "Hello, world!" for us. Check out `src/main.rs`:
```{rust}
fn main() {
@ -3036,7 +3039,7 @@ test foo ... FAILED
failures:
---- foo stdout ----
task 'foo' failed at 'assertion failed: false', /home/you/projects/testing/tests/lib.rs:3
thread 'foo' failed at 'assertion failed: false', /home/you/projects/testing/tests/lib.rs:3
@ -3045,7 +3048,7 @@ failures:
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
task '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:243
thread '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:243
```
Lots of output! Let's break this down:
@ -3088,7 +3091,7 @@ failed, especially as we accumulate more tests.
failures:
---- foo stdout ----
task 'foo' failed at 'assertion failed: false', /home/you/projects/testing/tests/lib.rs:3
thread 'foo' failed at 'assertion failed: false', /home/you/projects/testing/tests/lib.rs:3
@ -3097,7 +3100,7 @@ failures:
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
task '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:243
thread '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:243
```
After all the tests run, Rust will show us any output from our failed tests.
@ -4263,7 +4266,7 @@ is that a moving closure always takes ownership of all variables that
it uses. Ordinary closures, in contrast, just create a reference into
the enclosing stack frame. Moving closures are most useful with Rust's
concurrency features, and so we'll just leave it at this for
now. We'll talk about them more in the "Tasks" section of the guide.
now. We'll talk about them more in the "Threads" section of the guide.
## Accepting closures as arguments
@ -4290,7 +4293,9 @@ let square = |x: int| { x * x };
We've seen this before. We make a closure that takes an integer, and returns
its square.
```{rust,ignore}
```{rust}
# fn twice(x: int, f: |int| -> int) -> int { f(x) + f(x) }
# let square = |x: int| { x * x };
twice(5i, square); // evaluates to 50
```
@ -5213,9 +5218,7 @@ as you can see, there's no overhead of deciding which version to call here,
hence 'statically dispatched'. The downside is that we have two copies of
the same function, so our binary is a little bit larger.
# Tasks
**NOTE**: this section is currently out of date and will be rewritten soon.
# Threads
Concurrency and parallelism are topics that are of increasing interest to a
broad subsection of software developers. Modern computers are often multi-core,
@ -5224,24 +5227,22 @@ processor. Rust's semantics lend themselves very nicely to solving a number of
issues that programmers have with concurrency. Many concurrency errors that are
runtime errors in other languages are compile-time errors in Rust.
Rust's concurrency primitive is called a **task**. Tasks are similar to
threads, and do not share memory in an unsafe manner, preferring message
passing to communicate. It's worth noting that tasks are implemented as a
library, and not part of the language. This means that in the future, other
concurrency libraries can be written for Rust to help in specific scenarios.
Here's an example of creating a task:
Rust's concurrency primitive is called a **thread**. It's worth noting that
threads are implemented as a library, and not part of the language. This means
that in the future, other concurrency libraries can be written for Rust to help
in specific scenarios. Here's an example of creating a thread:
```{rust,ignore}
spawn(move || {
println!("Hello from a task!");
println!("Hello from a thread!");
});
```
The `spawn` function takes a closure as an argument, and runs that
closure in a new task. Typically, you will want to use a moving
closure in a new thread. Typically, you will want to use a moving
closure, so that the closure takes ownership of any variables that it
touches. This implies that those variables are not usable from the
parent task after the child task is spawned:
parent thread after the child thread is spawned:
```{rust,ignore}
let mut x = vec![1i, 2i, 3i];
@ -5257,15 +5258,15 @@ println!("The value of x[0] is: {}", x[0]); // error: use of moved value: `x`
other languages would let us do this, but it's not safe to do
so. Rust's borrow checker catches the error.
If tasks were only able to capture these values, they wouldn't be very useful.
Luckily, tasks can communicate with each other through **channel**s. Channels
If threads were only able to capture these values, they wouldn't be very useful.
Luckily, threads can communicate with each other through **channel**s. Channels
work like this:
```{rust,ignore}
let (tx, rx) = channel();
spawn(move || {
tx.send("Hello from a task!".to_string());
tx.send("Hello from a thread!".to_string());
});
let message = rx.recv();
@ -5278,14 +5279,14 @@ receive the message on the `Receiver<T>` side with the `recv()` method. This
method blocks until it gets a message. There's a similar method, `.try_recv()`,
which returns an `Result<T, TryRecvError>` and does not block.
If you want to send messages to the task as well, create two channels!
If you want to send messages to the thread as well, create two channels!
```{rust,ignore}
let (tx1, rx1) = channel();
let (tx2, rx2) = channel();
spawn(move || {
tx1.send("Hello from a task!".to_string());
tx1.send("Hello from a thread!".to_string());
let message = rx2.recv();
println!("{}", message);
});
@ -5296,9 +5297,9 @@ println!("{}", message);
tx2.send("Goodbye from main!".to_string());
```
The closure has one sending end and one receiving end, and the main
task has one of each as well. Now they can talk back and forth in
whatever way they wish.
The closure has one sending end and one receiving end, and the main thread has
one of each as well. Now they can talk back and forth in whatever way they
wish.
Notice as well that because `Sender` and `Receiver` are generic, while you can
pass any kind of information through the channel, the ends are strongly typed.
@ -5337,7 +5338,7 @@ we'll just get the value immediately.
## Success and failure
Tasks don't always succeed, they can also panic. A task that wishes to panic
Threads don't always succeed, they can also panic. A thread that wishes to panic
can call the `panic!` macro, passing a message:
```{rust,ignore}
@ -5346,14 +5347,14 @@ spawn(move || {
});
```
If a task panics, it is not possible for it to recover. However, it can
notify other tasks that it has panicked. We can do this with `task::try`:
If a thread panics, it is not possible for it to recover. However, it can
notify other thread that it has panicked. We can do this with `thread::try`:
```{rust,ignore}
use std::task;
use std::thread;
use std::rand;
let result = task::try(move || {
let result = thread::try(move || {
if rand::random() {
println!("OK");
} else {
@ -5362,7 +5363,7 @@ let result = task::try(move || {
});
```
This task will randomly panic or succeed. `task::try` returns a `Result`
This thread will randomly panic or succeed. `thread::try` returns a `Result`
type, so we can handle the response like any other computation that may
fail.
@ -5410,7 +5411,7 @@ fn main() {
}
```
You can have the macros expanded like this: `rustc print.rs --pretty=expanded`, which will
You can have the macros expanded like this: `rustc --pretty=expanded print.rs`, which will
give us this huge result:
```{rust,ignore}

View File

@ -58,7 +58,7 @@ a guide that can help you out:
* [Strings](guide-strings.html)
* [Pointers](guide-pointers.html)
* [Crates and modules](guide-crates.html)
* [Tasks and Communication](guide-tasks.html)
* [Threads and Communication](guide-threads.html)
* [Error Handling](guide-error-handling.html)
* [Foreign Function Interface](guide-ffi.html)
* [Writing Unsafe and Low-Level Code](guide-unsafe.html)

View File

@ -483,7 +483,7 @@ fn main() {
for i in range(0u, 3u) {
let number = numbers.clone();
Thread::spawn(move || {
let mut array = number.lock();
let mut array = number.lock().unwrap();
(*array)[i] += 1;

View File

@ -194,11 +194,11 @@ grammar as double-quoted strings. Other tokens have exact rules given.
| else | enum | extern | false | final |
| fn | for | if | impl | in |
| let | loop | match | mod | move |
| mut | offsetof | once | override | priv |
| pub | pure | ref | return | sizeof |
| static | self | struct | super | true |
| trait | type | typeof | unsafe | unsized |
| use | virtual | where | while | yield |
| mut | offsetof | override | priv | pub |
| pure | ref | return | sizeof | static |
| self | struct | super | true | trait |
| type | typeof | unsafe | unsized | use |
| virtual | where | while | yield |
Each of these keywords has special meaning in its grammar, and all of them are
@ -899,8 +899,8 @@ mirrors the module hierarchy.
// Load the `vec` module from `vec.rs`
mod vec;
mod task {
// Load the `local_data` module from `task/local_data.rs`
mod thread {
// Load the `local_data` module from `thread/local_data.rs`
mod local_data;
}
```
@ -909,9 +909,9 @@ The directories and files used for loading external file modules can be
influenced with the `path` attribute.
```{.ignore}
#[path = "task_files"]
mod task {
// Load the `local_data` module from `task_files/tls.rs`
#[path = "thread_files"]
mod thread {
// Load the `local_data` module from `thread_files/tls.rs`
#[path = "tls.rs"]
mod local_data;
}
@ -1188,7 +1188,7 @@ code safe, in the surrounding context.
Unsafe blocks are used to wrap foreign libraries, make direct use of hardware
or implement features not directly present in the language. For example, Rust
provides the language features necessary to implement memory-safe concurrency
in the language but the implementation of tasks and message passing is in the
in the language but the implementation of threads and message passing is in the
standard library.
Rust's type system is a conservative approximation of the dynamic safety
@ -1500,7 +1500,7 @@ be modified by the program. One of Rust's goals is to make concurrency bugs
hard to run into, and this is obviously a very large source of race conditions
or other bugs. For this reason, an `unsafe` block is required when either
reading or writing a mutable static variable. Care should be taken to ensure
that modifications to a mutable static are safe with respect to other tasks
that modifications to a mutable static are safe with respect to other threads
running in the same process.
Mutable statics are still very useful, however. They can be used with C
@ -2253,11 +2253,11 @@ A complete list of the built-in language items follows:
* `drop`
: Have destructors.
* `send`
: Able to be sent across task boundaries.
: Able to be sent across thread boundaries.
* `sized`
: Has a size known at compile time.
* `sync`
: Able to be safely shared between tasks when aliased.
: Able to be safely shared between threads when aliased.
#### Operators
@ -2621,7 +2621,7 @@ The currently implemented features of the reference compiler are:
LLVM's implementation which works in concert with the kernel
loader and dynamic linker. This is not necessarily available
on all platforms, and usage of it is discouraged (rust
focuses more on task-local data instead of thread-local
focuses more on thread-local data instead of thread-local
data).
* `trace_macros` - Allows use of the `trace_macros` macro, which is a nasty
@ -2939,7 +2939,7 @@ array is mutable, the resulting [lvalue](#lvalues,-rvalues-and-temporaries) can
be assigned to.
Indices are zero-based, and may be of any integral type. Vector access is
bounds-checked at run-time. When the check fails, it will put the task in a
bounds-checked at run-time. When the check fails, it will put the thread in a
_panicked state_.
```{should-fail}
@ -3950,7 +3950,7 @@ Types in Rust are categorized into kinds, based on various properties of the
components of the type. The kinds are:
* `Send`
: Types of this kind can be safely sent between tasks.
: Types of this kind can be safely sent between threads.
This kind includes scalars, boxes, procs, and
structural types containing only other owned types.
All `Send` types are `'static`.
@ -3998,21 +3998,21 @@ to sendable.
# Memory and concurrency models
Rust has a memory model centered around concurrently-executing _tasks_. Thus
Rust has a memory model centered around concurrently-executing _threads_. Thus
its memory model and its concurrency model are best discussed simultaneously,
as parts of each only make sense when considered from the perspective of the
other.
When reading about the memory model, keep in mind that it is partitioned in
order to support tasks; and when reading about tasks, keep in mind that their
order to support threads; and when reading about threads, keep in mind that their
isolation and communication mechanisms are only possible due to the ownership
and lifetime semantics of the memory model.
## Memory model
A Rust program's memory consists of a static set of *items*, a set of
[tasks](#tasks) each with its own *stack*, and a *heap*. Immutable portions of
the heap may be shared between tasks, mutable portions may not.
[threads](#threads) each with its own *stack*, and a *heap*. Immutable portions of
the heap may be shared between threads, mutable portions may not.
Allocations in the stack consist of *slots*, and allocations in the heap
consist of *boxes*.
@ -4023,8 +4023,8 @@ The _items_ of a program are those functions, modules and types that have their
value calculated at compile-time and stored uniquely in the memory image of the
rust process. Items are neither dynamically allocated nor freed.
A task's _stack_ consists of activation frames automatically allocated on entry
to each function as the task executes. A stack allocation is reclaimed when
A thread's _stack_ consists of activation frames automatically allocated on entry
to each function as the thread executes. A stack allocation is reclaimed when
control leaves the frame containing it.
The _heap_ is a general term that describes boxes. The lifetime of an
@ -4034,10 +4034,10 @@ in the heap, heap allocations may outlive the frame they are allocated within.
### Memory ownership
A task owns all memory it can *safely* reach through local variables, as well
A thread owns all memory it can *safely* reach through local variables, as well
as boxes and references.
When a task sends a value that has the `Send` trait to another task, it loses
When a thread sends a value that has the `Send` trait to another thread, it loses
ownership of the value sent and can no longer refer to it. This is statically
guaranteed by the combined use of "move semantics", and the compiler-checked
_meaning_ of the `Send` trait: it is only instantiated for (transitively)
@ -4046,12 +4046,12 @@ sendable kinds of data constructor and pointers, never including references.
When a stack frame is exited, its local allocations are all released, and its
references to boxes are dropped.
When a task finishes, its stack is necessarily empty and it therefore has no
When a thread finishes, its stack is necessarily empty and it therefore has no
references to any boxes; the remainder of its heap is immediately freed.
### Memory slots
A task's stack contains slots.
A thread's stack contains slots.
A _slot_ is a component of a stack frame, either a function parameter, a
[temporary](#lvalues,-rvalues-and-temporaries), or a local variable.
@ -4105,72 +4105,69 @@ let y = x;
// attempting to use `x` will result in an error here
```
## Tasks
## Threads
An executing Rust program consists of a tree of tasks. A Rust _task_ consists
of an entry function, a stack, a set of outgoing communication channels and
incoming communication ports, and ownership of some portion of the heap of a
single operating-system process.
Rust's primary concurrency mechanism is called a **thread**.
### Communication between tasks
### Communication between threads
Rust tasks are isolated and generally unable to interfere with one another's
Rust threads are isolated and generally unable to interfere with one another's
memory directly, except through [`unsafe` code](#unsafe-functions). All
contact between tasks is mediated by safe forms of ownership transfer, and data
contact between threads is mediated by safe forms of ownership transfer, and data
races on memory are prohibited by the type system.
When you wish to send data between tasks, the values are restricted to the
When you wish to send data between threads, the values are restricted to the
[`Send` type-kind](#type-kinds). Restricting communication interfaces to this
kind ensures that no references move between tasks. Thus access to an entire
kind ensures that no references move between threads. Thus access to an entire
data structure can be mediated through its owning "root" value; no further
locking or copying is required to avoid data races within the substructure of
such a value.
### Task lifecycle
### Thread
The _lifecycle_ of a task consists of a finite set of states and events that
cause transitions between the states. The lifecycle states of a task are:
The _lifecycle_ of a threads consists of a finite set of states and events that
cause transitions between the states. The lifecycle states of a thread are:
* running
* blocked
* panicked
* dead
A task begins its lifecycle &mdash; once it has been spawned &mdash; in the
A thread begins its lifecycle &mdash; once it has been spawned &mdash; in the
*running* state. In this state it executes the statements of its entry
function, and any functions called by the entry function.
A task may transition from the *running* state to the *blocked* state any time
A thread may transition from the *running* state to the *blocked* state any time
it makes a blocking communication call. When the call can be completed &mdash;
when a message arrives at a sender, or a buffer opens to receive a message
&mdash; then the blocked task will unblock and transition back to *running*.
&mdash; then the blocked thread will unblock and transition back to *running*.
A task may transition to the *panicked* state at any time, due being killed by
A thread may transition to the *panicked* state at any time, due being killed by
some external event or internally, from the evaluation of a `panic!()` macro.
Once *panicking*, a task unwinds its stack and transitions to the *dead* state.
Unwinding the stack of a task is done by the task itself, on its own control
Once *panicking*, a thread unwinds its stack and transitions to the *dead* state.
Unwinding the stack of a thread is done by the thread itself, on its own control
stack. If a value with a destructor is freed during unwinding, the code for the
destructor is run, also on the task's control stack. Running the destructor
destructor is run, also on the thread's control stack. Running the destructor
code causes a temporary transition to a *running* state, and allows the
destructor code to cause any subsequent state transitions. The original task
destructor code to cause any subsequent state transitions. The original thread
of unwinding and panicking thereby may suspend temporarily, and may involve
(recursive) unwinding of the stack of a failed destructor. Nonetheless, the
outermost unwinding activity will continue until the stack is unwound and the
task transitions to the *dead* state. There is no way to "recover" from task
panics. Once a task has temporarily suspended its unwinding in the *panicking*
thread transitions to the *dead* state. There is no way to "recover" from thread
panics. Once a thread has temporarily suspended its unwinding in the *panicking*
state, a panic occurring from within this destructor results in *hard* panic.
A hard panic currently results in the process aborting.
A task in the *dead* state cannot transition to other states; it exists only to
have its termination status inspected by other tasks, and/or to await
A thread in the *dead* state cannot transition to other states; it exists only to
have its termination status inspected by other threads, and/or to await
reclamation when the last reference to it drops.
# Runtime services, linkage and debugging
The Rust _runtime_ is a relatively compact collection of Rust code that
provides fundamental services and datatypes to all Rust tasks at run-time. It
provides fundamental services and datatypes to all Rust threads at run-time. It
is smaller and simpler than many modern language runtimes. It is tightly
integrated into the language's execution model of memory, tasks, communication
integrated into the language's execution model of memory, threads, communication
and logging.
### Memory allocation
@ -4181,7 +4178,7 @@ environment and releases them back to its environment when they are no longer
needed. The default implementation of the service-provider interface consists
of the C runtime functions `malloc` and `free`.
The runtime memory-management system, in turn, supplies Rust tasks with
The runtime memory-management system, in turn, supplies Rust threads with
facilities for allocating releasing stacks, as well as allocating and freeing
heap data.
@ -4189,15 +4186,15 @@ heap data.
The runtime provides C and Rust code to assist with various built-in types,
such as arrays, strings, and the low level communication system (ports,
channels, tasks).
channels, threads).
Support for other built-in types such as simple types, tuples and enums is
open-coded by the Rust compiler.
### Task scheduling and communication
### Thread scheduling and communication
The runtime provides code to manage inter-task communication. This includes
the system of task-lifecycle state transitions depending on the contents of
The runtime provides code to manage inter-thread communication. This includes
the system of thread-lifecycle state transitions depending on the contents of
queues, as well as code to copy values between queues and their recipients and
to serialize values for transmission over operating-system inter-process
communication facilities.

View File

@ -245,6 +245,7 @@
<context attribute="CharEscape" lineEndContext="#pop" name="CharEscape">
<AnyChar String="nrt\&apos;&quot;" attribute="CharEscape" context="#pop"/>
<RegExpr String="x[0-9a-fA-F]{2}" attribute="CharEscape" context="#pop"/>
<RegExpr String="u\{[0-9a-fA-F]{1,6}\}" attribute="CharEscape" context="#pop"/>
<RegExpr String="u[0-9a-fA-F]{4}" attribute="CharEscape" context="#pop"/>
<RegExpr String="U[0-9a-fA-F]{8}" attribute="CharEscape" context="#pop"/>
<RegExpr String="." attribute="Error" context="#pop"/>
@ -255,7 +256,7 @@
<Detect2Chars char="*" char1="/" attribute="Comment" context="#pop" endRegion="Comment"/>
</context>
</contexts>
<itemDatas>
<itemDatas>
<itemData name="Normal Text" defStyleNum="dsNormal"/>
<itemData name="Keyword" defStyleNum="dsKeyword" color="#770088" bold="1"/>
<itemData name="Self" defStyleNum="dsKeyword" color="#FF0000" bold="1"/>

View File

@ -114,11 +114,5 @@ def make_win_dist(rust_root, gcc_root, target_triple):
for src in target_libs:
shutil.copy(src, target_lib_dir)
# Copy license files
lic_dir = os.path.join(rust_root, "bin", "third-party")
if os.path.exists(lic_dir):
shutil.rmtree(lic_dir) # copytree() won't overwrite existing files
shutil.copytree(os.path.join(os.path.dirname(__file__), "third-party"), lic_dir)
if __name__=="__main__":
make_win_dist(sys.argv[1], sys.argv[2], sys.argv[3])

View File

@ -112,7 +112,8 @@ LIT_INTEGER
;
LIT_FLOAT
: [0-9][0-9_]* ('.' | ('.' [0-9][0-9_]*)? ([eE] [-+]? [0-9][0-9_]*)? SUFFIX?)
: [0-9][0-9_]* ( '.' {_input.LA(1) != '.'}?
| ('.' [0-9][0-9_]*)? ([eE] [-+]? [0-9][0-9_]*)? SUFFIX?)
;
LIT_STR

View File

@ -61,7 +61,7 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
"SHL" => token::BinOp(token::Shl),
"LBRACE" => token::OpenDelim(token::Brace),
"RARROW" => token::RArrow,
"LIT_STR" => token::Literal(token::Str_(Name(0))),
"LIT_STR" => token::Literal(token::Str_(Name(0)), None),
"DOTDOT" => token::DotDot,
"MOD_SEP" => token::ModSep,
"DOTDOTDOT" => token::DotDotDot,
@ -71,7 +71,7 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
"ANDAND" => token::AndAnd,
"AT" => token::At,
"LBRACKET" => token::OpenDelim(token::Bracket),
"LIT_STR_RAW" => token::Literal(token::StrRaw(Name(0), 0)),
"LIT_STR_RAW" => token::Literal(token::StrRaw(Name(0), 0), None),
"RPAREN" => token::CloseDelim(token::Paren),
"SLASH" => token::BinOp(token::Slash),
"COMMA" => token::Comma,
@ -80,8 +80,8 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
"TILDE" => token::Tilde,
"IDENT" => id(),
"PLUS" => token::BinOp(token::Plus),
"LIT_CHAR" => token::Literal(token::Char(Name(0))),
"LIT_BYTE" => token::Literal(token::Byte(Name(0))),
"LIT_CHAR" => token::Literal(token::Char(Name(0)), None),
"LIT_BYTE" => token::Literal(token::Byte(Name(0)), None),
"EQ" => token::Eq,
"RBRACKET" => token::CloseDelim(token::Bracket),
"COMMENT" => token::Comment,
@ -95,9 +95,9 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
"BINOP" => token::BinOp(token::Plus),
"POUND" => token::Pound,
"OROR" => token::OrOr,
"LIT_INTEGER" => token::Literal(token::Integer(Name(0))),
"LIT_INTEGER" => token::Literal(token::Integer(Name(0)), None),
"BINOPEQ" => token::BinOpEq(token::Plus),
"LIT_FLOAT" => token::Literal(token::Float(Name(0))),
"LIT_FLOAT" => token::Literal(token::Float(Name(0)), None),
"WHITESPACE" => token::Whitespace,
"UNDERSCORE" => token::Underscore,
"MINUS" => token::BinOp(token::Minus),
@ -107,8 +107,8 @@ fn parse_token_list(file: &str) -> HashMap<String, token::Token> {
"OR" => token::BinOp(token::Or),
"GT" => token::Gt,
"LE" => token::Le,
"LIT_BINARY" => token::Literal(token::Binary(Name(0))),
"LIT_BINARY_RAW" => token::Literal(token::BinaryRaw(Name(0), 0)),
"LIT_BINARY" => token::Literal(token::Binary(Name(0)), None),
"LIT_BINARY_RAW" => token::Literal(token::BinaryRaw(Name(0), 0), None),
_ => continue,
};
@ -189,17 +189,17 @@ fn parse_antlr_token(s: &str, tokens: &HashMap<String, token::Token>) -> TokenAn
token::BinOp(..) => token::BinOp(str_to_binop(content)),
token::BinOpEq(..) => token::BinOpEq(str_to_binop(content.slice_to(
content.len() - 1))),
token::Literal(token::Str_(..)) => token::Literal(token::Str_(fix(content))),
token::Literal(token::StrRaw(..)) => token::Literal(token::StrRaw(fix(content),
count(content))),
token::Literal(token::Char(..)) => token::Literal(token::Char(fixchar(content))),
token::Literal(token::Byte(..)) => token::Literal(token::Byte(fixchar(content))),
token::Literal(token::Str_(..), n) => token::Literal(token::Str_(fix(content)), n),
token::Literal(token::StrRaw(..), n) => token::Literal(token::StrRaw(fix(content),
count(content)), n),
token::Literal(token::Char(..), n) => token::Literal(token::Char(fixchar(content)), n),
token::Literal(token::Byte(..), n) => token::Literal(token::Byte(fixchar(content)), n),
token::DocComment(..) => token::DocComment(nm),
token::Literal(token::Integer(..)) => token::Literal(token::Integer(nm)),
token::Literal(token::Float(..)) => token::Literal(token::Float(nm)),
token::Literal(token::Binary(..)) => token::Literal(token::Binary(nm)),
token::Literal(token::BinaryRaw(..)) => token::Literal(token::BinaryRaw(fix(content),
count(content))),
token::Literal(token::Integer(..), n) => token::Literal(token::Integer(nm), n),
token::Literal(token::Float(..), n) => token::Literal(token::Float(nm), n),
token::Literal(token::Binary(..), n) => token::Literal(token::Binary(nm), n),
token::Literal(token::BinaryRaw(..), n) => token::Literal(token::BinaryRaw(fix(content),
count(content)), n),
token::Ident(..) => token::Ident(ast::Ident { name: nm, ctxt: 0 },
token::ModName),
token::Lifetime(..) => token::Lifetime(ast::Ident { name: nm, ctxt: 0 }),
@ -214,8 +214,8 @@ fn parse_antlr_token(s: &str, tokens: &HashMap<String, token::Token>) -> TokenAn
};
let sp = syntax::codemap::Span {
lo: syntax::codemap::BytePos(from_str::<u32>(start).unwrap() - offset),
hi: syntax::codemap::BytePos(from_str::<u32>(end).unwrap() + 1),
lo: syntax::codemap::BytePos(start.parse::<u32>().unwrap() - offset),
hi: syntax::codemap::BytePos(end.parse::<u32>().unwrap() + 1),
expn_id: syntax::codemap::NO_EXPANSION
};
@ -247,7 +247,9 @@ fn main() {
let token_map = parse_token_list(token_file.read_to_string().unwrap().as_slice());
let mut stdin = std::io::stdin();
let mut antlr_tokens = stdin.lines().map(|l| parse_antlr_token(l.unwrap().as_slice().trim(),
let mut lock = stdin.lock();
let lines = lock.lines();
let mut antlr_tokens = lines.map(|l| parse_antlr_token(l.unwrap().as_slice().trim(),
&token_map));
let code = File::open(&Path::new(args[1].as_slice())).unwrap().read_to_string().unwrap();
@ -284,17 +286,17 @@ fn main() {
ref c => assert!(c == &antlr_tok.tok, "{} is not {}", rustc_tok, antlr_tok)
}
)
)
);
matches!(
token::Literal(token::Byte(..)),
token::Literal(token::Char(..)),
token::Literal(token::Integer(..)),
token::Literal(token::Float(..)),
token::Literal(token::Str_(..)),
token::Literal(token::StrRaw(..)),
token::Literal(token::Binary(..)),
token::Literal(token::BinaryRaw(..)),
token::Literal(token::Byte(..), _),
token::Literal(token::Char(..), _),
token::Literal(token::Integer(..), _),
token::Literal(token::Float(..), _),
token::Literal(token::Str_(..), _),
token::Literal(token::StrRaw(..), _),
token::Literal(token::Binary(..), _),
token::Literal(token::BinaryRaw(..), _),
token::Ident(..),
token::Lifetime(..),
token::Interpolated(..),

View File

@ -58,7 +58,7 @@
//! let five = five.clone();
//!
//! Thread::spawn(move || {
//! let mut number = five.lock();
//! let mut number = five.lock().unwrap();
//!
//! *number += 1;
//!
@ -80,7 +80,7 @@ use core::nonzero::NonZero;
use core::ops::{Drop, Deref};
use core::option::Option;
use core::option::Option::{Some, None};
use core::ptr::{mod, RawPtr};
use core::ptr::{mod, PtrExt};
use heap::deallocate;
/// An atomically reference counted wrapper for shared state.
@ -722,7 +722,7 @@ mod tests {
let a = Arc::new(Cycle { x: Mutex::new(None) });
let b = a.clone().downgrade();
*a.x.lock() = Some(b);
*a.x.lock().unwrap() = Some(b);
// hopefully we don't double-free (or leak)...
}

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::ptr::RawPtr;
use core::ptr::PtrExt;
// FIXME: #13996: mark the `allocate` and `reallocate` return value as `noalias`
@ -371,7 +371,7 @@ mod imp {
mod test {
extern crate test;
use self::test::Bencher;
use core::ptr::RawPtr;
use core::ptr::PtrExt;
use heap;
#[test]

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Task-local reference-counted boxes (the `Rc<T>` type).
//! Thread-local reference-counted boxes (the `Rc<T>` type).
//!
//! The `Rc<T>` type provides shared ownership of an immutable value. Destruction is deterministic,
//! and will occur as soon as the last owner is gone. It is marked as non-sendable because it
@ -154,7 +154,7 @@ use core::nonzero::NonZero;
use core::ops::{Deref, Drop};
use core::option::Option;
use core::option::Option::{Some, None};
use core::ptr::{mod, RawPtr};
use core::ptr::{mod, PtrExt};
use core::result::Result;
use core::result::Result::{Ok, Err};

View File

@ -412,7 +412,7 @@ impl<T> TypedArenaChunk<T> {
let size = calculate_size::<T>(self.capacity);
deallocate(self as *mut TypedArenaChunk<T> as *mut u8, size,
mem::min_align_of::<TypedArenaChunk<T>>());
if next.is_not_null() {
if !next.is_null() {
let capacity = (*next).capacity;
(*next).destroy(capacity);
}

View File

@ -95,7 +95,7 @@ impl<T> Rawlink<T> {
/// Convert the `Rawlink` into an Option value
fn resolve_immut<'a>(&self) -> Option<&'a T> {
unsafe {
self.p.as_ref()
mem::transmute(self.p.as_ref())
}
}

View File

@ -114,14 +114,14 @@ mod prelude {
pub use core::ops::{Drop, Fn, FnMut, FnOnce};
pub use core::option::Option;
pub use core::option::Option::{Some, None};
pub use core::ptr::RawPtr;
pub use core::ptr::PtrExt;
pub use core::result::Result;
pub use core::result::Result::{Ok, Err};
// in core and collections (may differ).
pub use slice::{PartialEqSliceExt, OrdSliceExt};
pub use slice::{AsSlice, SliceExt};
pub use str::{from_str, Str};
pub use str::{from_str, Str, StrExt};
// from other crates.
pub use alloc::boxed::Box;

View File

@ -96,7 +96,7 @@ use core::mem::size_of;
use core::mem;
use core::ops::{FnMut,SliceMut};
use core::prelude::{Clone, Greater, Iterator, IteratorExt, Less, None, Option};
use core::prelude::{Ord, Ordering, RawPtr, Some, range};
use core::prelude::{Ord, Ordering, PtrExt, Some, range};
use core::ptr;
use core::slice as core_slice;
use self::Direction::*;
@ -1343,11 +1343,14 @@ pub mod raw {
#[cfg(test)]
mod tests {
use std::boxed::Box;
use prelude::*;
use prelude::{Some, None, range, Vec, ToString, Clone, Greater, Less, Equal};
use prelude::{SliceExt, Iterator, IteratorExt, DoubleEndedIteratorExt};
use prelude::{OrdSliceExt, CloneSliceExt, PartialEqSliceExt, AsSlice};
use prelude::{RandomAccessIterator, Ord, VectorVector};
use core::cell::Cell;
use core::default::Default;
use core::mem;
use std::rand::{Rng, task_rng};
use std::rand::{Rng, thread_rng};
use std::rc::Rc;
use super::ElementSwaps;
@ -1963,7 +1966,7 @@ mod tests {
fn test_sort() {
for len in range(4u, 25) {
for _ in range(0i, 100) {
let mut v = task_rng().gen_iter::<uint>().take(len)
let mut v = thread_rng().gen_iter::<uint>().take(len)
.collect::<Vec<uint>>();
let mut v1 = v.clone();
@ -1999,7 +2002,7 @@ mod tests {
// number this element is, i.e. the second elements
// will occur in sorted order.
let mut v = range(0, len).map(|_| {
let n = task_rng().gen::<uint>() % 10;
let n = thread_rng().gen::<uint>() % 10;
counts[n] += 1;
(n, counts[n])
}).collect::<Vec<(uint, int)>>();

View File

@ -89,8 +89,6 @@ pub use unicode::str::{Words, Graphemes, GraphemeIndices};
pub use core::str::{Split, SplitTerminator};
pub use core::str::{SplitN, RSplitN};
// FIXME(conventions): ensure bit/char conventions are followed by str's API
/*
Section: Creating a string
*/
@ -1768,26 +1766,13 @@ impl StrExt for str {}
#[cfg(test)]
mod tests {
use std::iter::AdditiveIterator;
use std::iter::range;
use std::default::Default;
use std::char::Char;
use std::clone::Clone;
use std::cmp::{Ord, PartialOrd, Equiv};
use std::cmp::Ordering::{Equal, Greater, Less};
use std::option::Option::{mod, Some, None};
use std::result::Result::{Ok, Err};
use std::ptr::RawPtr;
use std::iter::{Iterator, IteratorExt, DoubleEndedIteratorExt};
use prelude::*;
use super::*;
use core::default::Default;
use core::iter::AdditiveIterator;
use super::{from_utf8, is_utf8, raw};
use super::MaybeOwned::{Owned, Slice};
use std::slice::{AsSlice, SliceExt};
use string::{String, ToString};
use vec::Vec;
use slice::CloneSliceExt;
use unicode::char::UnicodeChar;
use super::Utf8Error;
#[test]
fn test_le() {
@ -3354,7 +3339,7 @@ mod tests {
#[cfg(test)]
mod bench {
use super::*;
use prelude::*;
use prelude::{SliceExt, IteratorExt, DoubleEndedIteratorExt};
use test::Bencher;
use test::black_box;

View File

@ -12,6 +12,8 @@
//! An owned, growable string that enforces that its contents are valid UTF-8.
#![stable]
use core::prelude::*;
use core::borrow::{Cow, IntoCow};
@ -36,6 +38,18 @@ pub struct String {
vec: Vec<u8>,
}
/// A possible error value from the `String::from_utf8` function.
#[stable]
pub struct FromUtf8Error {
bytes: Vec<u8>,
error: Utf8Error,
}
/// A possible error value from the `String::from_utf16` function.
#[stable]
#[allow(missing_copy_implementations)]
pub struct FromUtf16Error(());
impl String {
/// Creates a new string buffer initialized with the empty string.
///
@ -98,19 +112,20 @@ impl String {
/// use std::str::Utf8Error;
///
/// let hello_vec = vec![104, 101, 108, 108, 111];
/// let s = String::from_utf8(hello_vec);
/// assert_eq!(s, Ok("hello".to_string()));
/// let s = String::from_utf8(hello_vec).unwrap();
/// assert_eq!(s, "hello");
///
/// let invalid_vec = vec![240, 144, 128];
/// let s = String::from_utf8(invalid_vec);
/// assert_eq!(s, Err((vec![240, 144, 128], Utf8Error::TooShort)));
/// let s = String::from_utf8(invalid_vec).err().unwrap();
/// assert_eq!(s.utf8_error(), Utf8Error::TooShort);
/// assert_eq!(s.into_bytes(), vec![240, 144, 128]);
/// ```
#[inline]
#[unstable = "error type may change"]
pub fn from_utf8(vec: Vec<u8>) -> Result<String, (Vec<u8>, Utf8Error)> {
#[stable]
pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
match str::from_utf8(vec.as_slice()) {
Ok(..) => Ok(String { vec: vec }),
Err(e) => Err((vec, e))
Err(e) => Err(FromUtf8Error { bytes: vec, error: e })
}
}
@ -124,7 +139,7 @@ impl String {
/// let output = String::from_utf8_lossy(input);
/// assert_eq!(output.as_slice(), "Hello \u{FFFD}World");
/// ```
#[unstable = "return type may change"]
#[stable]
pub fn from_utf8_lossy<'a>(v: &'a [u8]) -> CowString<'a> {
match str::from_utf8(v) {
Ok(s) => return Cow::Borrowed(s),
@ -251,22 +266,23 @@ impl String {
/// // 𝄞music
/// let mut v = &mut [0xD834, 0xDD1E, 0x006d, 0x0075,
/// 0x0073, 0x0069, 0x0063];
/// assert_eq!(String::from_utf16(v), Some("𝄞music".to_string()));
/// assert_eq!(String::from_utf16(v).unwrap(),
/// "𝄞music".to_string());
///
/// // 𝄞mu<invalid>ic
/// v[4] = 0xD800;
/// assert_eq!(String::from_utf16(v), None);
/// assert!(String::from_utf16(v).is_err());
/// ```
#[unstable = "error value in return may change"]
pub fn from_utf16(v: &[u16]) -> Option<String> {
#[stable]
pub fn from_utf16(v: &[u16]) -> Result<String, FromUtf16Error> {
let mut s = String::with_capacity(v.len());
for c in unicode_str::utf16_items(v) {
match c {
Utf16Item::ScalarValue(c) => s.push(c),
Utf16Item::LoneSurrogate(_) => return None
Utf16Item::LoneSurrogate(_) => return Err(FromUtf16Error(())),
}
}
Some(s)
Ok(s)
}
/// Decode a UTF-16 encoded vector `v` into a string, replacing
@ -293,12 +309,13 @@ impl String {
/// # Examples
///
/// ```rust
/// # #![allow(deprecated)]
/// let chars = &['h', 'e', 'l', 'l', 'o'];
/// let s = String::from_chars(chars);
/// assert_eq!(s.as_slice(), "hello");
/// ```
#[inline]
#[unstable = "may be removed in favor of .collect()"]
#[deprecated = "use .collect() instead"]
pub fn from_chars(chs: &[char]) -> String {
chs.iter().map(|c| *c).collect()
}
@ -309,7 +326,7 @@ impl String {
/// * We call `Vec::from_raw_parts` to get a `Vec<u8>`;
/// * We assume that the `Vec` contains valid UTF-8.
#[inline]
#[unstable = "function just moved from string::raw"]
#[stable]
pub unsafe fn from_raw_parts(buf: *mut u8, length: uint, capacity: uint) -> String {
String {
vec: Vec::from_raw_parts(buf, length, capacity),
@ -344,7 +361,7 @@ impl String {
/// it contains valid UTF-8. This is unsafe because it assumes that
/// the UTF-8-ness of the vector has already been validated.
#[inline]
#[unstable = "awaiting stabilization"]
#[stable]
pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String {
String { vec: bytes }
}
@ -369,12 +386,12 @@ impl String {
/// # Examples
///
/// ```
/// # #![allow(deprecated)]
/// let s = String::from_char(5, 'a');
/// assert_eq!(s.as_slice(), "aaaaa");
/// ```
#[inline]
#[unstable = "may be replaced with iterators, questionable usability, and \
the name may change"]
#[deprecated = "use repeat(ch).take(length).collect() instead"]
pub fn from_char(length: uint, ch: char) -> String {
if length == 0 {
return String::new()
@ -400,7 +417,7 @@ impl String {
/// assert_eq!(s.as_slice(), "foobar");
/// ```
#[inline]
#[unstable = "extra variants of `push`, could possibly be based on iterators"]
#[stable]
pub fn push_str(&mut self, string: &str) {
self.vec.push_all(string.as_bytes())
}
@ -410,19 +427,21 @@ impl String {
/// # Examples
///
/// ```
/// # #![allow(deprecated)]
/// let mut s = String::from_str("foo");
/// s.grow(5, 'Z');
/// assert_eq!(s.as_slice(), "fooZZZZZ");
/// ```
#[inline]
#[unstable = "duplicate of iterator-based functionality"]
#[deprecated = "deprecated in favor of .extend(repeat(ch).take(count))"]
pub fn grow(&mut self, count: uint, ch: char) {
for _ in range(0, count) {
self.push(ch)
}
}
/// Returns the number of bytes that this string buffer can hold without reallocating.
/// Returns the number of bytes that this string buffer can hold without
/// reallocating.
///
/// # Examples
///
@ -431,7 +450,7 @@ impl String {
/// assert!(s.capacity() >= 10);
/// ```
#[inline]
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[stable]
pub fn capacity(&self) -> uint {
self.vec.capacity()
}
@ -442,8 +461,9 @@ impl String {
self.vec.reserve(extra)
}
/// Reserves capacity for at least `additional` more bytes to be inserted in the given
/// `String`. The collection may reserve more space to avoid frequent reallocations.
/// Reserves capacity for at least `additional` more bytes to be inserted
/// in the given `String`. The collection may reserve more space to avoid
/// frequent reallocations.
///
/// # Panics
///
@ -457,17 +477,18 @@ impl String {
/// assert!(s.capacity() >= 10);
/// ```
#[inline]
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[stable]
pub fn reserve(&mut self, additional: uint) {
self.vec.reserve(additional)
}
/// Reserves the minimum capacity for exactly `additional` more bytes to be inserted in the
/// given `String`. Does nothing if the capacity is already sufficient.
/// Reserves the minimum capacity for exactly `additional` more bytes to be
/// inserted in the given `String`. Does nothing if the capacity is already
/// sufficient.
///
/// Note that the allocator may give the collection more space than it requests. Therefore
/// capacity can not be relied upon to be precisely minimal. Prefer `reserve` if future
/// insertions are expected.
/// Note that the allocator may give the collection more space than it
/// requests. Therefore capacity can not be relied upon to be precisely
/// minimal. Prefer `reserve` if future insertions are expected.
///
/// # Panics
///
@ -481,7 +502,7 @@ impl String {
/// assert!(s.capacity() >= 10);
/// ```
#[inline]
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[stable]
pub fn reserve_exact(&mut self, additional: uint) {
self.vec.reserve_exact(additional)
}
@ -498,7 +519,7 @@ impl String {
/// assert_eq!(s.capacity(), 3);
/// ```
#[inline]
#[unstable = "matches collection reform specification, waiting for dust to settle"]
#[stable]
pub fn shrink_to_fit(&mut self) {
self.vec.shrink_to_fit()
}
@ -515,7 +536,7 @@ impl String {
/// assert_eq!(s.as_slice(), "abc123");
/// ```
#[inline]
#[stable = "function just renamed from push_char"]
#[stable]
pub fn push(&mut self, ch: char) {
if (ch as u32) < 0x80 {
self.vec.push(ch as u8);
@ -568,7 +589,7 @@ impl String {
/// assert_eq!(s.as_slice(), "he");
/// ```
#[inline]
#[unstable = "the panic conventions for strings are under development"]
#[stable]
pub fn truncate(&mut self, new_len: uint) {
assert!(self.is_char_boundary(new_len));
self.vec.truncate(new_len)
@ -587,7 +608,7 @@ impl String {
/// assert_eq!(s.pop(), None);
/// ```
#[inline]
#[unstable = "this function was just renamed from pop_char"]
#[stable]
pub fn pop(&mut self) -> Option<char> {
let len = self.len();
if len == 0 {
@ -602,7 +623,7 @@ impl String {
}
/// Removes the character from the string buffer at byte position `idx` and
/// returns it. Returns `None` if `idx` is out of bounds.
/// returns it.
///
/// # Warning
///
@ -611,23 +632,21 @@ impl String {
///
/// # Panics
///
/// If `idx` does not lie on a character boundary, then this function will
/// panic.
/// If `idx` does not lie on a character boundary, or if it is out of
/// bounds, then this function will panic.
///
/// # Examples
///
/// ```
/// let mut s = String::from_str("foo");
/// assert_eq!(s.remove(0), Some('f'));
/// assert_eq!(s.remove(1), Some('o'));
/// assert_eq!(s.remove(0), Some('o'));
/// assert_eq!(s.remove(0), None);
/// assert_eq!(s.remove(0), 'f');
/// assert_eq!(s.remove(1), 'o');
/// assert_eq!(s.remove(0), 'o');
/// ```
#[unstable = "the panic semantics of this function and return type \
may change"]
pub fn remove(&mut self, idx: uint) -> Option<char> {
#[stable]
pub fn remove(&mut self, idx: uint) -> char {
let len = self.len();
if idx >= len { return None }
assert!(idx <= len);
let CharRange { ch, next } = self.char_range_at(idx);
unsafe {
@ -636,7 +655,7 @@ impl String {
len - next);
self.vec.set_len(len - (next - idx));
}
Some(ch)
ch
}
/// Insert a character into the string buffer at byte position `idx`.
@ -650,7 +669,7 @@ impl String {
///
/// If `idx` does not lie on a character boundary or is out of bounds, then
/// this function will panic.
#[unstable = "the panic semantics of this function are uncertain"]
#[stable]
pub fn insert(&mut self, idx: uint, ch: char) {
let len = self.len();
assert!(idx <= len);
@ -686,7 +705,7 @@ impl String {
/// }
/// assert_eq!(s.as_slice(), "olleh");
/// ```
#[unstable = "the name of this method may be changed"]
#[stable]
pub unsafe fn as_mut_vec<'a>(&'a mut self) -> &'a mut Vec<u8> {
&mut self.vec
}
@ -713,6 +732,7 @@ impl String {
/// v.push('a');
/// assert!(!v.is_empty());
/// ```
#[stable]
pub fn is_empty(&self) -> bool { self.len() == 0 }
/// Truncates the string, returning it to 0 length.
@ -731,6 +751,29 @@ impl String {
}
}
impl FromUtf8Error {
/// Consume this error, returning the bytes that were attempted to make a
/// `String` with.
#[stable]
pub fn into_bytes(self) -> Vec<u8> { self.bytes }
/// Access the underlying UTF8-error that was the cause of this error.
#[stable]
pub fn utf8_error(&self) -> Utf8Error { self.error }
}
impl fmt::Show for FromUtf8Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
self.error.fmt(f)
}
}
impl fmt::Show for FromUtf16Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
"invalid utf-16: lone surrogate found".fmt(f)
}
}
#[experimental = "waiting on FromIterator stabilization"]
impl FromIterator<char> for String {
fn from_iter<I:Iterator<char>>(iterator: I) -> String {
@ -933,6 +976,7 @@ impl FromStr for String {
}
/// Trait for converting a type to a string, consuming it in the process.
#[deprecated = "trait will be removed"]
pub trait IntoString {
/// Consume and convert to a string.
fn into_string(self) -> String;
@ -1038,7 +1082,7 @@ mod tests {
use prelude::*;
use test::Bencher;
use str::{StrExt, Utf8Error};
use str::Utf8Error;
use str;
use super::as_string;
@ -1057,16 +1101,17 @@ mod tests {
#[test]
fn test_from_utf8() {
let xs = b"hello".to_vec();
assert_eq!(String::from_utf8(xs),
Ok(String::from_str("hello")));
assert_eq!(String::from_utf8(xs).unwrap(),
String::from_str("hello"));
let xs = "ศไทย中华Việt Nam".as_bytes().to_vec();
assert_eq!(String::from_utf8(xs),
Ok(String::from_str("ศไทย中华Việt Nam")));
assert_eq!(String::from_utf8(xs).unwrap(),
String::from_str("ศไทย中华Việt Nam"));
let xs = b"hello\xFF".to_vec();
assert_eq!(String::from_utf8(xs),
Err((b"hello\xFF".to_vec(), Utf8Error::TooShort)));
let err = String::from_utf8(xs).err().unwrap();
assert_eq!(err.utf8_error(), Utf8Error::TooShort);
assert_eq!(err.into_bytes(), b"hello\xff".to_vec());
}
#[test]
@ -1171,15 +1216,15 @@ mod tests {
fn test_utf16_invalid() {
// completely positive cases tested above.
// lead + eof
assert_eq!(String::from_utf16(&[0xD800]), None);
assert!(String::from_utf16(&[0xD800]).is_err());
// lead + lead
assert_eq!(String::from_utf16(&[0xD800, 0xD800]), None);
assert!(String::from_utf16(&[0xD800, 0xD800]).is_err());
// isolated trail
assert_eq!(String::from_utf16(&[0x0061, 0xDC00]), None);
assert!(String::from_utf16(&[0x0061, 0xDC00]).is_err());
// general
assert_eq!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]), None);
assert!(String::from_utf16(&[0xD800, 0xd801, 0xdc8b, 0xD800]).is_err());
}
#[test]
@ -1312,12 +1357,10 @@ mod tests {
#[test]
fn remove() {
let mut s = "ศไทย中华Việt Nam; foobar".to_string();;
assert_eq!(s.remove(0), Some('ศ'));
assert_eq!(s.remove(0), 'ศ');
assert_eq!(s.len(), 33);
assert_eq!(s, "ไทย中华Việt Nam; foobar");
assert_eq!(s.remove(33), None);
assert_eq!(s.remove(300), None);
assert_eq!(s.remove(17), Some('ệ'));
assert_eq!(s.remove(17), 'ệ');
assert_eq!(s, "ไทย中华Vit Nam; foobar");
}

View File

@ -158,7 +158,7 @@
use clone::Clone;
use cmp::PartialEq;
use default::Default;
use kinds::{marker, Copy};
use kinds::{Copy, Send};
use ops::{Deref, DerefMut, Drop};
use option::Option;
use option::Option::{None, Some};
@ -167,7 +167,6 @@ use option::Option::{None, Some};
#[stable]
pub struct Cell<T> {
value: UnsafeCell<T>,
noshare: marker::NoSync,
}
impl<T:Copy> Cell<T> {
@ -176,7 +175,6 @@ impl<T:Copy> Cell<T> {
pub fn new(value: T) -> Cell<T> {
Cell {
value: UnsafeCell::new(value),
noshare: marker::NoSync,
}
}
@ -208,6 +206,9 @@ impl<T:Copy> Cell<T> {
}
}
#[stable]
unsafe impl<T> Send for Cell<T> where T: Send {}
#[stable]
impl<T:Copy> Clone for Cell<T> {
fn clone(&self) -> Cell<T> {
@ -235,7 +236,6 @@ impl<T:PartialEq + Copy> PartialEq for Cell<T> {
pub struct RefCell<T> {
value: UnsafeCell<T>,
borrow: Cell<BorrowFlag>,
noshare: marker::NoSync,
}
// Values [1, MAX-1] represent the number of `Ref` active
@ -251,7 +251,6 @@ impl<T> RefCell<T> {
RefCell {
value: UnsafeCell::new(value),
borrow: Cell::new(UNUSED),
noshare: marker::NoSync,
}
}
@ -341,6 +340,9 @@ impl<T> RefCell<T> {
}
}
#[stable]
unsafe impl<T> Send for RefCell<T> where T: Send {}
#[stable]
impl<T: Clone> Clone for RefCell<T> {
fn clone(&self) -> RefCell<T> {

View File

@ -36,7 +36,7 @@ pub trait Clone {
/// but can be overridden to reuse the resources of `a` to avoid unnecessary
/// allocations.
#[inline(always)]
#[unstable = "this function rarely unused"]
#[unstable = "this function is rarely used"]
fn clone_from(&mut self, source: &Self) {
*self = source.clone()
}

View File

@ -85,16 +85,6 @@ macro_rules! assert {
);
}
/// Runtime assertion, only without `--cfg ndebug`
#[macro_export]
macro_rules! debug_assert {
($(a:tt)*) => ({
if cfg!(not(ndebug)) {
assert!($($a)*);
}
})
}
/// Runtime assertion for equality, for details see std::macros
#[macro_export]
macro_rules! assert_eq {
@ -117,7 +107,7 @@ macro_rules! debug_assert_eq {
})
}
/// Runtime assertion, disableable at compile time
/// Runtime assertion, disableable at compile time with `--cfg ndebug`
#[macro_export]
macro_rules! debug_assert {
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert!($($arg)*); })

View File

@ -57,7 +57,7 @@ pub use iter::{IteratorOrdExt, MutableDoubleEndedIterator, ExactSizeIterator};
pub use num::{ToPrimitive, FromPrimitive};
pub use option::Option;
pub use option::Option::{Some, None};
pub use ptr::RawPtr;
pub use ptr::{PtrExt, MutPtrExt};
pub use result::Result;
pub use result::Result::{Ok, Err};
pub use str::{Str, StrExt};

View File

@ -16,11 +16,10 @@
//! typically limited to a few patterns.
//!
//! Use the [`null` function](fn.null.html) to create null pointers,
//! the [`is_null`](trait.RawPtr.html#tymethod.is_null)
//! and [`is_not_null`](trait.RawPtr.html#method.is_not_null)
//! methods of the [`RawPtr` trait](trait.RawPtr.html) to check for null.
//! The `RawPtr` trait is imported by the prelude, so `is_null` etc.
//! work everywhere. The `RawPtr` also defines the `offset` method,
//! the [`is_null`](trait.PtrExt.html#tymethod.is_null)
//! methods of the [`PtrExt` trait](trait.PtrExt.html) to check for null.
//! The `PtrExt` trait is imported by the prelude, so `is_null` etc.
//! work everywhere. The `PtrExt` also defines the `offset` method,
//! for pointer math.
//!
//! # Common ways to create unsafe pointers
@ -87,16 +86,16 @@
//! but C APIs hand out a lot of pointers generally, so are a common source
//! of unsafe pointers in Rust.
#![stable]
use mem;
use clone::Clone;
use intrinsics;
use option::Option::{mod, Some, None};
use kinds::{Send, Sync};
use option::Option;
use option::Option::{Some, None};
use cmp::{PartialEq, Eq, Ord, PartialOrd, Equiv};
use cmp::Ordering;
use cmp::Ordering::{Less, Equal, Greater};
use cmp::Ordering::{mod, Less, Equal, Greater};
// FIXME #19649: instrinsic docs don't render, so these have no docs :(
@ -121,7 +120,7 @@ pub use intrinsics::set_memory;
/// assert!(p.is_null());
/// ```
#[inline]
#[unstable = "may need a different name after pending changes to pointer types"]
#[stable]
pub fn null<T>() -> *const T { 0 as *const T }
/// Creates a null mutable raw pointer.
@ -135,31 +134,31 @@ pub fn null<T>() -> *const T { 0 as *const T }
/// assert!(p.is_null());
/// ```
#[inline]
#[unstable = "may need a different name after pending changes to pointer types"]
#[stable]
pub fn null_mut<T>() -> *mut T { 0 as *mut T }
/// Zeroes out `count * size_of::<T>` bytes of memory at `dst`. `count` may be `0`.
/// Zeroes out `count * size_of::<T>` bytes of memory at `dst`. `count` may be
/// `0`.
///
/// # Safety
///
/// Beyond accepting a raw pointer, this is unsafe because it will not drop the contents of `dst`,
/// and may be used to create invalid instances of `T`.
/// Beyond accepting a raw pointer, this is unsafe because it will not drop the
/// contents of `dst`, and may be used to create invalid instances of `T`.
#[inline]
#[experimental = "uncertain about naming and semantics"]
#[allow(experimental)]
#[unstable = "may play a larger role in std::ptr future extensions"]
pub unsafe fn zero_memory<T>(dst: *mut T, count: uint) {
set_memory(dst, 0, count);
}
/// Swaps the values at two mutable locations of the same type, without
/// deinitialising either. They may overlap, unlike `mem::swap` which is otherwise
/// equivalent.
/// deinitialising either. They may overlap, unlike `mem::swap` which is
/// otherwise equivalent.
///
/// # Safety
///
/// This is only unsafe because it accepts a raw pointer.
#[inline]
#[unstable]
#[stable]
pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
// Give ourselves some scratch space to work with
let mut tmp: T = mem::uninitialized();
@ -183,7 +182,7 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
/// This is only unsafe because it accepts a raw pointer.
/// Otherwise, this operation is identical to `mem::replace`.
#[inline]
#[unstable]
#[stable]
pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
mem::swap(mem::transmute(dest), &mut src); // cannot overlap
src
@ -201,7 +200,7 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
/// `zero_memory`, or `copy_memory`). Note that `*src = foo` counts as a use
/// because it will attempt to drop the value previously at `*src`.
#[inline(always)]
#[unstable]
#[stable]
pub unsafe fn read<T>(src: *const T) -> T {
let mut tmp: T = mem::uninitialized();
copy_nonoverlapping_memory(&mut tmp, src, 1);
@ -214,8 +213,7 @@ pub unsafe fn read<T>(src: *const T) -> T {
///
/// This is unsafe for the same reasons that `read` is unsafe.
#[inline(always)]
#[experimental]
#[allow(experimental)]
#[unstable = "may play a larger role in std::ptr future extensions"]
pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
// Copy the data out from `dest`:
let tmp = read(&*dest);
@ -226,8 +224,8 @@ pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
tmp
}
/// Overwrites a memory location with the given value without reading or dropping
/// the old value.
/// Overwrites a memory location with the given value without reading or
/// dropping the old value.
///
/// # Safety
///
@ -235,36 +233,44 @@ pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
/// not drop the contents of `dst`. This could leak allocations or resources,
/// so care must be taken not to overwrite an object that should be dropped.
///
/// This is appropriate for initializing uninitialized memory, or overwritting memory
/// that has previously been `read` from.
/// This is appropriate for initializing uninitialized memory, or overwritting
/// memory that has previously been `read` from.
#[inline]
#[unstable]
#[stable]
pub unsafe fn write<T>(dst: *mut T, src: T) {
intrinsics::move_val_init(&mut *dst, src)
}
/// Methods on raw pointers
pub trait RawPtr<T> {
/// Returns a null raw pointer.
#[stable]
pub trait PtrExt<T> {
/// Returns the null pointer.
#[deprecated = "call ptr::null instead"]
fn null() -> Self;
/// Returns true if the pointer is null.
fn is_null(&self) -> bool;
#[stable]
fn is_null(self) -> bool;
/// Returns true if the pointer is not equal to the null pointer.
#[deprecated = "use !p.is_null() instead"]
fn is_not_null(self) -> bool { !self.is_null() }
/// Returns true if the pointer is not null.
fn is_not_null(&self) -> bool { !self.is_null() }
#[deprecated = "use `as uint` instead"]
fn to_uint(self) -> uint;
/// Returns the address of the pointer.
fn to_uint(&self) -> uint;
/// Returns `None` if the pointer is null, or else returns a reference to the
/// value wrapped in `Some`.
/// Returns `None` if the pointer is null, or else returns a reference to
/// the value wrapped in `Some`.
///
/// # Safety
///
/// While this method and its mutable counterpart are useful for null-safety,
/// it is important to note that this is still an unsafe operation because
/// the returned value could be pointing to invalid memory.
/// While this method and its mutable counterpart are useful for
/// null-safety, it is important to note that this is still an unsafe
/// operation because the returned value could be pointing to invalid
/// memory.
#[unstable = "Option is not clearly the right return type, and we may want \
to tie the return lifetime to a borrow of the raw pointer"]
unsafe fn as_ref<'a>(&self) -> Option<&'a T>;
/// Calculates the offset from a pointer. `count` is in units of T; e.g. a
@ -272,39 +278,51 @@ pub trait RawPtr<T> {
///
/// # Safety
///
/// The offset must be in-bounds of the object, or one-byte-past-the-end. Otherwise
/// `offset` invokes Undefined Behaviour, regardless of whether the pointer is used.
/// The offset must be in-bounds of the object, or one-byte-past-the-end.
/// Otherwise `offset` invokes Undefined Behaviour, regardless of whether
/// the pointer is used.
#[stable]
unsafe fn offset(self, count: int) -> Self;
}
/// Methods on mutable raw pointers
pub trait RawMutPtr<T>{
/// Returns `None` if the pointer is null, or else returns a mutable reference
/// to the value wrapped in `Some`.
#[stable]
pub trait MutPtrExt<T>{
/// Returns `None` if the pointer is null, or else returns a mutable
/// reference to the value wrapped in `Some`.
///
/// # Safety
///
/// As with `as_ref`, this is unsafe because it cannot verify the validity
/// of the returned pointer.
#[unstable = "Option is not clearly the right return type, and we may want \
to tie the return lifetime to a borrow of the raw pointer"]
unsafe fn as_mut<'a>(&self) -> Option<&'a mut T>;
}
impl<T> RawPtr<T> for *const T {
#[stable]
impl<T> PtrExt<T> for *const T {
#[inline]
#[deprecated = "call ptr::null instead"]
fn null() -> *const T { null() }
#[inline]
fn is_null(&self) -> bool { *self == RawPtr::null() }
#[stable]
fn is_null(self) -> bool { self as uint == 0 }
#[inline]
fn to_uint(&self) -> uint { *self as uint }
#[deprecated = "use `as uint` instead"]
fn to_uint(self) -> uint { self as uint }
#[inline]
#[stable]
unsafe fn offset(self, count: int) -> *const T {
intrinsics::offset(self, count)
}
#[inline]
#[unstable = "return value does not necessarily convey all possible \
information"]
unsafe fn as_ref<'a>(&self) -> Option<&'a T> {
if self.is_null() {
None
@ -314,22 +332,29 @@ impl<T> RawPtr<T> for *const T {
}
}
impl<T> RawPtr<T> for *mut T {
#[stable]
impl<T> PtrExt<T> for *mut T {
#[inline]
#[deprecated = "call ptr::null instead"]
fn null() -> *mut T { null_mut() }
#[inline]
fn is_null(&self) -> bool { *self == RawPtr::null() }
#[stable]
fn is_null(self) -> bool { self as uint == 0 }
#[inline]
fn to_uint(&self) -> uint { *self as uint }
#[deprecated = "use `as uint` instead"]
fn to_uint(self) -> uint { self as uint }
#[inline]
#[stable]
unsafe fn offset(self, count: int) -> *mut T {
intrinsics::offset(self as *const T, count) as *mut T
}
#[inline]
#[unstable = "return value does not necessarily convey all possible \
information"]
unsafe fn as_ref<'a>(&self) -> Option<&'a T> {
if self.is_null() {
None
@ -339,8 +364,11 @@ impl<T> RawPtr<T> for *mut T {
}
}
impl<T> RawMutPtr<T> for *mut T {
#[stable]
impl<T> MutPtrExt<T> for *mut T {
#[inline]
#[unstable = "return value does not necessarily convey all possible \
information"]
unsafe fn as_mut<'a>(&self) -> Option<&'a mut T> {
if self.is_null() {
None
@ -510,28 +538,33 @@ impl<T> PartialOrd for *mut T {
/// raw `*mut T` (which conveys no particular ownership semantics).
/// Useful for building abstractions like `Vec<T>` or `Box<T>`, which
/// internally use raw pointers to manage the memory that they own.
#[unstable = "recently added to this module"]
pub struct Unique<T>(pub *mut T);
/// `Unique` pointers are `Send` if `T` is `Send` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
#[unstable = "recently added to this module"]
unsafe impl<T:Send> Send for Unique<T> { }
/// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
/// reference is unaliased. Note that this aliasing invariant is
/// unenforced by the type system; the abstraction using the
/// `Unique` must enforce it.
#[unstable = "recently added to this module"]
unsafe impl<T:Sync> Sync for Unique<T> { }
impl<T> Unique<T> {
/// Returns a null Unique.
#[unstable = "recently added to this module"]
pub fn null() -> Unique<T> {
Unique(RawPtr::null())
Unique(null_mut())
}
/// Return an (unsafe) pointer into the memory owned by `self`.
#[unstable = "recently added to this module"]
pub unsafe fn offset(self, offset: int) -> *mut T {
(self.0 as *const T).offset(offset) as *mut T
self.0.offset(offset)
}
}

View File

@ -332,7 +332,7 @@ impl<T, E> Result<T, E> {
/// Convert from `Result<T, E>` to `Option<E>`
///
/// Converts `self` into an `Option<T>`, consuming `self`,
/// Converts `self` into an `Option<E>`, consuming `self`,
/// and discarding the value, if any.
///
/// # Example

View File

@ -47,7 +47,7 @@ use ops::{FnMut, mod};
use option::Option;
use option::Option::{None, Some};
use ptr;
use ptr::RawPtr;
use ptr::PtrExt;
use mem;
use mem::size_of;
use kinds::{Sized, marker};
@ -1335,7 +1335,7 @@ pub unsafe fn from_raw_mut_buf<'a, T>(p: &'a *mut T, len: uint) -> &'a mut [T] {
#[deprecated]
pub mod raw {
use mem::transmute;
use ptr::RawPtr;
use ptr::PtrExt;
use raw::Slice;
use ops::FnOnce;
use option::Option;

View File

@ -28,7 +28,7 @@ use mem;
use num::Int;
use ops::{Fn, FnMut};
use option::Option::{mod, None, Some};
use ptr::RawPtr;
use ptr::PtrExt;
use raw::{Repr, Slice};
use result::Result::{mod, Ok, Err};
use slice::{mod, SliceExt};
@ -1073,7 +1073,7 @@ const TAG_CONT_U8: u8 = 0b1000_0000u8;
/// Unsafe operations
#[deprecated]
pub mod raw {
use ptr::RawPtr;
use ptr::PtrExt;
use raw::Slice;
use slice::SliceExt;
use str::StrExt;

View File

@ -112,7 +112,7 @@ mod tests {
#[test]
fn test_flate_round_trip() {
let mut r = rand::task_rng();
let mut r = rand::thread_rng();
let mut words = vec!();
for _ in range(0u, 20) {
let range = r.gen_range(1u, 10);

View File

@ -64,7 +64,7 @@ impl Rand for Exp1 {
/// use std::rand::distributions::{Exp, IndependentSample};
///
/// let exp = Exp::new(2.0);
/// let v = exp.ind_sample(&mut rand::task_rng());
/// let v = exp.ind_sample(&mut rand::thread_rng());
/// println!("{} is from a Exp(2) distribution", v);
/// ```
#[deriving(Copy)]

View File

@ -44,7 +44,7 @@ use super::{IndependentSample, Sample, Exp};
/// use std::rand::distributions::{IndependentSample, Gamma};
///
/// let gamma = Gamma::new(2.0, 5.0);
/// let v = gamma.ind_sample(&mut rand::task_rng());
/// let v = gamma.ind_sample(&mut rand::thread_rng());
/// println!("{} is from a Gamma(2, 5) distribution", v);
/// ```
///
@ -191,7 +191,7 @@ impl IndependentSample<f64> for GammaLargeShape {
/// use std::rand::distributions::{ChiSquared, IndependentSample};
///
/// let chi = ChiSquared::new(11.0);
/// let v = chi.ind_sample(&mut rand::task_rng());
/// let v = chi.ind_sample(&mut rand::thread_rng());
/// println!("{} is from a χ²(11) distribution", v)
/// ```
pub struct ChiSquared {
@ -248,7 +248,7 @@ impl IndependentSample<f64> for ChiSquared {
/// use std::rand::distributions::{FisherF, IndependentSample};
///
/// let f = FisherF::new(2.0, 32.0);
/// let v = f.ind_sample(&mut rand::task_rng());
/// let v = f.ind_sample(&mut rand::thread_rng());
/// println!("{} is from an F(2, 32) distribution", v)
/// ```
pub struct FisherF {
@ -292,7 +292,7 @@ impl IndependentSample<f64> for FisherF {
/// use std::rand::distributions::{StudentT, IndependentSample};
///
/// let t = StudentT::new(11.0);
/// let v = t.ind_sample(&mut rand::task_rng());
/// let v = t.ind_sample(&mut rand::thread_rng());
/// println!("{} is from a t(11) distribution", v)
/// ```
pub struct StudentT {

View File

@ -96,7 +96,7 @@ pub struct Weighted<T> {
/// Weighted { weight: 4, item: 'b' },
/// Weighted { weight: 1, item: 'c' });
/// let wc = WeightedChoice::new(items.as_mut_slice());
/// let mut rng = rand::task_rng();
/// let mut rng = rand::thread_rng();
/// for _ in range(0u, 16) {
/// // on average prints 'a' 4 times, 'b' 8 and 'c' twice.
/// println!("{}", wc.ind_sample(&mut rng));

View File

@ -81,7 +81,7 @@ impl Rand for StandardNormal {
///
/// // mean 2, standard deviation 3
/// let normal = Normal::new(2.0, 3.0);
/// let v = normal.ind_sample(&mut rand::task_rng());
/// let v = normal.ind_sample(&mut rand::thread_rng());
/// println!("{} is from a N(2, 9) distribution", v)
/// ```
#[deriving(Copy)]
@ -129,7 +129,7 @@ impl IndependentSample<f64> for Normal {
///
/// // mean 2, standard deviation 3
/// let log_normal = LogNormal::new(2.0, 3.0);
/// let v = log_normal.ind_sample(&mut rand::task_rng());
/// let v = log_normal.ind_sample(&mut rand::thread_rng());
/// println!("{} is from an ln N(2, 9) distribution", v)
/// ```
#[deriving(Copy)]

View File

@ -39,7 +39,7 @@ use distributions::{Sample, IndependentSample};
///
/// fn main() {
/// let between = Range::new(10u, 10000u);
/// let mut rng = std::rand::task_rng();
/// let mut rng = std::rand::thread_rng();
/// let mut sum = 0;
/// for _ in range(0u, 1000) {
/// sum += between.ind_sample(&mut rng);

View File

@ -138,10 +138,10 @@ pub trait Rng {
/// # Example
///
/// ```rust
/// use std::rand::{task_rng, Rng};
/// use std::rand::{thread_rng, Rng};
///
/// let mut v = [0u8, .. 13579];
/// task_rng().fill_bytes(&mut v);
/// thread_rng().fill_bytes(&mut v);
/// println!("{}", v.as_slice());
/// ```
fn fill_bytes(&mut self, dest: &mut [u8]) {
@ -173,9 +173,9 @@ pub trait Rng {
/// # Example
///
/// ```rust
/// use std::rand::{task_rng, Rng};
/// use std::rand::{thread_rng, Rng};
///
/// let mut rng = task_rng();
/// let mut rng = thread_rng();
/// let x: uint = rng.gen();
/// println!("{}", x);
/// println!("{}", rng.gen::<(f64, bool)>());
@ -191,9 +191,9 @@ pub trait Rng {
/// # Example
///
/// ```
/// use std::rand::{task_rng, Rng};
/// use std::rand::{thread_rng, Rng};
///
/// let mut rng = task_rng();
/// let mut rng = thread_rng();
/// let x = rng.gen_iter::<uint>().take(10).collect::<Vec<uint>>();
/// println!("{}", x);
/// println!("{}", rng.gen_iter::<(f64, bool)>().take(5)
@ -218,9 +218,9 @@ pub trait Rng {
/// # Example
///
/// ```rust
/// use std::rand::{task_rng, Rng};
/// use std::rand::{thread_rng, Rng};
///
/// let mut rng = task_rng();
/// let mut rng = thread_rng();
/// let n: uint = rng.gen_range(0u, 10);
/// println!("{}", n);
/// let m: f64 = rng.gen_range(-40.0f64, 1.3e5f64);
@ -236,9 +236,9 @@ pub trait Rng {
/// # Example
///
/// ```rust
/// use std::rand::{task_rng, Rng};
/// use std::rand::{thread_rng, Rng};
///
/// let mut rng = task_rng();
/// let mut rng = thread_rng();
/// println!("{}", rng.gen_weighted_bool(3));
/// ```
fn gen_weighted_bool(&mut self, n: uint) -> bool {
@ -250,9 +250,9 @@ pub trait Rng {
/// # Example
///
/// ```rust
/// use std::rand::{task_rng, Rng};
/// use std::rand::{thread_rng, Rng};
///
/// let s: String = task_rng().gen_ascii_chars().take(10).collect();
/// let s: String = thread_rng().gen_ascii_chars().take(10).collect();
/// println!("{}", s);
/// ```
fn gen_ascii_chars<'a>(&'a mut self) -> AsciiGenerator<'a, Self> {
@ -266,10 +266,10 @@ pub trait Rng {
/// # Example
///
/// ```
/// use std::rand::{task_rng, Rng};
/// use std::rand::{thread_rng, Rng};
///
/// let choices = [1i, 2, 4, 8, 16, 32];
/// let mut rng = task_rng();
/// let mut rng = thread_rng();
/// println!("{}", rng.choose(&choices));
/// assert_eq!(rng.choose(choices[..0]), None);
/// ```
@ -286,9 +286,9 @@ pub trait Rng {
/// # Example
///
/// ```rust
/// use std::rand::{task_rng, Rng};
/// use std::rand::{thread_rng, Rng};
///
/// let mut rng = task_rng();
/// let mut rng = thread_rng();
/// let mut y = [1i, 2, 3];
/// rng.shuffle(&mut y);
/// println!("{}", y.as_slice());
@ -520,8 +520,8 @@ mod test {
}
}
pub fn rng() -> MyRng<rand::TaskRng> {
MyRng { inner: rand::task_rng() }
pub fn rng() -> MyRng<rand::ThreadRng> {
MyRng { inner: rand::thread_rng() }
}
pub fn weak_rng() -> MyRng<rand::XorShiftRng> {

View File

@ -215,7 +215,7 @@ impl<T:Rand> Rand for Option<T> {
#[cfg(test)]
mod tests {
use std::prelude::*;
use std::rand::{Rng, task_rng, Open01, Closed01};
use std::rand::{Rng, thread_rng, Open01, Closed01};
struct ConstantRng(u64);
impl Rng for ConstantRng {
@ -240,7 +240,7 @@ mod tests {
fn rand_open() {
// this is unlikely to catch an incorrect implementation that
// generates exactly 0 or 1, but it keeps it sane.
let mut rng = task_rng();
let mut rng = thread_rng();
for _ in range(0u, 1_000) {
// strict inequalities
let Open01(f) = rng.gen::<Open01<f64>>();
@ -253,7 +253,7 @@ mod tests {
#[test]
fn rand_closed() {
let mut rng = task_rng();
let mut rng = thread_rng();
for _ in range(0u, 1_000) {
// strict inequalities
let Closed01(f) = rng.gen::<Closed01<f64>>();

View File

@ -519,8 +519,8 @@ impl<'a> Parser<'a> {
};
self.chari = closer;
let greed = try!(self.get_next_greedy());
let inner = String::from_chars(
self.chars[start+1..closer]);
let inner = self.chars[start+1..closer].iter().cloned()
.collect::<String>();
// Parse the min and max values from the regex.
let (mut min, mut max): (uint, Option<uint>);
@ -954,7 +954,7 @@ impl<'a> Parser<'a> {
}
fn slice(&self, start: uint, end: uint) -> String {
String::from_chars(self.chars[start..end])
self.chars[start..end].iter().cloned().collect()
}
}

View File

@ -9,8 +9,9 @@
// except according to those terms.
#![allow(non_snake_case)]
use std::rand::{Rng, task_rng};
use std::rand::{Rng, thread_rng};
use stdtest::Bencher;
use std::iter::repeat;
use regex::{Regex, NoExpand};
@ -22,30 +23,30 @@ fn bench_assert_match(b: &mut Bencher, re: Regex, text: &str) {
fn no_exponential(b: &mut Bencher) {
let n = 100;
let re = Regex::new(format!("{}{}",
"a?".repeat(n),
"a".repeat(n)).as_slice()).unwrap();
let text = "a".repeat(n);
repeat("a?").take(n).collect::<String>(),
repeat("a").take(n).collect::<String>()).as_slice()).unwrap();
let text = repeat("a").take(n).collect::<String>();
bench_assert_match(b, re, text.as_slice());
}
#[bench]
fn literal(b: &mut Bencher) {
let re = regex!("y");
let text = format!("{}y", "x".repeat(50));
let text = format!("{}y", repeat("x").take(50).collect::<String>());
bench_assert_match(b, re, text.as_slice());
}
#[bench]
fn not_literal(b: &mut Bencher) {
let re = regex!(".y");
let text = format!("{}y", "x".repeat(50));
let text = format!("{}y", repeat("x").take(50).collect::<String>());
bench_assert_match(b, re, text.as_slice());
}
#[bench]
fn match_class(b: &mut Bencher) {
let re = regex!("[abcdw]");
let text = format!("{}w", "xxxx".repeat(20));
let text = format!("{}w", repeat("xxxx").take(20).collect::<String>());
bench_assert_match(b, re, text.as_slice());
}
@ -53,7 +54,7 @@ fn match_class(b: &mut Bencher) {
fn match_class_in_range(b: &mut Bencher) {
// 'b' is between 'a' and 'c', so the class range checking doesn't help.
let re = regex!("[ac]");
let text = format!("{}c", "bbbb".repeat(20));
let text = format!("{}c", repeat("bbbb").take(20).collect::<String>());
bench_assert_match(b, re, text.as_slice());
}
@ -77,7 +78,7 @@ fn anchored_literal_short_non_match(b: &mut Bencher) {
#[bench]
fn anchored_literal_long_non_match(b: &mut Bencher) {
let re = regex!("^zbc(d|e)");
let text = "abcdefghijklmnopqrstuvwxyz".repeat(15);
let text = repeat("abcdefghijklmnopqrstuvwxyz").take(15).collect::<String>();
b.iter(|| re.is_match(text.as_slice()));
}
@ -91,7 +92,7 @@ fn anchored_literal_short_match(b: &mut Bencher) {
#[bench]
fn anchored_literal_long_match(b: &mut Bencher) {
let re = regex!("^.bc(d|e)");
let text = "abcdefghijklmnopqrstuvwxyz".repeat(15);
let text = repeat("abcdefghijklmnopqrstuvwxyz").take(15).collect::<String>();
b.iter(|| re.is_match(text.as_slice()));
}
@ -154,7 +155,7 @@ fn medium() -> Regex { regex!("[XYZ]ABCDEFGHIJKLMNOPQRSTUVWXYZ$") }
fn hard() -> Regex { regex!("[ -~]*ABCDEFGHIJKLMNOPQRSTUVWXYZ$") }
fn gen_text(n: uint) -> String {
let mut rng = task_rng();
let mut rng = thread_rng();
let mut bytes = rng.gen_ascii_chars().map(|n| n as u8).take(n)
.collect::<Vec<u8>>();
for (i, b) in bytes.iter_mut().enumerate() {

View File

@ -1782,9 +1782,9 @@ impl LintPass for Stability {
if self.is_internal(cx, item.span) { return }
match item.node {
ast::ItemTrait(_, _, _, ref supertraits, _) => {
ast::ItemTrait(_, _, ref supertraits, _) => {
for t in supertraits.iter() {
if let ast::TraitTyParamBound(ref t) = *t {
if let ast::TraitTyParamBound(ref t, _) = *t {
let id = ty::trait_ref_to_def_id(cx.tcx, &t.trait_ref);
self.lint(cx, id, t.trait_ref.path.span);
}

View File

@ -1308,7 +1308,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
}
}
}
ast::ItemTrait(_, _, _, _, ref ms) => {
ast::ItemTrait(_, _, _, ref ms) => {
add_to_index(item, rbml_w, index);
rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, def_id);

View File

@ -25,7 +25,7 @@ use middle::ty::*;
use middle::ty;
use std::fmt;
use std::iter::AdditiveIterator;
use std::iter::range_inclusive;
use std::iter::{range_inclusive, repeat};
use std::num::Float;
use std::slice;
use syntax::ast::{mod, DUMMY_NODE_ID, NodeId, Pat};
@ -76,7 +76,7 @@ impl<'a> fmt::Show for Matrix<'a> {
}).collect();
let total_width = column_widths.iter().map(|n| *n).sum() + column_count * 3 + 1;
let br = String::from_char(total_width, '+');
let br = repeat('+').take(total_width).collect::<String>();
try!(write!(f, "{}\n", br));
for row in pretty_printed_matrix.into_iter() {
try!(write!(f, "+"));

View File

@ -1043,7 +1043,6 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
ident: ty_param.ident,
id: ty_param.id,
bounds: bounds,
unbound: ty_param.unbound.clone(),
default: ty_param.default.clone(),
span: ty_param.span,
}
@ -1063,7 +1062,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
// be passing down a map.
ast::RegionTyParamBound(lt)
}
&ast::TraitTyParamBound(ref poly_tr) => {
&ast::TraitTyParamBound(ref poly_tr, modifier) => {
let tr = &poly_tr.trait_ref;
let last_seg = tr.path.segments.last().unwrap();
let mut insert = Vec::new();
@ -1087,7 +1086,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
path: new_path,
ref_id: tr.ref_id,
}
})
}, modifier)
}
}
})

View File

@ -122,7 +122,7 @@ impl<'v> Visitor<'v> for ParentVisitor {
// method to the root. In this case, if the trait is private, then
// parent all the methods to the trait to indicate that they're
// private.
ast::ItemTrait(_, _, _, _, ref methods) if item.vis != ast::Public => {
ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => {
for m in methods.iter() {
match *m {
ast::ProvidedMethod(ref m) => {
@ -328,7 +328,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
// Default methods on traits are all public so long as the trait
// is public
ast::ItemTrait(_, _, _, _, ref methods) if public_first => {
ast::ItemTrait(_, _, _, ref methods) if public_first => {
for method in methods.iter() {
match *method {
ast::ProvidedMethod(ref m) => {
@ -1178,7 +1178,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
}
}
ast::ItemTrait(_, _, _, _, ref methods) => {
ast::ItemTrait(_, _, _, ref methods) => {
for m in methods.iter() {
match *m {
ast::ProvidedMethod(ref m) => {
@ -1242,7 +1242,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
ast::ItemStruct(ref def, _) => check_struct(&**def),
ast::ItemTrait(_, _, _, _, ref methods) => {
ast::ItemTrait(_, _, _, ref methods) => {
for m in methods.iter() {
match *m {
ast::RequiredMethod(..) => {}
@ -1306,7 +1306,7 @@ impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
fn check_ty_param_bound(&self,
ty_param_bound: &ast::TyParamBound) {
if let ast::TraitTyParamBound(ref trait_ref) = *ty_param_bound {
if let ast::TraitTyParamBound(ref trait_ref, _) = *ty_param_bound {
if !self.tcx.sess.features.borrow().visible_private_types &&
self.path_is_private_type(trait_ref.trait_ref.ref_id) {
let span = trait_ref.trait_ref.path.span;
@ -1349,7 +1349,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
// namespace (the contents have their own privacies).
ast::ItemForeignMod(_) => {}
ast::ItemTrait(_, _, _, ref bounds, _) => {
ast::ItemTrait(_, _, ref bounds, _) => {
if !self.trait_is_public(item.id) {
return
}

View File

@ -105,7 +105,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
ast::ItemTy(_, ref generics) |
ast::ItemEnum(_, ref generics) |
ast::ItemStruct(_, ref generics) |
ast::ItemTrait(_, ref generics, _, _, _) |
ast::ItemTrait(_, ref generics, _, _) |
ast::ItemImpl(_, ref generics, _, _, _) => {
// These kinds of items have only early bound lifetime parameters.
let lifetimes = &generics.lifetimes;
@ -232,7 +232,9 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> {
}
}
fn visit_poly_trait_ref(&mut self, trait_ref: &ast::PolyTraitRef) {
fn visit_poly_trait_ref(&mut self, trait_ref:
&ast::PolyTraitRef,
_modifier: &ast::TraitBoundModifier) {
debug!("visit_poly_trait_ref trait_ref={}", trait_ref);
self.with(LateScope(&trait_ref.bound_lifetimes, self.scope), |old_scope, this| {

View File

@ -4740,7 +4740,7 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
match cx.map.find(id.node) {
Some(ast_map::NodeItem(item)) => {
match item.node {
ItemTrait(_, _, _, _, ref ms) => {
ItemTrait(_, _, _, ref ms) => {
let (_, p) =
ast_util::split_trait_methods(ms[]);
p.iter()

View File

@ -26,7 +26,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsiOS => {
@ -34,7 +34,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsWindows => {
@ -42,7 +42,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsLinux => {
@ -50,7 +50,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsAndroid => {
@ -58,7 +58,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsFreebsd | abi::OsDragonfly => {
@ -66,7 +66,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
},

View File

@ -21,7 +21,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsiOS => {
@ -29,7 +29,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsWindows => {
@ -37,7 +37,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsLinux => {
@ -45,7 +45,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsAndroid => {
@ -53,7 +53,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsFreebsd | abi::OsDragonfly => {
@ -61,7 +61,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
},

View File

@ -21,7 +21,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsiOS => {
@ -29,7 +29,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsWindows => {
@ -37,7 +37,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsLinux => {
@ -45,7 +45,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsAndroid => {
@ -53,7 +53,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
abi::OsFreebsd | abi::OsDragonfly => {
@ -61,7 +61,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string()
-a:0:64-n32".to_string()
}
},

View File

@ -16,7 +16,7 @@ pub fn target() -> Target {
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string(),
-a:0:64-n32".to_string(),
llvm_target: "arm-apple-ios".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),

View File

@ -24,7 +24,7 @@ pub fn target() -> Target {
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string(),
-a:0:64-n32".to_string(),
llvm_target: "arm-linux-androideabi".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),

View File

@ -17,7 +17,7 @@ pub fn target() -> Target {
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string(),
-a:0:64-n32".to_string(),
llvm_target: "arm-unknown-linux-gnueabi".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),

View File

@ -17,7 +17,7 @@ pub fn target() -> Target {
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string(),
-a:0:64-n32".to_string(),
llvm_target: "arm-unknown-linux-gnueabihf".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),

View File

@ -15,7 +15,7 @@ pub fn target() -> Target {
data_layout: "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\
-i32:32:32-i64:32:64\
-f32:32:32-f64:32:64-v64:64:64\
-v128:128:128-a0:0:64-f80:128:128\
-v128:128:128-a:0:64-f80:128:128\
-n8:16:32".to_string(),
llvm_target: "i386-apple-ios".to_string(),
target_endian: "little".to_string(),

View File

@ -18,7 +18,7 @@ pub fn target() -> Target {
data_layout: "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\
-i32:32:32-i64:32:64\
-f32:32:32-f64:32:64-v64:64:64\
-v128:128:128-a0:0:64-f80:128:128\
-v128:128:128-a:0:64-f80:128:128\
-n8:16:32".to_string(),
llvm_target: "i686-apple-darwin".to_string(),
target_endian: "little".to_string(),

View File

@ -16,7 +16,7 @@ pub fn target() -> Target {
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string(),
-a:0:64-n32".to_string(),
llvm_target: "mips-unknown-linux-gnu".to_string(),
target_endian: "big".to_string(),
target_word_size: "32".to_string(),

View File

@ -16,7 +16,7 @@ pub fn target() -> Target {
-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-f32:32:32-f64:64:64\
-v64:64:64-v128:64:128\
-a0:0:64-n32".to_string(),
-a:0:64-n32".to_string(),
llvm_target: "mipsel-unknown-linux-gnu".to_string(),
target_endian: "little".to_string(),
target_word_size: "32".to_string(),

View File

@ -17,7 +17,7 @@ pub fn target() -> Target {
Target {
data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64".to_string(),
llvm_target: "x86_64-apple-darwin".to_string(),
target_endian: "little".to_string(),

View File

@ -19,7 +19,7 @@ pub fn target() -> Target {
Target {
// FIXME: Test this. Copied from linux (#2398)
data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
llvm_target: "x86_64-pc-windows-gnu".to_string(),
target_endian: "little".to_string(),

View File

@ -16,7 +16,7 @@ pub fn target() -> Target {
Target {
data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
llvm_target: "x86_64-unknown-dragonfly".to_string(),
target_endian: "little".to_string(),

View File

@ -16,7 +16,7 @@ pub fn target() -> Target {
Target {
data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
llvm_target: "x86_64-unknown-freebsd".to_string(),
target_endian: "little".to_string(),

View File

@ -16,7 +16,7 @@ pub fn target() -> Target {
Target {
data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
llvm_target: "x86_64-unknown-linux-gnu".to_string(),
target_endian: "little".to_string(),

View File

@ -22,7 +22,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os)
"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\
-i32:32:32-i64:32:64\
-f32:32:32-f64:32:64-v64:64:64\
-v128:128:128-a0:0:64-f80:128:128\
-v128:128:128-a:0:64-f80:128:128\
-n8:16:32".to_string()
}
@ -30,7 +30,7 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os)
"e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16\
-i32:32:32-i64:32:64\
-f32:32:32-f64:32:64-v64:64:64\
-v128:128:128-a0:0:64-f80:128:128\
-v128:128:128-a:0:64-f80:128:128\
-n8:16:32".to_string()
}

View File

@ -19,42 +19,42 @@ pub fn get_target_strs(target_triple: String, target_os: abi::Os) -> target_strs
data_layout: match target_os {
abi::OsMacos => {
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64".to_string()
}
abi::OsiOS => {
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64".to_string()
}
abi::OsWindows => {
// FIXME: Test this. Copied from Linux (#2398)
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
}
abi::OsLinux => {
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
}
abi::OsAndroid => {
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
}
abi::OsFreebsd => {
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
}
abi::OsDragonfly => {
"e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-\
f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
s0:64:64-f80:128:128-n8:16:32:64-S128".to_string()
}

View File

@ -540,7 +540,7 @@ pub fn monitor<F:FnOnce()+Send>(f: F) {
match cfg.spawn(move || { std::io::stdio::set_stderr(box w); f() }).join() {
Ok(()) => { /* fallthrough */ }
Err(value) => {
// Task panicked without emitting a fatal diagnostic
// Thread panicked without emitting a fatal diagnostic
if !value.is::<diagnostic::FatalError>() {
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None);

View File

@ -345,9 +345,6 @@ impl Rib {
#[deriving(Show,PartialEq,Clone,Copy)]
enum Shadowable {
Always,
/// Means that the recorded import obeys the glob shadowing rules, i.e., can
/// only be shadowed by another glob import.
Glob,
Never
}
@ -462,6 +459,22 @@ impl ImportResolution {
target.unwrap().shadowable
}
fn set_target_and_id(&mut self,
namespace: Namespace,
target: Option<Target>,
id: NodeId) {
match namespace {
TypeNS => {
self.type_target = target;
self.type_id = id;
}
ValueNS => {
self.value_target = target;
self.value_id = id;
}
}
}
}
/// The link from a module up to its nearest parent node.
@ -1493,7 +1506,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ItemImpl(_, _, Some(_), _, _) => parent,
ItemTrait(_, _, _, _, ref items) => {
ItemTrait(_, _, _, ref items) => {
let name_bindings =
self.add_child(name,
parent.clone(),
@ -1719,11 +1732,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
view_path.span,
id,
is_public,
if shadowable == Shadowable::Never {
Shadowable::Glob
} else {
shadowable
});
shadowable);
}
}
}
@ -2712,64 +2721,45 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// We've successfully resolved the import. Write the results in.
let mut import_resolutions = module_.import_resolutions.borrow_mut();
let import_resolution = &mut (*import_resolutions)[target];
{
let check_and_write_import = |namespace, result: &_, used_public: &mut bool| {
let namespace_name = match namespace {
TypeNS => "type",
ValueNS => "value",
};
match value_result {
BoundResult(ref target_module, ref name_bindings) => {
debug!("(resolving single import) found value target: {}",
{ name_bindings.value_def.borrow().clone().unwrap().def });
self.check_for_conflicting_import(
&import_resolution.value_target,
directive.span,
target,
ValueNS);
match *result {
BoundResult(ref target_module, ref name_bindings) => {
debug!("(resolving single import) found {} target: {}",
namespace_name,
name_bindings.def_for_namespace(namespace));
self.check_for_conflicting_import(
&import_resolution.target_for_namespace(namespace),
directive.span,
target,
namespace);
self.check_that_import_is_importable(
&**name_bindings,
directive.span,
target,
ValueNS);
self.check_that_import_is_importable(
&**name_bindings,
directive.span,
target,
namespace);
import_resolution.value_target =
Some(Target::new(target_module.clone(),
name_bindings.clone(),
directive.shadowable));
import_resolution.value_id = directive.id;
import_resolution.is_public = directive.is_public;
value_used_public = name_bindings.defined_in_public_namespace(ValueNS);
}
UnboundResult => { /* Continue. */ }
UnknownResult => {
panic!("value result should be known at this point");
}
}
match type_result {
BoundResult(ref target_module, ref name_bindings) => {
debug!("(resolving single import) found type target: {}",
{ name_bindings.type_def.borrow().clone().unwrap().type_def });
self.check_for_conflicting_import(
&import_resolution.type_target,
directive.span,
target,
TypeNS);
self.check_that_import_is_importable(
&**name_bindings,
directive.span,
target,
TypeNS);
import_resolution.type_target =
Some(Target::new(target_module.clone(),
name_bindings.clone(),
directive.shadowable));
import_resolution.type_id = directive.id;
import_resolution.is_public = directive.is_public;
type_used_public = name_bindings.defined_in_public_namespace(TypeNS);
}
UnboundResult => { /* Continue. */ }
UnknownResult => {
panic!("type result should be known at this point");
}
let target = Some(Target::new(target_module.clone(),
name_bindings.clone(),
directive.shadowable));
import_resolution.set_target_and_id(namespace, target, directive.id);
import_resolution.is_public = directive.is_public;
*used_public = name_bindings.defined_in_public_namespace(namespace);
}
UnboundResult => { /* Continue. */ }
UnknownResult => {
panic!("{} result should be known at this point", namespace_name);
}
}
};
check_and_write_import(ValueNS, &value_result, &mut value_used_public);
check_and_write_import(TypeNS, &type_result, &mut type_used_public);
}
self.check_for_conflicts_between_imports_and_items(
@ -2825,7 +2815,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// Resolves a glob import. Note that this function cannot fail; it either
// succeeds or bails out (as importing * from an empty module or a module
// that exports nothing is valid).
// that exports nothing is valid). containing_module is the module we are
// actually importing, i.e., `foo` in `use foo::*`.
fn resolve_glob_import(&mut self,
module_: &Module,
containing_module: Rc<Module>,
@ -2851,12 +2842,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
assert_eq!(containing_module.glob_count.get(), 0);
// Add all resolved imports from the containing module.
let import_resolutions = containing_module.import_resolutions
.borrow();
let import_resolutions = containing_module.import_resolutions.borrow();
for (ident, target_import_resolution) in import_resolutions.iter() {
debug!("(resolving glob import) writing module resolution \
{} into `{}`",
target_import_resolution.type_target.is_none(),
token::get_name(*ident),
self.module_to_string(module_));
if !target_import_resolution.is_public {
@ -2876,8 +2866,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// Continue.
}
Some(ref value_target) => {
dest_import_resolution.value_target =
Some(value_target.clone());
self.check_for_conflicting_import(&dest_import_resolution.value_target,
import_directive.span,
*ident,
ValueNS);
dest_import_resolution.value_target = Some(value_target.clone());
}
}
match target_import_resolution.type_target {
@ -2885,8 +2878,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// Continue.
}
Some(ref type_target) => {
dest_import_resolution.type_target =
Some(type_target.clone());
self.check_for_conflicting_import(&dest_import_resolution.type_target,
import_directive.span,
*ident,
TypeNS);
dest_import_resolution.type_target = Some(type_target.clone());
}
}
dest_import_resolution.is_public = is_public;
@ -2908,8 +2904,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
// Add all children from the containing module.
self.populate_module_if_necessary(&containing_module);
for (&name, name_bindings) in containing_module.children
.borrow().iter() {
for (&name, name_bindings) in containing_module.children.borrow().iter() {
self.merge_import_resolution(module_,
containing_module.clone(),
import_directive,
@ -2919,8 +2914,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
// Add external module children from the containing module.
for (&name, module) in containing_module.external_module_children
.borrow().iter() {
for (&name, module) in containing_module.external_module_children.borrow().iter() {
let name_bindings =
Rc::new(Resolver::create_name_bindings_from_module(module.clone()));
self.merge_import_resolution(module_,
@ -2965,41 +2959,39 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
debug!("(resolving glob import) writing resolution `{}` in `{}` \
to `{}`",
token::get_name(name).get().to_string(),
token::get_name(name).get(),
self.module_to_string(&*containing_module),
self.module_to_string(module_));
// Merge the child item into the import resolution.
if name_bindings.defined_in_namespace_with(ValueNS, IMPORTABLE | PUBLIC) {
debug!("(resolving glob import) ... for value target");
if dest_import_resolution.shadowable(ValueNS) == Shadowable::Never {
let msg = format!("a value named `{}` has already been imported \
in this module",
token::get_name(name).get());
self.session.span_err(import_directive.span, msg.as_slice());
} else {
dest_import_resolution.value_target =
Some(Target::new(containing_module.clone(),
name_bindings.clone(),
import_directive.shadowable));
dest_import_resolution.value_id = id;
}
}
if name_bindings.defined_in_namespace_with(TypeNS, IMPORTABLE | PUBLIC) {
debug!("(resolving glob import) ... for type target");
if dest_import_resolution.shadowable(TypeNS) == Shadowable::Never {
let msg = format!("a type named `{}` has already been imported \
in this module",
token::get_name(name).get());
self.session.span_err(import_directive.span, msg.as_slice());
} else {
dest_import_resolution.type_target =
Some(Target::new(containing_module,
name_bindings.clone(),
import_directive.shadowable));
dest_import_resolution.type_id = id;
}
{
let merge_child_item = |namespace| {
if name_bindings.defined_in_namespace_with(namespace, IMPORTABLE | PUBLIC) {
let namespace_name = match namespace {
TypeNS => "type",
ValueNS => "value",
};
debug!("(resolving glob import) ... for {} target", namespace_name);
if dest_import_resolution.shadowable(namespace) == Shadowable::Never {
let msg = format!("a {} named `{}` has already been imported \
in this module",
namespace_name,
token::get_name(name).get());
self.session.span_err(import_directive.span, msg.as_slice());
} else {
let target = Target::new(containing_module.clone(),
name_bindings.clone(),
import_directive.shadowable);
dest_import_resolution.set_target_and_id(namespace,
Some(target),
id);
}
}
};
merge_child_item(ValueNS);
merge_child_item(TypeNS);
}
dest_import_resolution.is_public = is_public;
self.check_for_conflicts_between_imports_and_items(
@ -3019,6 +3011,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
return
}
debug!("check_for_conflicting_import: {}; target exists: {}",
token::get_name(name).get(),
target.is_some());
match *target {
Some(ref target) if target.shadowable != Shadowable::Always => {
let msg = format!("a {} named `{}` has already been imported \
@ -4008,6 +4004,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
/// Searches the current set of local scopes and
/// applies translations for closures.
fn search_ribs(&self,
ribs: &[Rib],
name: Name,
@ -4029,6 +4027,27 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
None
}
/// Searches the current set of local scopes for labels.
/// Stops after meeting a closure.
fn search_label(&self, name: Name) -> Option<DefLike> {
for rib in self.label_ribs.iter().rev() {
match rib.kind {
NormalRibKind => {
// Continue
}
_ => {
// Do not resolve labels across function boundary
return None
}
}
let result = rib.bindings.get(&name).cloned();
if result.is_some() {
return result
}
}
None
}
fn resolve_crate(&mut self, krate: &ast::Crate) {
debug!("(resolving crate) starting");
@ -4093,7 +4112,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
impl_items[]);
}
ItemTrait(_, ref generics, ref unbound, ref bounds, ref trait_items) => {
ItemTrait(_, ref generics, ref bounds, ref trait_items) => {
// Create a new rib for the self type.
let mut self_type_rib = Rib::new(ItemRibKind);
@ -4114,13 +4133,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
this.resolve_type_parameter_bounds(item.id, bounds,
TraitDerivation);
match *unbound {
Some(ref tpb) => {
this.resolve_trait_reference(item.id, tpb, TraitDerivation);
}
None => {}
}
for trait_item in (*trait_items).iter() {
// Create a new rib for the trait_item-specific type
// parameters.
@ -4368,12 +4380,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
self.resolve_type_parameter_bound(type_parameter.id, bound,
TraitBoundingTypeParameter);
}
match &type_parameter.unbound {
&Some(ref unbound) =>
self.resolve_trait_reference(
type_parameter.id, unbound, TraitBoundingTypeParameter),
&None => {}
}
match type_parameter.default {
Some(ref ty) => self.resolve_type(&**ty),
None => {}
@ -4395,7 +4401,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
type_parameter_bound: &TyParamBound,
reference_type: TraitReferenceType) {
match *type_parameter_bound {
TraitTyParamBound(ref tref) => {
TraitTyParamBound(ref tref, _) => {
self.resolve_poly_trait_reference(id, tref, reference_type)
}
RegionTyParamBound(..) => {}
@ -5848,8 +5854,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
ExprBreak(Some(label)) | ExprAgain(Some(label)) => {
let renamed = mtwt::resolve(label);
match self.search_ribs(self.label_ribs[],
renamed, expr.span) {
match self.search_label(renamed) {
None => {
self.resolve_error(
expr.span,

View File

@ -98,7 +98,7 @@ impl SharedEmitter {
}
fn dump(&mut self, handler: &Handler) {
let mut buffer = self.buffer.lock();
let mut buffer = self.buffer.lock().unwrap();
for diag in buffer.iter() {
match diag.code {
Some(ref code) => {
@ -123,7 +123,7 @@ impl Emitter for SharedEmitter {
msg: &str, code: Option<&str>, lvl: Level) {
assert!(cmsp.is_none(), "SharedEmitter doesn't support spans");
self.buffer.lock().push(Diagnostic {
self.buffer.lock().unwrap().push(Diagnostic {
msg: msg.to_string(),
code: code.map(|s| s.to_string()),
lvl: lvl,
@ -915,7 +915,7 @@ fn run_work_multithreaded(sess: &Session,
loop {
// Avoid holding the lock for the entire duration of the match.
let maybe_work = work_items_arc.lock().pop();
let maybe_work = work_items_arc.lock().unwrap().pop();
match maybe_work {
Some(work) => {
execute_work_item(&cgcx, work);

View File

@ -636,7 +636,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
item.id);
for field in struct_def.fields.iter() {
self.process_struct_field_def(field, enum_name[], variant.node.id);
self.process_struct_field_def(field, qualname[], variant.node.id);
self.visit_ty(&*field.node.ty);
}
}
@ -710,7 +710,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
// super-traits
for super_bound in trait_refs.iter() {
let trait_ref = match *super_bound {
ast::TraitTyParamBound(ref trait_ref) => {
ast::TraitTyParamBound(ref trait_ref, _) => {
trait_ref
}
ast::RegionTyParamBound(..) => {
@ -763,37 +763,38 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
}
fn process_path(&mut self,
ex: &ast::Expr,
path: &ast::Path) {
id: NodeId,
span: Span,
path: &ast::Path,
ref_kind: Option<recorder::Row>) {
if generated_code(path.span) {
return
}
let def_map = self.analysis.ty_cx.def_map.borrow();
if !def_map.contains_key(&ex.id) {
self.sess.span_bug(ex.span,
format!("def_map has no key for {} in visit_expr",
ex.id)[]);
if !def_map.contains_key(&id) {
self.sess.span_bug(span,
format!("def_map has no key for {} in visit_expr", id)[]);
}
let def = &(*def_map)[ex.id];
let sub_span = self.span.span_for_last_ident(ex.span);
let def = &(*def_map)[id];
let sub_span = self.span.span_for_last_ident(span);
match *def {
def::DefUpvar(..) |
def::DefLocal(..) |
def::DefStatic(..) |
def::DefConst(..) |
def::DefVariant(..) => self.fmt.ref_str(recorder::VarRef,
ex.span,
def::DefVariant(..) => self.fmt.ref_str(ref_kind.unwrap_or(recorder::VarRef),
span,
sub_span,
def.def_id(),
self.cur_scope),
def::DefStruct(def_id) => self.fmt.ref_str(recorder::StructRef,
ex.span,
span,
sub_span,
def_id,
self.cur_scope),
self.cur_scope),
def::DefStaticMethod(declid, provenence) => {
let sub_span = self.span.sub_span_for_meth_name(ex.span);
let sub_span = self.span.sub_span_for_meth_name(span);
let defid = if declid.krate == ast::LOCAL_CRATE {
let ti = ty::impl_or_trait_item(&self.analysis.ty_cx,
declid);
@ -828,34 +829,31 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
} else {
None
};
self.fmt.meth_call_str(ex.span,
self.fmt.meth_call_str(span,
sub_span,
defid,
Some(declid),
self.cur_scope);
},
def::DefFn(def_id, _) => self.fmt.fn_call_str(ex.span,
sub_span,
def_id,
self.cur_scope),
_ => self.sess.span_bug(ex.span,
def::DefFn(def_id, _) => self.fmt.fn_call_str(span,
sub_span,
def_id,
self.cur_scope),
_ => self.sess.span_bug(span,
format!("Unexpected def kind while looking up path in '{}'",
self.span.snippet(ex.span))[]),
self.span.snippet(span))[]),
}
// modules or types in the path prefix
match *def {
def::DefStaticMethod(..) => {
self.write_sub_path_trait_truncated(path);
},
def::DefStaticMethod(..) => self.write_sub_path_trait_truncated(path),
def::DefLocal(_) |
def::DefStatic(_,_) |
def::DefConst(..) |
def::DefStruct(_) |
def::DefVariant(..) |
def::DefFn(..) => self.write_sub_paths_truncated(path),
_ => {},
}
visit::walk_path(self, path);
}
fn process_struct_lit(&mut self,
@ -982,18 +980,19 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> {
}
};
for &Spanned { node: ref field, span } in fields.iter() {
self.visit_pat(&*field.pat);
let sub_span = self.span.span_for_first_ident(span);
let fields = ty::lookup_struct_fields(&self.analysis.ty_cx, struct_def);
for f in fields.iter() {
if f.name == field.ident.name {
self.fmt.ref_str(recorder::VarRef,
p.span,
Some(span),
span,
sub_span,
f.id,
self.cur_scope);
break;
}
}
self.visit_pat(&*field.pat);
}
}
ast::PatEnum(ref path, _) => {
@ -1052,7 +1051,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
&**typ,
impl_items)
}
ast::ItemTrait(_, ref generics, _, ref trait_refs, ref methods) =>
ast::ItemTrait(_, ref generics, ref trait_refs, ref methods) =>
self.process_trait(item, generics, trait_refs, methods),
ast::ItemMod(ref m) => self.process_mod(item, m),
ast::ItemTy(ref ty, ref ty_params) => {
@ -1076,7 +1075,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
fn visit_generics(&mut self, generics: &ast::Generics) {
for param in generics.ty_params.iter() {
for bound in param.bounds.iter() {
if let ast::TraitTyParamBound(ref trait_ref) = *bound {
if let ast::TraitTyParamBound(ref trait_ref, _) = *bound {
self.process_trait_ref(&trait_ref.trait_ref, None);
}
}
@ -1162,8 +1161,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
}
match i.node {
ast::ViewItemUse(ref path) => {
match path.node {
ast::ViewItemUse(ref item) => {
match item.node {
ast::ViewPathSimple(ident, ref path, id) => {
let sub_span = self.span.span_for_last_ident(path.span);
let mod_id = match self.lookup_type_ref(id) {
@ -1184,7 +1183,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
// 'use' always introduces an alias, if there is not an explicit
// one, there is an implicit one.
let sub_span =
match self.span.sub_span_before_token(path.span, token::Eq) {
match self.span.sub_span_after_keyword(item.span, keywords::As) {
Some(sub_span) => Some(sub_span),
None => sub_span,
};
@ -1308,7 +1307,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
// because just walking the callee path does what we want.
visit::walk_expr(self, ex);
},
ast::ExprPath(ref path) => self.process_path(ex, path),
ast::ExprPath(ref path) => {
self.process_path(ex.id, ex.span, path, None);
visit::walk_path(self, path);
}
ast::ExprStruct(ref path, ref fields, ref base) =>
self.process_struct_lit(ex, path, fields, base),
ast::ExprMethodCall(_, _, ref args) => self.process_method_call(ex, args),
@ -1405,46 +1407,50 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> {
fn visit_arm(&mut self, arm: &ast::Arm) {
assert!(self.collected_paths.len() == 0 && !self.collecting);
self.collecting = true;
for pattern in arm.pats.iter() {
// collect paths from the arm's patterns
self.visit_pat(&**pattern);
}
self.collecting = false;
// This is to get around borrow checking, because we need mut self to call process_path.
let mut paths_to_process = vec![];
// process collected paths
for &(id, ref p, ref immut, ref_kind) in self.collected_paths.iter() {
let value = if *immut {
self.span.snippet(p.span).to_string()
} else {
"<mutable>".to_string()
};
let sub_span = self.span.span_for_first_ident(p.span);
let def_map = self.analysis.ty_cx.def_map.borrow();
if !def_map.contains_key(&id) {
self.sess.span_bug(p.span,
format!("def_map has no key for {} in visit_arm",
id)[]);
format!("def_map has no key for {} in visit_arm", id)[]);
}
let def = &(*def_map)[id];
match *def {
def::DefLocal(id) => self.fmt.variable_str(p.span,
sub_span,
id,
path_to_string(p)[],
value[],
""),
def::DefVariant(_,id,_) => self.fmt.ref_str(ref_kind,
p.span,
sub_span,
id,
self.cur_scope),
// FIXME(nrc) what is this doing here?
def::DefLocal(id) => {
let value = if *immut {
self.span.snippet(p.span).to_string()
} else {
"<mutable>".to_string()
};
assert!(p.segments.len() == 1, "qualified path for local variable def in arm");
self.fmt.variable_str(p.span,
Some(p.span),
id,
path_to_string(p)[],
value[],
"")
}
def::DefVariant(..) => {
paths_to_process.push((id, p.span, p.clone(), Some(ref_kind)))
}
// FIXME(nrc) what are these doing here?
def::DefStatic(_, _) => {}
def::DefConst(..) => {}
_ => error!("unexpected definition kind when processing collected paths: {}",
*def)
_ => error!("unexpected definition kind when processing collected paths: {}", *def)
}
}
for &(id, span, ref path, ref_kind) in paths_to_process.iter() {
self.process_path(id, span, path, ref_kind);
}
self.collecting = false;
self.collected_paths.clear();
visit::walk_expr_opt(self, &arm.guard);
self.visit_expr(&*arm.body);

View File

@ -61,7 +61,7 @@ macro_rules! svec {
})
}
#[deriving(Copy)]
#[deriving(Copy,Show)]
pub enum Row {
Variable,
Enum,

View File

@ -294,8 +294,8 @@ impl<'a> SpanUtils<'a> {
}
pub fn sub_span_after_keyword(&self,
span: Span,
keyword: keywords::Keyword) -> Option<Span> {
span: Span,
keyword: keywords::Keyword) -> Option<Span> {
let mut toks = self.retokenise_span(span);
loop {
let ts = toks.real_token();

View File

@ -983,23 +983,14 @@ pub fn invoke<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
llfn: ValueRef,
llargs: &[ValueRef],
fn_ty: Ty<'tcx>,
call_info: Option<NodeInfo>,
// FIXME(15064) is_lang_item is a horrible hack, please remove it
// at the soonest opportunity.
is_lang_item: bool)
call_info: Option<NodeInfo>)
-> (ValueRef, Block<'blk, 'tcx>) {
let _icx = push_ctxt("invoke_");
if bcx.unreachable.get() {
return (C_null(Type::i8(bcx.ccx())), bcx);
}
// FIXME(15064) Lang item methods may (in the reflect case) not have proper
// types, so doing an attribute lookup will fail.
let attributes = if is_lang_item {
llvm::AttrBuilder::new()
} else {
get_fn_llvm_attributes(bcx.ccx(), fn_ty)
};
let attributes = get_fn_llvm_attributes(bcx.ccx(), fn_ty);
match bcx.opt_node_id {
None => {
@ -1554,8 +1545,7 @@ pub fn arg_kind<'a, 'tcx>(cx: &FunctionContext<'a, 'tcx>, t: Ty<'tcx>)
}
// work around bizarre resolve errors
pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
pub type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>;
type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
// create_datums_for_fn_args: creates rvalue datums for each of the
// incoming function arguments. These will later be stored into

View File

@ -501,7 +501,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
debug!("Store {} -> {}",
self.ccx.tn().val_to_string(val),
self.ccx.tn().val_to_string(ptr));
assert!(self.llbuilder.is_not_null());
assert!(!self.llbuilder.is_null());
self.count_insn("store");
unsafe {
llvm::LLVMBuildStore(self.llbuilder, val, ptr);
@ -512,7 +512,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
debug!("Store {} -> {}",
self.ccx.tn().val_to_string(val),
self.ccx.tn().val_to_string(ptr));
assert!(self.llbuilder.is_not_null());
assert!(!self.llbuilder.is_null());
self.count_insn("store.volatile");
unsafe {
let insn = llvm::LLVMBuildStore(self.llbuilder, val, ptr);

View File

@ -779,8 +779,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
llfn,
llargs[],
callee_ty,
call_info,
dest.is_none());
call_info);
bcx = b;
llresult = llret;

View File

@ -190,8 +190,8 @@ pub fn validate_substs(substs: &Substs) {
}
// work around bizarre resolve errors
pub type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
pub type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>;
type RvalueDatum<'tcx> = datum::Datum<'tcx, datum::Rvalue>;
type LvalueDatum<'tcx> = datum::Datum<'tcx, datum::Lvalue>;
// Function context. Every LLVM function we create will have one of
// these.

View File

@ -292,7 +292,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
class_did,
&[get_drop_glue_type(bcx.ccx(), t)],
ty::mk_nil(bcx.tcx()));
let (_, variant_cx) = invoke(variant_cx, dtor_addr, args[], dtor_ty, None, false);
let (_, variant_cx) = invoke(variant_cx, dtor_addr, args[], dtor_ty, None);
variant_cx.fcx.pop_and_trans_custom_cleanup_scope(variant_cx, field_scope);
variant_cx

View File

@ -20,7 +20,7 @@ pub struct Value(pub ValueRef);
macro_rules! opt_val { ($e:expr) => (
unsafe {
match $e {
p if p.is_not_null() => Some(Value(p)),
p if !p.is_null() => Some(Value(p)),
_ => None
}
}
@ -37,7 +37,7 @@ impl Value {
pub fn get_parent(self) -> Option<BasicBlock> {
unsafe {
match llvm::LLVMGetInstructionParent(self.get()) {
p if p.is_not_null() => Some(BasicBlock(p)),
p if !p.is_null() => Some(BasicBlock(p)),
_ => None
}
}
@ -77,7 +77,7 @@ impl Value {
pub fn get_first_use(self) -> Option<Use> {
unsafe {
match llvm::LLVMGetFirstUse(self.get()) {
u if u.is_not_null() => Some(Use(u)),
u if !u.is_null() => Some(Use(u)),
_ => None
}
}
@ -119,7 +119,7 @@ impl Value {
/// Tests if this value is a terminator instruction
pub fn is_a_terminator_inst(self) -> bool {
unsafe {
llvm::LLVMIsATerminatorInst(self.get()).is_not_null()
!llvm::LLVMIsATerminatorInst(self.get()).is_null()
}
}
}
@ -142,7 +142,7 @@ impl Use {
pub fn get_next_use(self) -> Option<Use> {
unsafe {
match llvm::LLVMGetNextUse(self.get()) {
u if u.is_not_null() => Some(Use(u)),
u if !u.is_null() => Some(Use(u)),
_ => None
}
}

View File

@ -164,10 +164,16 @@ pub fn opt_ast_region_to_region<'tcx, AC: AstConv<'tcx>, RS: RegionScope>(
let mut m = String::new();
let len = v.len();
for (i, (name, n)) in v.into_iter().enumerate() {
m.push_str(if n == 1 {
format!("`{}`", name)
let help_name = if name.is_empty() {
format!("argument {}", i + 1)
} else {
format!("one of `{}`'s {} elided lifetimes", name, n)
format!("`{}`", name)
};
m.push_str(if n == 1 {
help_name
} else {
format!("one of {}'s {} elided lifetimes", help_name, n)
}[]);
if len == 2 && i == 0 {
@ -1626,7 +1632,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
let mut trait_def_ids = DefIdMap::new();
for ast_bound in ast_bounds.iter() {
match *ast_bound {
ast::TraitTyParamBound(ref b) => {
ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => {
match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
def::DefTrait(trait_did) => {
match trait_def_ids.get(&trait_did) {
@ -1664,6 +1670,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
}
trait_bounds.push(b);
}
ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) => {}
ast::RegionTyParamBound(ref l) => {
region_bounds.push(l);
}

View File

@ -673,7 +673,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
}
}
ast::ItemTrait(_, _, _, _, ref trait_methods) => {
ast::ItemTrait(_, _, _, ref trait_methods) => {
let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
for trait_method in trait_methods.iter() {
match *trait_method {

View File

@ -259,7 +259,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
trait_def: &ty::TraitDef<'tcx>) {
let tcx = ccx.tcx;
if let ast_map::NodeItem(item) = tcx.map.get(trait_id) {
if let ast::ItemTrait(_, _, _, _, ref trait_items) = item.node {
if let ast::ItemTrait(_, _, _, ref trait_items) = item.node {
// For each method, construct a suitable ty::Method and
// store it into the `tcx.impl_or_trait_items` table:
for trait_item in trait_items.iter() {
@ -627,11 +627,6 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
ast::RegionTyParamBound(..) => { }
}
}
match ty_param.unbound {
Some(_) => { warn = true; }
None => { }
}
}
if warn {
@ -1146,7 +1141,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) {
AllowEqConstraints::DontAllow);
}
},
ast::ItemTrait(_, _, _, _, ref trait_methods) => {
ast::ItemTrait(_, _, _, ref trait_methods) => {
let trait_def = trait_def_of_item(ccx, it);
debug!("trait_def: ident={} trait_def={}",
@ -1338,13 +1333,12 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
return def.clone();
}
let (unsafety, generics, unbound, bounds, items) = match it.node {
let (unsafety, generics, bounds, items) = match it.node {
ast::ItemTrait(unsafety,
ref generics,
ref unbound,
ref supertraits,
ref items) => {
(unsafety, generics, unbound, supertraits, items.as_slice())
(unsafety, generics, supertraits, items.as_slice())
}
ref s => {
tcx.sess.span_bug(
@ -1367,7 +1361,6 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
token::SELF_KEYWORD_NAME,
self_param_ty,
bounds.as_slice(),
unbound,
it.span);
let substs = mk_item_substs(ccx, &ty_generics);
@ -1683,29 +1676,37 @@ fn ty_generics_for_fn_or_method<'tcx,AC>(
create_type_parameters_for_associated_types)
}
// Add the Sized bound, unless the type parameter is marked as `Sized?`.
// Add the Sized bound, unless the type parameter is marked as `?Sized`.
fn add_unsized_bound<'tcx,AC>(this: &AC,
unbound: &Option<ast::TraitRef>,
bounds: &mut ty::BuiltinBounds,
desc: &str,
ast_bounds: &[ast::TyParamBound],
span: Span)
where AC: AstConv<'tcx> {
// Try to find an unbound in bounds.
let mut unbound = None;
for ab in ast_bounds.iter() {
if let &ast::TraitTyParamBound(ref ptr, ast::TraitBoundModifier::Maybe) = ab {
if unbound.is_none() {
assert!(ptr.bound_lifetimes.is_empty());
unbound = Some(ptr.trait_ref.clone());
} else {
this.tcx().sess.span_err(span, "type parameter has more than one relaxed default \
bound, only one is supported");
}
}
}
let kind_id = this.tcx().lang_items.require(SizedTraitLangItem);
match unbound {
&Some(ref tpb) => {
Some(ref tpb) => {
// FIXME(#8559) currently requires the unbound to be built-in.
let trait_def_id = ty::trait_ref_to_def_id(this.tcx(), tpb);
match kind_id {
Ok(kind_id) if trait_def_id != kind_id => {
this.tcx().sess.span_warn(span,
format!("default bound relaxed \
for a {}, but this \
does nothing because \
the given bound is not \
a default. \
Only `Sized?` is \
supported",
desc)[]);
"default bound relaxed for a type parameter, but \
this does nothing because the given bound is not \
a default. Only `?Sized` is supported");
ty::try_add_builtin_trait(this.tcx(),
kind_id,
bounds);
@ -1717,7 +1718,7 @@ fn add_unsized_bound<'tcx,AC>(this: &AC,
ty::try_add_builtin_trait(this.tcx(), kind_id.unwrap(), bounds);
}
// No lang item for Sized, so we can't add it as a bound.
&None => {}
None => {}
}
}
@ -1807,7 +1808,7 @@ fn ty_generics<'tcx,AC>(this: &AC,
for bound in bound_pred.bounds.iter() {
match bound {
&ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref) => {
&ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
let trait_ref = astconv::instantiate_poly_trait_ref(
this,
&ExplicitRscope,
@ -1880,7 +1881,7 @@ fn ty_generics<'tcx,AC>(this: &AC,
for bound in param.bounds.iter() {
// In the above example, `ast_trait_ref` is `Iterator`.
let ast_trait_ref = match *bound {
ast::TraitTyParamBound(ref r) => r,
ast::TraitTyParamBound(ref r, _) => r,
ast::RegionTyParamBound(..) => { continue; }
};
@ -1978,7 +1979,6 @@ fn get_or_create_type_parameter_def<'tcx,AC>(this: &AC,
param.ident.name,
param_ty,
param.bounds[],
&param.unbound,
param.span);
let default = match param.default {
None => None,
@ -2023,7 +2023,6 @@ fn compute_bounds<'tcx,AC>(this: &AC,
name_of_bounded_thing: ast::Name,
param_ty: ty::ParamTy,
ast_bounds: &[ast::TyParamBound],
unbound: &Option<ast::TraitRef>,
span: Span)
-> ty::ParamBounds<'tcx>
where AC: AstConv<'tcx> {
@ -2032,11 +2031,9 @@ fn compute_bounds<'tcx,AC>(this: &AC,
param_ty,
ast_bounds);
add_unsized_bound(this,
unbound,
&mut param_bounds.builtin_bounds,
"type parameter",
ast_bounds,
span);
check_bounds_compatible(this.tcx(),

View File

@ -353,7 +353,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> {
match item.node {
ast::ItemEnum(_, ref generics) |
ast::ItemStruct(_, ref generics) |
ast::ItemTrait(_, ref generics, _, _, _) => {
ast::ItemTrait(_, ref generics, _, _) => {
for (i, p) in generics.lifetimes.iter().enumerate() {
let id = p.lifetime.id;
self.add_inferred(item.id, RegionParam, TypeSpace, i, id);

View File

@ -163,13 +163,12 @@ pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt,
}
});
let trait_def = ty::lookup_trait_def(tcx, did);
let (bounds, default_unbound) = trait_def.bounds.clean(cx);
let bounds = trait_def.bounds.clean(cx);
clean::Trait {
unsafety: def.unsafety,
generics: (&def.generics, subst::TypeSpace).clean(cx),
items: items.collect(),
bounds: bounds,
default_unbound: default_unbound
}
}
@ -328,7 +327,7 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
derived: clean::detect_derived(attrs.as_slice()),
trait_: associated_trait.clean(cx).map(|bound| {
match bound {
clean::TraitBound(polyt) => polyt.trait_,
clean::TraitBound(polyt, _) => polyt.trait_,
clean::RegionBound(..) => unreachable!(),
}
}),

View File

@ -458,8 +458,6 @@ pub struct TyParam {
pub did: ast::DefId,
pub bounds: Vec<TyParamBound>,
pub default: Option<Type>,
/// An optional default bound on the parameter which is unbound, like `Sized?`
pub default_unbound: Option<Type>
}
impl Clean<TyParam> for ast::TyParam {
@ -469,7 +467,6 @@ impl Clean<TyParam> for ast::TyParam {
did: ast::DefId { krate: ast::LOCAL_CRATE, node: self.id },
bounds: self.bounds.clean(cx),
default: self.default.clean(cx),
default_unbound: self.unbound.clean(cx)
}
}
}
@ -478,13 +475,12 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
fn clean(&self, cx: &DocContext) -> TyParam {
cx.external_typarams.borrow_mut().as_mut().unwrap()
.insert(self.def_id, self.name.clean(cx));
let (bounds, default_unbound) = self.bounds.clean(cx);
let bounds = self.bounds.clean(cx);
TyParam {
name: self.name.clean(cx),
did: self.def_id,
bounds: bounds,
default: self.default.clean(cx),
default_unbound: default_unbound
}
}
}
@ -492,14 +488,14 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
#[deriving(Clone, RustcEncodable, RustcDecodable, PartialEq)]
pub enum TyParamBound {
RegionBound(Lifetime),
TraitBound(PolyTrait)
TraitBound(PolyTrait, ast::TraitBoundModifier)
}
impl Clean<TyParamBound> for ast::TyParamBound {
fn clean(&self, cx: &DocContext) -> TyParamBound {
match *self {
ast::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)),
ast::TraitTyParamBound(ref t) => TraitBound(t.clean(cx)),
ast::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier),
}
}
}
@ -600,7 +596,7 @@ impl Clean<TyParamBound> for ty::BuiltinBound {
did: did,
},
lifetimes: vec![]
})
}, ast::TraitBoundModifier::None)
}
}
@ -648,37 +644,20 @@ impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
TraitBound(PolyTrait {
trait_: ResolvedPath { path: path, typarams: None, did: self.def_id, },
lifetimes: late_bounds
})
}, ast::TraitBoundModifier::None)
}
}
// Returns (bounds, default_unbound)
impl<'tcx> Clean<(Vec<TyParamBound>, Option<Type>)> for ty::ParamBounds<'tcx> {
fn clean(&self, cx: &DocContext) -> (Vec<TyParamBound>, Option<Type>) {
impl<'tcx> Clean<Vec<TyParamBound>> for ty::ParamBounds<'tcx> {
fn clean(&self, cx: &DocContext) -> Vec<TyParamBound> {
let mut v = Vec::new();
let mut has_sized_bound = false;
for b in self.builtin_bounds.iter() {
if b != ty::BoundSized {
v.push(b.clean(cx));
} else {
has_sized_bound = true;
}
}
for t in self.trait_bounds.iter() {
v.push(t.clean(cx));
}
for r in self.region_bounds.iter().filter_map(|r| r.clean(cx)) {
v.push(RegionBound(r));
}
if has_sized_bound {
(v, None)
} else {
let ty = match ty::BoundSized.clean(cx) {
TraitBound(polyt) => polyt.trait_,
_ => unreachable!()
};
(v, Some(ty))
}
v
}
}
@ -689,7 +668,7 @@ impl<'tcx> Clean<Option<Vec<TyParamBound>>> for subst::Substs<'tcx> {
v.extend(self.types.iter().map(|t| TraitBound(PolyTrait {
trait_: t.clean(cx),
lifetimes: vec![]
})));
}, ast::TraitBoundModifier::None)));
if v.len() > 0 {Some(v)} else {None}
}
}
@ -1047,8 +1026,6 @@ pub struct Trait {
pub items: Vec<TraitMethod>,
pub generics: Generics,
pub bounds: Vec<TyParamBound>,
/// An optional default bound not required for `Self`, like `Sized?`
pub default_unbound: Option<Type>
}
impl Clean<Item> for doctree::Trait {
@ -1065,7 +1042,6 @@ impl Clean<Item> for doctree::Trait {
items: self.items.clean(cx),
generics: self.generics.clean(cx),
bounds: self.bounds.clean(cx),
default_unbound: self.default_unbound.clean(cx)
}),
}
}
@ -2412,7 +2388,6 @@ impl Clean<Item> for ty::AssociatedType {
},
bounds: vec![],
default: None,
default_unbound: None
}),
visibility: None,
def_id: self.def_id,

View File

@ -178,7 +178,6 @@ pub struct Trait {
pub whence: Span,
pub vis: ast::Visibility,
pub stab: Option<attr::Stability>,
pub default_unbound: Option<ast::TraitRef> // FIXME(tomjakubowski)
}
pub struct Impl {

View File

@ -97,9 +97,6 @@ impl fmt::Show for clean::Generics {
if i > 0 {
try!(f.write(", ".as_bytes()))
}
if let Some(ref unbound) = tp.default_unbound {
try!(write!(f, "{}? ", unbound));
};
try!(f.write(tp.name.as_bytes()));
if tp.bounds.len() > 0 {
@ -123,7 +120,7 @@ impl<'a> fmt::Show for WhereClause<'a> {
if gens.where_predicates.len() == 0 {
return Ok(());
}
try!(f.write(" where ".as_bytes()));
try!(f.write(" <span class='where'>where ".as_bytes()));
for (i, pred) in gens.where_predicates.iter().enumerate() {
if i > 0 {
try!(f.write(", ".as_bytes()));
@ -149,6 +146,7 @@ impl<'a> fmt::Show for WhereClause<'a> {
}
}
}
try!(f.write("</span>".as_bytes()));
Ok(())
}
}
@ -182,8 +180,12 @@ impl fmt::Show for clean::TyParamBound {
clean::RegionBound(ref lt) => {
write!(f, "{}", *lt)
}
clean::TraitBound(ref ty) => {
write!(f, "{}", *ty)
clean::TraitBound(ref ty, modifier) => {
let modifier_str = match modifier {
ast::TraitBoundModifier::None => "",
ast::TraitBoundModifier::Maybe => "?",
};
write!(f, "{}{}", modifier_str, *ty)
}
}
}
@ -458,12 +460,15 @@ impl fmt::Show for clean::Type {
for bound in decl.bounds.iter() {
match *bound {
clean::RegionBound(..) => {}
clean::TraitBound(ref t) => {
clean::TraitBound(ref t, modifier) => {
if ret.len() == 0 {
ret.push_str(": ");
} else {
ret.push_str(" + ");
}
if modifier == ast::TraitBoundModifier::Maybe {
ret.push_str("?");
}
ret.push_str(format!("{}",
*t).as_slice());
}

View File

@ -1679,9 +1679,6 @@ fn item_function(w: &mut fmt::Formatter, it: &clean::Item,
fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
t: &clean::Trait) -> fmt::Result {
let mut bounds = String::new();
if let Some(ref ty) = t.default_unbound {
bounds.push_str(format!(" for {}?", ty).as_slice());
}
if t.bounds.len() > 0 {
if bounds.len() > 0 {
bounds.push(' ');

View File

@ -306,6 +306,11 @@ nav.sub {
font-size: 1em;
position: relative;
}
/* Shift "where ..." part of method definition down a line */
.content .method .where { display: block; }
/* Bit of whitespace to indent it */
.content .method .where::before { content: ' '; }
.content .methods .docblock { margin-left: 40px; }
.content .impl-items .docblock { margin-left: 40px; }

View File

@ -322,7 +322,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
};
om.constants.push(s);
},
ast::ItemTrait(unsafety, ref gen, ref def_ub, ref b, ref items) => {
ast::ItemTrait(unsafety, ref gen, ref b, ref items) => {
let t = Trait {
unsafety: unsafety,
name: name,
@ -334,7 +334,6 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
whence: item.span,
vis: item.vis,
stab: self.stability(item.id),
default_unbound: def_ub.clone()
};
om.traits.push(t);
},

View File

@ -392,10 +392,10 @@ mod tests {
#[test]
fn test_base64_random() {
use std::rand::{task_rng, random, Rng};
use std::rand::{thread_rng, random, Rng};
for _ in range(0u, 1000) {
let times = task_rng().gen_range(1u, 100);
let times = thread_rng().gen_range(1u, 100);
let v = Vec::from_fn(times, |_| random::<u8>());
assert_eq!(v.to_base64(STANDARD)
.from_base64()

View File

@ -29,7 +29,7 @@
//! * `String`: equivalent to rust's `String`
//! * `Array`: equivalent to rust's `Vec<T>`, but also allowing objects of different types in the
//! same array
//! * `Object`: equivalent to rust's `Treemap<String, json::Json>`
//! * `Object`: equivalent to rust's `BTreeMap<String, json::Json>`
//! * `Null`
//!
//! An object is a series of string keys mapping to values, in `"key": value` format.
@ -2517,7 +2517,7 @@ mod tests {
#[test]
fn test_from_str_trait() {
let s = "null";
assert!(::std::str::from_str::<Json>(s).unwrap() == from_str(s).unwrap());
assert!(s.parse::<Json>().unwrap() == s.parse().unwrap());
}
#[test]
@ -3729,8 +3729,8 @@ mod tests {
let array3 = Array(vec!(U64(1), U64(2), U64(3)));
let object = {
let mut tree_map = BTreeMap::new();
tree_map.insert("a".into_string(), U64(1));
tree_map.insert("b".into_string(), U64(2));
tree_map.insert("a".to_string(), U64(1));
tree_map.insert("b".to_string(), U64(2));
Object(tree_map)
};
@ -3762,8 +3762,8 @@ mod tests {
assert_eq!((vec![1u, 2]).to_json(), array2);
assert_eq!(vec!(1u, 2, 3).to_json(), array3);
let mut tree_map = BTreeMap::new();
tree_map.insert("a".into_string(), 1u);
tree_map.insert("b".into_string(), 2);
tree_map.insert("a".to_string(), 1u);
tree_map.insert("b".to_string(), 2);
assert_eq!(tree_map.to_json(), object);
let mut hash_map = HashMap::new();
hash_map.insert("a".to_string(), 1u);

View File

@ -104,6 +104,10 @@
/// - `empty`: an empty set of flags
/// - `all`: the set of all flags
/// - `bits`: the raw value of the flags currently stored
/// - `from_bits`: convert from underlying bit representation, unless that
/// representation contains bits that do not correspond to a flag
/// - `from_bits_truncate`: convert from underlying bit representation, dropping
/// any bits that do not correspond to flags
/// - `is_empty`: `true` if no flags are currently stored
/// - `is_all`: `true` if all flags are currently set
/// - `intersects`: `true` if there are flags common to both `self` and `other`

View File

@ -537,7 +537,8 @@ pub unsafe fn from_c_multistring<F>(buf: *const libc::c_char,
#[cfg(test)]
mod tests {
use super::*;
use prelude::*;
use prelude::{spawn, Some, None, Option, FnOnce, ToString, CloneSliceExt};
use prelude::{Clone, PtrExt, Iterator, SliceExt, StrExt};
use ptr;
use thread::Thread;
use libc;

View File

@ -40,7 +40,7 @@ use mem;
use ops::{Drop, FnOnce};
use option::Option;
use option::Option::{Some, None};
use ptr::RawPtr;
use ptr::PtrExt;
use ptr;
use raw;
use slice::AsSlice;

View File

@ -264,27 +264,35 @@ fn test_resize_policy() {
/// }
/// ```
///
/// The easiest way to use `HashMap` with a custom type is to derive `Eq` and `Hash`.
/// The easiest way to use `HashMap` with a custom type as key is to derive `Eq` and `Hash`.
/// We must also derive `PartialEq`.
///
/// ```
/// use std::collections::HashMap;
///
/// #[deriving(Hash, Eq, PartialEq, Show)]
/// struct Viking<'a> {
/// name: &'a str,
/// power: uint,
/// struct Viking {
/// name: String,
/// country: String,
/// }
///
/// impl Viking {
/// /// Create a new Viking.
/// fn new(name: &str, country: &str) -> Viking {
/// Viking { name: name.to_string(), country: country.to_string() }
/// }
/// }
///
/// // Use a HashMap to store the vikings' health points.
/// let mut vikings = HashMap::new();
///
/// vikings.insert("Norway", Viking { name: "Einar", power: 9u });
/// vikings.insert("Denmark", Viking { name: "Olaf", power: 4u });
/// vikings.insert("Iceland", Viking { name: "Harald", power: 8u });
/// vikings.insert(Viking::new("Einar", "Norway"), 25u);
/// vikings.insert(Viking::new("Olaf", "Denmark"), 24u);
/// vikings.insert(Viking::new("Harald", "Iceland"), 12u);
///
/// // Use derived implementation to print the vikings.
/// for (land, viking) in vikings.iter() {
/// println!("{} at {}", viking, land);
/// // Use derived implementation to print the status of the vikings.
/// for (viking, health) in vikings.iter() {
/// println!("{} has {} hp", viking, health);
/// }
/// ```
#[deriving(Clone)]
@ -888,8 +896,8 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
/// }
/// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn iter(&self) -> Entries<K, V> {
Entries { inner: self.table.iter() }
pub fn iter(&self) -> Iter<K, V> {
Iter { inner: self.table.iter() }
}
/// An iterator visiting all key-value pairs in arbitrary order,
@ -1305,8 +1313,8 @@ impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> IndexMut<Q, V> for HashMap<K
}
/// HashMap iterator
pub struct Entries<'a, K: 'a, V: 'a> {
inner: table::Entries<'a, K, V>
pub struct Iter<'a, K: 'a, V: 'a> {
inner: table::Iter<'a, K, V>
}
/// HashMap mutable values iterator
@ -1326,12 +1334,12 @@ pub struct IntoIter<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>
inner: Map<(&'a K, &'a V), &'a K, Iter<'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>
inner: Map<(&'a K, &'a V), &'a V, Iter<'a, K, V>, fn((&'a K, &'a V)) -> &'a V>
}
/// HashMap drain iterator
@ -1373,7 +1381,7 @@ enum VacantEntryState<K, V, M> {
NoElem(EmptyBucket<K, V, M>),
}
impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
impl<'a, K, V> Iterator<(&'a K, &'a V)> for Iter<'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() }
}

View File

@ -23,7 +23,7 @@ use num::{Int, UnsignedInt};
use ops::{Deref, DerefMut, Drop};
use option::Option;
use option::Option::{Some, None};
use ptr::{Unique, RawPtr, copy_nonoverlapping_memory, zero_memory};
use ptr::{Unique, PtrExt, copy_nonoverlapping_memory, zero_memory};
use ptr;
use rt::heap::{allocate, deallocate};
@ -657,8 +657,8 @@ impl<K, V> RawTable<K, V> {
}
}
pub fn iter(&self) -> Entries<K, V> {
Entries {
pub fn iter(&self) -> Iter<K, V> {
Iter {
iter: self.raw_buckets(),
elems_left: self.size(),
}
@ -770,7 +770,7 @@ impl<'a, K, V> Iterator<(K, V)> for RevMoveBuckets<'a, K, V> {
}
/// Iterator over shared references to entries in a table.
pub struct Entries<'a, K: 'a, V: 'a> {
pub struct Iter<'a, K: 'a, V: 'a> {
iter: RawBuckets<'a, K, V>,
elems_left: uint,
}
@ -793,7 +793,7 @@ pub struct Drain<'a, K: 'a, V: 'a> {
iter: RawBuckets<'static, K, V>,
}
impl<'a, K, V> Iterator<(&'a K, &'a V)> for Entries<'a, K, V> {
impl<'a, K, V> Iterator<(&'a K, &'a V)> for Iter<'a, K, V> {
fn next(&mut self) -> Option<(&'a K, &'a V)> {
self.iter.next().map(|bucket| {
self.elems_left -= 1;

View File

@ -181,7 +181,7 @@
// senders. Under the hood, however, there are actually three flavors of
// channels in play.
//
// * Oneshots - these channels are highly optimized for the one-send use case.
// * Flavor::Oneshots - these channels are highly optimized for the one-send use case.
// 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
@ -316,7 +316,6 @@ use core::prelude::*;
pub use self::TryRecvError::*;
pub use self::TrySendError::*;
use self::Flavor::*;
use alloc::arc::Arc;
use core::kinds;
@ -337,7 +336,8 @@ macro_rules! test {
use super::*;
use comm::*;
use thread::Thread;
use prelude::*;
use prelude::{Ok, Err, spawn, range, drop, Box, Some, None, Option};
use prelude::{Vec, Buffer, from_str, Clone};
$(#[$a])* #[test] fn f() { $b }
}
@ -478,7 +478,7 @@ impl<T> UnsafeFlavor<T> for Receiver<T> {
#[unstable]
pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
let a = Arc::new(RacyCell::new(oneshot::Packet::new()));
(Sender::new(Oneshot(a.clone())), Receiver::new(Oneshot(a)))
(Sender::new(Flavor::Oneshot(a.clone())), Receiver::new(Flavor::Oneshot(a)))
}
/// Creates a new synchronous, bounded channel.
@ -518,7 +518,7 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
of channel that is is creating"]
pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
let a = Arc::new(RacyCell::new(sync::Packet::new(bound)));
(SyncSender::new(a.clone()), Receiver::new(Sync(a)))
(SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a)))
}
////////////////////////////////////////////////////////////////////////////////
@ -592,7 +592,7 @@ impl<T: Send> Sender<T> {
#[unstable = "this function may be renamed to send() in the future"]
pub fn send_opt(&self, t: T) -> Result<(), T> {
let (new_inner, ret) = match *unsafe { self.inner() } {
Oneshot(ref p) => {
Flavor::Oneshot(ref p) => {
unsafe {
let p = p.get();
if !(*p).sent() {
@ -600,7 +600,7 @@ impl<T: Send> Sender<T> {
} else {
let a =
Arc::new(RacyCell::new(stream::Packet::new()));
match (*p).upgrade(Receiver::new(Stream(a.clone()))) {
match (*p).upgrade(Receiver::new(Flavor::Stream(a.clone()))) {
oneshot::UpSuccess => {
let ret = (*a.get()).send(t);
(a, ret)
@ -618,13 +618,13 @@ impl<T: Send> Sender<T> {
}
}
}
Stream(ref p) => return unsafe { (*p.get()).send(t) },
Shared(ref p) => return unsafe { (*p.get()).send(t) },
Sync(..) => unreachable!(),
Flavor::Stream(ref p) => return unsafe { (*p.get()).send(t) },
Flavor::Shared(ref p) => return unsafe { (*p.get()).send(t) },
Flavor::Sync(..) => unreachable!(),
};
unsafe {
let tmp = Sender::new(Stream(new_inner));
let tmp = Sender::new(Flavor::Stream(new_inner));
mem::swap(self.inner_mut(), tmp.inner_mut());
}
return ret;
@ -635,42 +635,42 @@ impl<T: Send> Sender<T> {
impl<T: Send> Clone for Sender<T> {
fn clone(&self) -> Sender<T> {
let (packet, sleeper, guard) = match *unsafe { self.inner() } {
Oneshot(ref p) => {
Flavor::Oneshot(ref p) => {
let a = Arc::new(RacyCell::new(shared::Packet::new()));
unsafe {
let guard = (*a.get()).postinit_lock();
match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) {
match (*p.get()).upgrade(Receiver::new(Flavor::Shared(a.clone()))) {
oneshot::UpSuccess |
oneshot::UpDisconnected => (a, None, guard),
oneshot::UpWoke(task) => (a, Some(task), guard)
}
}
}
Stream(ref p) => {
Flavor::Stream(ref p) => {
let a = Arc::new(RacyCell::new(shared::Packet::new()));
unsafe {
let guard = (*a.get()).postinit_lock();
match (*p.get()).upgrade(Receiver::new(Shared(a.clone()))) {
match (*p.get()).upgrade(Receiver::new(Flavor::Shared(a.clone()))) {
stream::UpSuccess |
stream::UpDisconnected => (a, None, guard),
stream::UpWoke(task) => (a, Some(task), guard),
}
}
}
Shared(ref p) => {
Flavor::Shared(ref p) => {
unsafe { (*p.get()).clone_chan(); }
return Sender::new(Shared(p.clone()));
return Sender::new(Flavor::Shared(p.clone()));
}
Sync(..) => unreachable!(),
Flavor::Sync(..) => unreachable!(),
};
unsafe {
(*packet.get()).inherit_blocker(sleeper, guard);
let tmp = Sender::new(Shared(packet.clone()));
let tmp = Sender::new(Flavor::Shared(packet.clone()));
mem::swap(self.inner_mut(), tmp.inner_mut());
}
Sender::new(Shared(packet))
Sender::new(Flavor::Shared(packet))
}
}
@ -678,10 +678,10 @@ impl<T: Send> Clone for Sender<T> {
impl<T: Send> Drop for Sender<T> {
fn drop(&mut self) {
match *unsafe { self.inner_mut() } {
Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
Stream(ref mut p) => unsafe { (*p.get()).drop_chan(); },
Shared(ref mut p) => unsafe { (*p.get()).drop_chan(); },
Sync(..) => unreachable!(),
Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_chan(); },
Flavor::Stream(ref mut p) => unsafe { (*p.get()).drop_chan(); },
Flavor::Shared(ref mut p) => unsafe { (*p.get()).drop_chan(); },
Flavor::Sync(..) => unreachable!(),
}
}
}
@ -827,7 +827,7 @@ impl<T: Send> Receiver<T> {
pub fn try_recv(&self) -> Result<T, TryRecvError> {
loop {
let new_port = match *unsafe { self.inner() } {
Oneshot(ref p) => {
Flavor::Oneshot(ref p) => {
match unsafe { (*p.get()).try_recv() } {
Ok(t) => return Ok(t),
Err(oneshot::Empty) => return Err(Empty),
@ -835,7 +835,7 @@ impl<T: Send> Receiver<T> {
Err(oneshot::Upgraded(rx)) => rx,
}
}
Stream(ref p) => {
Flavor::Stream(ref p) => {
match unsafe { (*p.get()).try_recv() } {
Ok(t) => return Ok(t),
Err(stream::Empty) => return Err(Empty),
@ -843,14 +843,14 @@ impl<T: Send> Receiver<T> {
Err(stream::Upgraded(rx)) => rx,
}
}
Shared(ref p) => {
Flavor::Shared(ref p) => {
match unsafe { (*p.get()).try_recv() } {
Ok(t) => return Ok(t),
Err(shared::Empty) => return Err(Empty),
Err(shared::Disconnected) => return Err(Disconnected),
}
}
Sync(ref p) => {
Flavor::Sync(ref p) => {
match unsafe { (*p.get()).try_recv() } {
Ok(t) => return Ok(t),
Err(sync::Empty) => return Err(Empty),
@ -881,7 +881,7 @@ impl<T: Send> Receiver<T> {
pub fn recv_opt(&self) -> Result<T, ()> {
loop {
let new_port = match *unsafe { self.inner() } {
Oneshot(ref p) => {
Flavor::Oneshot(ref p) => {
match unsafe { (*p.get()).recv() } {
Ok(t) => return Ok(t),
Err(oneshot::Empty) => return unreachable!(),
@ -889,7 +889,7 @@ impl<T: Send> Receiver<T> {
Err(oneshot::Upgraded(rx)) => rx,
}
}
Stream(ref p) => {
Flavor::Stream(ref p) => {
match unsafe { (*p.get()).recv() } {
Ok(t) => return Ok(t),
Err(stream::Empty) => return unreachable!(),
@ -897,14 +897,14 @@ impl<T: Send> Receiver<T> {
Err(stream::Upgraded(rx)) => rx,
}
}
Shared(ref p) => {
Flavor::Shared(ref p) => {
match unsafe { (*p.get()).recv() } {
Ok(t) => return Ok(t),
Err(shared::Empty) => return unreachable!(),
Err(shared::Disconnected) => return Err(()),
}
}
Sync(ref p) => return unsafe { (*p.get()).recv() }
Flavor::Sync(ref p) => return unsafe { (*p.get()).recv() }
};
unsafe {
mem::swap(self.inner_mut(), new_port.inner_mut());
@ -924,22 +924,22 @@ impl<T: Send> select::Packet for Receiver<T> {
fn can_recv(&self) -> bool {
loop {
let new_port = match *unsafe { self.inner() } {
Oneshot(ref p) => {
Flavor::Oneshot(ref p) => {
match unsafe { (*p.get()).can_recv() } {
Ok(ret) => return ret,
Err(upgrade) => upgrade,
}
}
Stream(ref p) => {
Flavor::Stream(ref p) => {
match unsafe { (*p.get()).can_recv() } {
Ok(ret) => return ret,
Err(upgrade) => upgrade,
}
}
Shared(ref p) => {
Flavor::Shared(ref p) => {
return unsafe { (*p.get()).can_recv() };
}
Sync(ref p) => {
Flavor::Sync(ref p) => {
return unsafe { (*p.get()).can_recv() };
}
};
@ -953,24 +953,24 @@ impl<T: Send> select::Packet for Receiver<T> {
fn start_selection(&self, mut token: SignalToken) -> StartResult {
loop {
let (t, new_port) = match *unsafe { self.inner() } {
Oneshot(ref p) => {
Flavor::Oneshot(ref p) => {
match unsafe { (*p.get()).start_selection(token) } {
oneshot::SelSuccess => return Installed,
oneshot::SelCanceled => return Abort,
oneshot::SelUpgraded(t, rx) => (t, rx),
}
}
Stream(ref p) => {
Flavor::Stream(ref p) => {
match unsafe { (*p.get()).start_selection(token) } {
stream::SelSuccess => return Installed,
stream::SelCanceled => return Abort,
stream::SelUpgraded(t, rx) => (t, rx),
}
}
Shared(ref p) => {
Flavor::Shared(ref p) => {
return unsafe { (*p.get()).start_selection(token) };
}
Sync(ref p) => {
Flavor::Sync(ref p) => {
return unsafe { (*p.get()).start_selection(token) };
}
};
@ -985,14 +985,14 @@ impl<T: Send> select::Packet for Receiver<T> {
let mut was_upgrade = false;
loop {
let result = match *unsafe { self.inner() } {
Oneshot(ref p) => unsafe { (*p.get()).abort_selection() },
Stream(ref p) => unsafe {
Flavor::Oneshot(ref p) => unsafe { (*p.get()).abort_selection() },
Flavor::Stream(ref p) => unsafe {
(*p.get()).abort_selection(was_upgrade)
},
Shared(ref p) => return unsafe {
Flavor::Shared(ref p) => return unsafe {
(*p.get()).abort_selection(was_upgrade)
},
Sync(ref p) => return unsafe {
Flavor::Sync(ref p) => return unsafe {
(*p.get()).abort_selection()
},
};
@ -1015,10 +1015,10 @@ impl<'a, T: Send> Iterator<T> for Messages<'a, T> {
impl<T: Send> Drop for Receiver<T> {
fn drop(&mut self) {
match *unsafe { self.inner_mut() } {
Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
Stream(ref mut p) => unsafe { (*p.get()).drop_port(); },
Shared(ref mut p) => unsafe { (*p.get()).drop_port(); },
Sync(ref mut p) => unsafe { (*p.get()).drop_port(); },
Flavor::Oneshot(ref mut p) => unsafe { (*p.get()).drop_port(); },
Flavor::Stream(ref mut p) => unsafe { (*p.get()).drop_port(); },
Flavor::Shared(ref mut p) => unsafe { (*p.get()).drop_port(); },
Flavor::Sync(ref mut p) => unsafe { (*p.get()).drop_port(); },
}
}
}
@ -1047,7 +1047,7 @@ unsafe impl<T> kinds::Sync for RacyCell<T> { } // Oh dear
#[cfg(test)]
mod test {
use super::*;
use prelude::*;
use prelude::{spawn, range, Some, None, from_str, Clone, Str};
use os;
pub fn stress_factor() -> uint {

View File

@ -86,7 +86,7 @@ impl<T: Send> Packet<T> {
// and that could cause problems on platforms where it is
// represented by opaque data structure
pub fn postinit_lock(&self) -> MutexGuard<()> {
self.select_lock.lock()
self.select_lock.lock().unwrap()
}
// This function is used at the creation of a shared packet to inherit a
@ -435,7 +435,7 @@ impl<T: Send> Packet<T> {
// about looking at and dealing with to_wake. Once we have acquired the
// lock, we are guaranteed that inherit_blocker is done.
{
let _guard = self.select_lock.lock();
let _guard = self.select_lock.lock().unwrap();
}
// Like the stream implementation, we want to make sure that the count

View File

@ -121,9 +121,9 @@ fn wait<'a, 'b, T: Send>(lock: &'a Mutex<State<T>>,
NoneBlocked => {}
_ => unreachable!(),
}
drop(guard); // unlock
wait_token.wait(); // block
lock.lock() // relock
drop(guard); // unlock
wait_token.wait(); // block
lock.lock().unwrap() // relock
}
/// Wakes up a thread, dropping the lock at the correct time
@ -161,7 +161,7 @@ impl<T: Send> Packet<T> {
fn acquire_send_slot(&self) -> MutexGuard<State<T>> {
let mut node = Node { token: None, next: 0 as *mut Node };
loop {
let mut guard = self.lock.lock();
let mut guard = self.lock.lock().unwrap();
// are we ready to go?
if guard.disconnected || guard.buf.size() < guard.buf.cap() {
return guard;
@ -202,7 +202,7 @@ impl<T: Send> Packet<T> {
}
pub fn try_send(&self, t: T) -> Result<(), super::TrySendError<T>> {
let mut guard = self.lock.lock();
let mut guard = self.lock.lock().unwrap();
if guard.disconnected {
Err(super::RecvDisconnected(t))
} else if guard.buf.size() == guard.buf.cap() {
@ -239,7 +239,7 @@ impl<T: Send> Packet<T> {
// When reading this, remember that there can only ever be one receiver at
// time.
pub fn recv(&self) -> Result<T, ()> {
let mut guard = self.lock.lock();
let mut guard = self.lock.lock().unwrap();
// Wait for the buffer to have something in it. No need for a while loop
// because we're the only receiver.
@ -258,7 +258,7 @@ impl<T: Send> Packet<T> {
}
pub fn try_recv(&self) -> Result<T, Failure> {
let mut guard = self.lock.lock();
let mut guard = self.lock.lock().unwrap();
// Easy cases first
if guard.disconnected { return Err(Disconnected) }
@ -315,7 +315,7 @@ impl<T: Send> Packet<T> {
}
// Not much to do other than wake up a receiver if one's there
let mut guard = self.lock.lock();
let mut guard = self.lock.lock().unwrap();
if guard.disconnected { return }
guard.disconnected = true;
match mem::replace(&mut guard.blocker, NoneBlocked) {
@ -326,7 +326,7 @@ impl<T: Send> Packet<T> {
}
pub fn drop_port(&self) {
let mut guard = self.lock.lock();
let mut guard = self.lock.lock().unwrap();
if guard.disconnected { return }
guard.disconnected = true;
@ -372,14 +372,14 @@ impl<T: Send> Packet<T> {
// If Ok, the value is whether this port has data, if Err, then the upgraded
// port needs to be checked instead of this one.
pub fn can_recv(&self) -> bool {
let guard = self.lock.lock();
let guard = self.lock.lock().unwrap();
guard.disconnected || guard.buf.size() > 0
}
// Attempts to start selection on this port. This can either succeed or fail
// because there is data waiting.
pub fn start_selection(&self, token: SignalToken) -> StartResult {
let mut guard = self.lock.lock();
let mut guard = self.lock.lock().unwrap();
if guard.disconnected || guard.buf.size() > 0 {
Abort
} else {
@ -397,7 +397,7 @@ impl<T: Send> Packet<T> {
//
// The return value indicates whether there's data on this port.
pub fn abort_selection(&self) -> bool {
let mut guard = self.lock.lock();
let mut guard = self.lock.lock().unwrap();
match mem::replace(&mut guard.blocker, NoneBlocked) {
NoneBlocked => true,
BlockedSender(token) => {
@ -413,7 +413,7 @@ impl<T: Send> Packet<T> {
impl<T: Send> Drop for Packet<T> {
fn drop(&mut self) {
assert_eq!(self.channels.load(atomic::SeqCst), 0);
let mut guard = self.lock.lock();
let mut guard = self.lock.lock().unwrap();
assert!(guard.queue.dequeue().is_none());
assert!(guard.canceled.is_none());
}

View File

@ -81,6 +81,7 @@
use prelude::*;
use str::Utf8Error;
use string::{FromUtf8Error, FromUtf16Error};
/// Base functionality for all errors in Rust.
pub trait Error: Send {
@ -117,3 +118,12 @@ impl Error for Utf8Error {
fn detail(&self) -> Option<String> { Some(self.to_string()) }
}
impl Error for FromUtf8Error {
fn description(&self) -> &str { "invalid utf-8" }
fn detail(&self) -> Option<String> { Some(self.to_string()) }
}
impl Error for FromUtf16Error {
fn description(&self) -> &str { "invalid utf-16" }
}

Some files were not shown because too many files have changed in this diff Show More