提交 be760566 编写于 作者: B bors

Auto merge of #40148 - frewsxcv:rollup, r=frewsxcv

Rollup of 9 pull requests

- Successful merges: #39977, #40033, #40047, #40056, #40057, #40122, #40124, #40126, #40131
- Failed merges: #40101
......@@ -97,33 +97,38 @@ system internals, try asking in [`#rust-internals`][pound-rust-internals].
Before you can start building the compiler you need to configure the build for
your system. In most cases, that will just mean using the defaults provided
for Rust. Configuring involves invoking the `configure` script in the project
root.
for Rust.
```
./configure
```
To change configuration, you must copy the file `src/bootstrap/config.toml.example`
to `config.toml` in the directory from which you will be running the build, and
change the settings provided.
There are large number of options provided in this config file that will alter the
configuration used in the build process. Some options to note:
There are large number of options accepted by this script to alter the
configuration used later in the build process. Some options to note:
#### `[llvm]`:
- `ccache = true` - Use ccache when building llvm
- `--enable-debug` - Build a debug version of the compiler (disables optimizations,
which speeds up compilation of stage1 rustc)
- `--enable-optimize` - Enable optimizations (can be used with `--enable-debug`
to make a debug build with optimizations)
- `--disable-valgrind-rpass` - Don't run tests with valgrind
- `--enable-clang` - Prefer clang to gcc for building dependencies (e.g., LLVM)
- `--enable-ccache` - Invoke clang/gcc with ccache to re-use object files between builds
- `--enable-compiler-docs` - Build compiler documentation
#### `[build]`:
- `compiler-docs = true` - Build compiler documentation
To see a full list of options, run `./configure --help`.
#### `[rust]`:
- `debuginfo = true` - Build a compiler with debuginfo
- `optimize = false` - Disable optimizations to speed up compilation of stage1 rust
For more options, the `config.toml` file contains commented out defaults, with
descriptions of what each option will do.
Note: Previously the `./configure` script was used to configure this
project. It can still be used, but it's recommended to use a `config.toml`
file. If you still have a `config.mk` file in your directory - from
`./configure` - you may need to delete it for `config.toml` to work.
### Building
Although the `./configure` script will generate a `Makefile`, this is actually
just a thin veneer over the actual build system driver, `x.py`. This file, at
the root of the repository, is used to build, test, and document various parts
of the compiler. You can execute it as:
The build system uses the `x.py` script to control the build process. This script
is used to build, test, and document various parts of the compiler. You can
execute it as:
```sh
python x.py build
......@@ -185,6 +190,9 @@ To learn about all possible rules you can execute, run:
python x.py build --help --verbose
```
Note: Previously `./configure` and `make` were used to build this project.
They are still available, but `x.py` is the recommended build system.
### Useful commands
Some common invocations of `x.py` are:
......@@ -235,8 +243,8 @@ feature. We use the 'fork and pull' model described there.
Please make pull requests against the `master` branch.
Compiling all of `make check` can take a while. When testing your pull request,
consider using one of the more specialized `make` targets to cut down on the
Compiling all of `./x.py test` can take a while. When testing your pull request,
consider using one of the more specialized `./x.py` targets to cut down on the
amount of time you have to wait. You need to have built the compiler at least
once before running these will work, but that’s only one full build rather than
one each time.
......@@ -307,7 +315,7 @@ To find documentation-related issues, sort by the [A-docs label][adocs].
[adocs]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AA-docs
In many cases, you don't need a full `make doc`. You can use `rustdoc` directly
In many cases, you don't need a full `./x.py doc`. You can use `rustdoc` directly
to check small fixes. For example, `rustdoc src/doc/reference.md` will render
reference to `doc/reference.html`. The CSS might be messed up, but you can
verify that the HTML is right.
......
......@@ -35,15 +35,15 @@ Read ["Installing Rust"] from [The Book].
3. Build and install:
```sh
$ ./configure
$ make && sudo make install
$ ./x.py build && sudo ./x.py dist --install
```
> ***Note:*** Install locations can be adjusted by passing a `--prefix`
> argument to `configure`. Various other options are also supported – pass
> `--help` for more information on them.
> ***Note:*** Install locations can be adjusted by copying the config file
> from `./src/bootstrap/config.toml.example` to `./config.toml`, and
> adjusting the `prefix` option under `[install]`. Various other options are
> also supported, and are documented in the config file.
When complete, `sudo make install` will place several programs into
When complete, `sudo ./x.py dist --install` will place several programs into
`/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the
API-documentation tool. This install does not include [Cargo],
Rust's package manager, which you may also want to build.
......@@ -59,7 +59,6 @@ for interop with software produced by Visual Studio use the MSVC build of Rust;
for interop with GNU software built using the MinGW/MSYS2 toolchain use the GNU
build.
#### MinGW
[MSYS2][msys2] can be used to easily build Rust on Windows:
......@@ -94,11 +93,10 @@ build.
mingw-w64-x86_64-gcc
```
4. Navigate to Rust's source code (or clone it), then configure and build it:
4. Navigate to Rust's source code (or clone it), then build it:
```sh
$ ./configure
$ make && make install
$ ./x.py build && ./x.py dist --install
```
#### MSVC
......@@ -114,13 +112,6 @@ shell with:
> python x.py build
```
If you're running inside of an msys shell, however, you can run:
```sh
$ ./configure --build=x86_64-pc-windows-msvc
$ make && make install
```
Currently building Rust only works with some known versions of Visual Studio. If
you have a more recent version installed the build system doesn't understand
then you may need to force rustbuild to use an older version. This can be done
......@@ -131,13 +122,43 @@ CALL "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\vcvars64.
python x.py build
```
#### Specifying an ABI
Each specific ABI can also be used from either environment (for example, using
the GNU ABI in powershell) by using an explicit build triple. The available
Windows build triples are:
- GNU ABI (using GCC)
- `i686-pc-windows-gnu`
- `x86_64-pc-windows-gnu`
- The MSVC ABI
- `i686-pc-windows-msvc`
- `x86_64-pc-windows-msvc`
The build triple can be specified by either specifying `--build=ABI` when
invoking `x.py` commands, or by copying the `config.toml` file (as described
in Building From Source), and modifying the `build` option under the `[build]`
section.
### Configure and Make
While it's not the recommended build system, this project also provides a
configure script and makefile (the latter of which just invokes `x.py`).
```sh
$ ./configure
$ make && sudo make install
```
When using the configure script, the generated config.mk` file may override the
`config.toml` file. To go back to the `config.toml` file, delete the generated
`config.mk` file.
## Building Documentation
If you’d like to build the documentation, it’s almost the same:
```sh
$ ./configure
$ make docs
$ ./x.py doc
```
The generated documentation will appear in a top-level `doc` directory,
......
......@@ -349,8 +349,8 @@ to it.
## Lifetime Elision
Rust supports powerful local type inference in the bodies of functions but not in their item signatures.
It's forbidden to allow reasoning about types based on the item signature alone.
Rust supports powerful local type inference in the bodies of functions, but it
deliberately does not perform any reasoning about types for item signatures.
However, for ergonomic reasons, a very restricted secondary inference algorithm called
“lifetime elision” does apply when judging lifetimes. Lifetime elision is concerned solely with inferring
lifetime parameters using three easily memorizable and unambiguous rules. This means lifetime elision
......
......@@ -128,7 +128,7 @@ pub fn hello_world(input: TokenStream) -> TokenStream {
So there is a lot going on here. We have introduced two new crates: [`syn`] and
[`quote`]. As you may have noticed, `input: TokenSteam` is immediately converted
to a `String`. This `String` is a string representation of the Rust code for which
we are deriving `HelloWorld` for. At the moment, the only thing you can do with a
we are deriving `HelloWorld`. At the moment, the only thing you can do with a
`TokenStream` is convert it to a string. A richer API will exist in the future.
So what we really need is to be able to _parse_ Rust code into something
......
......@@ -65,12 +65,15 @@ pub mod rt {
/// A collection of methods that are required to format a message into a stream.
///
/// This trait is the type which this modules requires when formatting
/// information. This is similar to the standard library's `io::Write` trait,
/// information. This is similar to the standard library's [`io::Write`] trait,
/// but it is only intended for use in libcore.
///
/// This trait should generally not be implemented by consumers of the standard
/// library. The `write!` macro accepts an instance of `io::Write`, and the
/// `io::Write` trait is favored over implementing this trait.
/// library. The [`write!`] macro accepts an instance of [`io::Write`], and the
/// [`io::Write`] trait is favored over implementing this trait.
///
/// [`write!`]: ../../std/macro.write.html
/// [`io::Write`]: ../../std/io/trait.Write.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Write {
/// Writes a slice of bytes into this writer, returning whether the write
......@@ -82,29 +85,79 @@ pub trait Write {
///
/// # Errors
///
/// This function will return an instance of `Error` on error.
/// This function will return an instance of [`Error`] on error.
///
/// [`Error`]: struct.Error.html
///
/// # Examples
///
/// ```
/// use std::fmt::{Error, Write};
///
/// fn writer<W: Write>(f: &mut W, s: &str) -> Result<(), Error> {
/// f.write_str(s)
/// }
///
/// let mut buf = String::new();
/// writer(&mut buf, "hola").unwrap();
/// assert_eq!(&buf, "hola");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn write_str(&mut self, s: &str) -> Result;
/// Writes a `char` into this writer, returning whether the write succeeded.
/// Writes a [`char`] into this writer, returning whether the write succeeded.
///
/// A single `char` may be encoded as more than one byte.
/// A single [`char`] may be encoded as more than one byte.
/// This method can only succeed if the entire byte sequence was successfully
/// written, and this method will not return until all data has been
/// written or an error occurs.
///
/// # Errors
///
/// This function will return an instance of `Error` on error.
/// This function will return an instance of [`Error`] on error.
///
/// [`char`]: ../../std/primitive.char.html
/// [`Error`]: struct.Error.html
///
/// # Examples
///
/// ```
/// use std::fmt::{Error, Write};
///
/// fn writer<W: Write>(f: &mut W, c: char) -> Result<(), Error> {
/// f.write_char(c)
/// }
///
/// let mut buf = String::new();
/// writer(&mut buf, 'a').unwrap();
/// writer(&mut buf, 'b').unwrap();
/// assert_eq!(&buf, "ab");
/// ```
#[stable(feature = "fmt_write_char", since = "1.1.0")]
fn write_char(&mut self, c: char) -> Result {
self.write_str(c.encode_utf8(&mut [0; 4]))
}
/// Glue for usage of the `write!` macro with implementors of this trait.
/// Glue for usage of the [`write!`] macro with implementors of this trait.
///
/// This method should generally not be invoked manually, but rather through
/// the `write!` macro itself.
/// the [`write!`] macro itself.
///
/// [`write!`]: ../../std/macro.write.html
///
/// # Examples
///
/// ```
/// use std::fmt::{Error, Write};
///
/// fn writer<W: Write>(f: &mut W, s: &str) -> Result<(), Error> {
/// f.write_fmt(format_args!("{}", s))
/// }
///
/// let mut buf = String::new();
/// writer(&mut buf, "world").unwrap();
/// assert_eq!(&buf, "world");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn write_fmt(&mut self, args: Arguments) -> Result {
// This Adapter is needed to allow `self` (of type `&mut
......
......@@ -23,6 +23,7 @@
use traits;
use ty::{self, Ty, TyCtxt, TypeFoldable};
use ty::subst::Substs;
use std::borrow::Cow;
use syntax::ast;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
......@@ -38,6 +39,25 @@ pub enum ObjectSafetyViolation {
Method(ast::Name, MethodViolationCode),
}
impl ObjectSafetyViolation {
pub fn error_msg(&self) -> Cow<'static, str> {
match *self {
ObjectSafetyViolation::SizedSelf =>
"the trait cannot require that `Self : Sized`".into(),
ObjectSafetyViolation::SupertraitSelf =>
"the trait cannot use `Self` as a type parameter \
in the supertrait listing".into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::StaticMethod) =>
format!("method `{}` has no receiver", name).into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::ReferencesSelf) =>
format!("method `{}` references the `Self` type \
in its arguments or return type", name).into(),
ObjectSafetyViolation::Method(name, MethodViolationCode::Generic) =>
format!("method `{}` has generic type parameters", name).into(),
}
}
}
/// Reasons a method might not be object-safe.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum MethodViolationCode {
......
......@@ -1097,24 +1097,6 @@ pub fn is_empty(&self) -> bool {
}
}
impl<'tcx> TraitRef<'tcx> {
pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> {
TraitRef { def_id: def_id, substs: substs }
}
pub fn self_ty(&self) -> Ty<'tcx> {
self.substs.type_at(0)
}
pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
// Select only the "input types" from a trait-reference. For
// now this is all the types that appear in the
// trait-reference, but it should eventually exclude
// associated types.
self.substs.types()
}
}
/// When type checking, we use the `ParameterEnvironment` to track
/// details about the type/lifetime parameters that are in scope.
/// It primarily stores the bounds information.
......
......@@ -389,6 +389,24 @@ pub struct TraitRef<'tcx> {
pub substs: &'tcx Substs<'tcx>,
}
impl<'tcx> TraitRef<'tcx> {
pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> {
TraitRef { def_id: def_id, substs: substs }
}
pub fn self_ty(&self) -> Ty<'tcx> {
self.substs.type_at(0)
}
pub fn input_types<'a>(&'a self) -> impl DoubleEndedIterator<Item=Ty<'tcx>> + 'a {
// Select only the "input types" from a trait-reference. For
// now this is all the types that appear in the
// trait-reference, but it should eventually exclude
// associated types.
self.substs.types()
}
}
pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>;
impl<'tcx> PolyTraitRef<'tcx> {
......
......@@ -1878,7 +1878,7 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
&cx.shared.issue_tracker_base_url,
stab.issue) {
(true, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 =>
format!(" (<code>{}</code> <a href=\"{}{}\">#{}</a>)",
format!(" (<code>{} </code><a href=\"{}{}\">#{}</a>)",
Escape(&stab.feature), tracker_url, issue_no, issue_no),
(false, &Some(ref tracker_url), Some(issue_no)) if issue_no > 0 =>
format!(" (<a href=\"{}{}\">#{}</a>)", Escape(&tracker_url), issue_no,
......@@ -1890,12 +1890,12 @@ fn short_stability(item: &clean::Item, cx: &Context, show_reason: bool) -> Vec<S
if stab.unstable_reason.is_empty() {
stability.push(format!("<div class='stab unstable'>\
<span class=microscope>🔬</span> \
This is a nightly-only experimental API. &nbsp;{}\
This is a nightly-only experimental API. {}\
</div>",
unstable_extra));
unstable_extra));
} else {
let text = format!("<summary><span class=microscope>🔬</span> \
This is a nightly-only experimental API. &nbsp;{}\
This is a nightly-only experimental API. {}\
</summary>{}",
unstable_extra, MarkdownHtml(&stab.unstable_reason));
stability.push(format!("<div class='stab unstable'><details>{}</details></div>",
......
......@@ -27,6 +27,31 @@
//!
//! assert!(ecode.success());
//! ```
//!
//! Calling a command with input and reading its output:
//!
//! ```no_run
//! use std::process::{Command, Stdio};
//! use std::io::Write;
//!
//! let mut child = Command::new("/bin/cat")
//! .stdin(Stdio::piped())
//! .stdout(Stdio::piped())
//! .spawn()
//! .expect("failed to execute child");
//!
//! {
//! // limited borrow of stdin
//! let stdin = child.stdin.as_mut().expect("failed to get stdin");
//! stdin.write_all(b"test").expect("failed to write to stdin");
//! }
//!
//! let output = child
//! .wait_with_output()
//! .expect("failed to wait on child");
//!
//! assert_eq!(b"test", output.stdout.as_slice());
//! ```
#![stable(feature = "process", since = "1.0.0")]
......
......@@ -18,12 +18,57 @@
/// A type indicating whether a timed wait on a condition variable returned
/// due to a time out or not.
///
/// It is returned by the [`wait_timeout`] method.
///
/// [`wait_timeout`]: struct.Condvar.html#method.wait_timeout
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
#[stable(feature = "wait_timeout", since = "1.5.0")]
pub struct WaitTimeoutResult(bool);
impl WaitTimeoutResult {
/// Returns whether the wait was known to have timed out.
///
/// # Examples
///
/// This example spawns a thread which will update the boolean value and
/// then wait 100 milliseconds before notifying the condvar.
///
/// The main thread will wait with a timeout on the condvar and then leave
/// once the boolean has been updated and notified.
///
/// ```
/// use std::sync::{Arc, Mutex, Condvar};
/// use std::thread;
/// use std::time::Duration;
///
/// let pair = Arc::new((Mutex::new(false), Condvar::new()));
/// let pair2 = pair.clone();
///
/// thread::spawn(move|| {
/// let &(ref lock, ref cvar) = &*pair2;
/// let mut started = lock.lock().unwrap();
/// // We update the boolean value.
/// *started = true;
/// // Let's wait 20 milliseconds before notifying the condvar.
/// thread::sleep(Duration::from_millis(20));
/// cvar.notify_one();
/// });
///
/// // Wait for the thread to start up.
/// let &(ref lock, ref cvar) = &*pair;
/// let mut started = lock.lock().unwrap();
/// loop {
/// // Let's put a timeout on the condvar's wait.
/// let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap();
/// // 10 milliseconds have passed, or maybe the value changed!
/// started = result.0;
/// if *started == true {
/// // We received the notification and the value has been updated, we can leave.
/// break
/// }
/// }
/// ```
#[stable(feature = "wait_timeout", since = "1.5.0")]
pub fn timed_out(&self) -> bool {
self.0
......@@ -55,15 +100,16 @@ pub fn timed_out(&self) -> bool {
/// let pair = Arc::new((Mutex::new(false), Condvar::new()));
/// let pair2 = pair.clone();
///
/// // Inside of our lock, spawn a new thread, and then wait for it to start
/// // Inside of our lock, spawn a new thread, and then wait for it to start.
/// thread::spawn(move|| {
/// let &(ref lock, ref cvar) = &*pair2;
/// let mut started = lock.lock().unwrap();
/// *started = true;
/// // We notify the condvar that the value has changed.
/// cvar.notify_one();
/// });
///
/// // wait for the thread to start up
/// // Wait for the thread to start up.
/// let &(ref lock, ref cvar) = &*pair;
/// let mut started = lock.lock().unwrap();
/// while !*started {
......@@ -79,6 +125,14 @@ pub struct Condvar {
impl Condvar {
/// Creates a new condition variable which is ready to be waited on and
/// notified.
///
/// # Examples
///
/// ```
/// use std::sync::Condvar;
///
/// let condvar = Condvar::new();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new() -> Condvar {
let mut c = Condvar {
......@@ -95,10 +149,10 @@ pub fn new() -> Condvar {
/// notification.
///
/// This function will atomically unlock the mutex specified (represented by
/// `mutex_guard`) and block the current thread. This means that any calls
/// to `notify_*()` which happen logically after the mutex is unlocked are
/// candidates to wake this thread up. When this function call returns, the
/// lock specified will have been re-acquired.
/// `guard`) and block the current thread. This means that any calls
/// to [`notify_one()`] or [`notify_all()`] which happen logically after the
/// mutex is unlocked are candidates to wake this thread up. When this
/// function call returns, the lock specified will have been re-acquired.
///
/// Note that this function is susceptible to spurious wakeups. Condition
/// variables normally have a boolean predicate associated with them, and
......@@ -109,14 +163,46 @@ pub fn new() -> Condvar {
///
/// This function will return an error if the mutex being waited on is
/// poisoned when this thread re-acquires the lock. For more information,
/// see information about poisoning on the Mutex type.
/// see information about [poisoning] on the [`Mutex`] type.
///
/// # Panics
///
/// This function will `panic!()` if it is used with more than one mutex
/// This function will [`panic!()`] if it is used with more than one mutex
/// over time. Each condition variable is dynamically bound to exactly one
/// mutex to ensure defined behavior across platforms. If this functionality
/// is not desired, then unsafe primitives in `sys` are provided.
///
/// [`notify_one()`]: #method.notify_one
/// [`notify_all()`]: #method.notify_all
/// [poisoning]: ../sync/struct.Mutex.html#poisoning
/// [`Mutex`]: ../sync/struct.Mutex.html
/// [`panic!()`]: ../../std/macro.panic.html
///
/// # Examples
///
/// ```
/// use std::sync::{Arc, Mutex, Condvar};
/// use std::thread;
///
/// let pair = Arc::new((Mutex::new(false), Condvar::new()));
/// let pair2 = pair.clone();
///
/// thread::spawn(move|| {
/// let &(ref lock, ref cvar) = &*pair2;
/// let mut started = lock.lock().unwrap();
/// *started = true;
/// // We notify the condvar that the value has changed.
/// cvar.notify_one();
/// });
///
/// // Wait for the thread to start up.
/// let &(ref lock, ref cvar) = &*pair;
/// let mut started = lock.lock().unwrap();
/// // As long as the value inside the `Mutex` is false, we wait.
/// while !*started {
/// started = cvar.wait(started).unwrap();
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>)
-> LockResult<MutexGuard<'a, T>> {
......@@ -136,7 +222,7 @@ pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>)
/// Waits on this condition variable for a notification, timing out after a
/// specified duration.
///
/// The semantics of this function are equivalent to `wait()`
/// The semantics of this function are equivalent to [`wait`]
/// except that the thread will be blocked for roughly no longer
/// than `ms` milliseconds. This method should not be used for
/// precise timing due to anomalies such as preemption or platform
......@@ -150,8 +236,42 @@ pub fn wait<'a, T>(&self, guard: MutexGuard<'a, T>)
/// The returned boolean is `false` only if the timeout is known
/// to have elapsed.
///
/// Like `wait`, the lock specified will be re-acquired when this function
/// Like [`wait`], the lock specified will be re-acquired when this function
/// returns, regardless of whether the timeout elapsed or not.
///
/// [`wait`]: #method.wait
///
/// # Examples
///
/// ```
/// use std::sync::{Arc, Mutex, Condvar};
/// use std::thread;
///
/// let pair = Arc::new((Mutex::new(false), Condvar::new()));
/// let pair2 = pair.clone();
///
/// thread::spawn(move|| {
/// let &(ref lock, ref cvar) = &*pair2;
/// let mut started = lock.lock().unwrap();
/// *started = true;
/// // We notify the condvar that the value has changed.
/// cvar.notify_one();
/// });
///
/// // Wait for the thread to start up.
/// let &(ref lock, ref cvar) = &*pair;
/// let mut started = lock.lock().unwrap();
/// // As long as the value inside the `Mutex` is false, we wait.
/// loop {
/// let result = cvar.wait_timeout_ms(started, 10).unwrap();
/// // 10 milliseconds have passed, or maybe the value changed!
/// started = result.0;
/// if *started == true {
/// // We received the notification and the value has been updated, we can leave.
/// break
/// }
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_deprecated(since = "1.6.0", reason = "replaced by `std::sync::Condvar::wait_timeout`")]
pub fn wait_timeout_ms<'a, T>(&self, guard: MutexGuard<'a, T>, ms: u32)
......@@ -165,7 +285,7 @@ pub fn wait_timeout_ms<'a, T>(&self, guard: MutexGuard<'a, T>, ms: u32)
/// Waits on this condition variable for a notification, timing out after a
/// specified duration.
///
/// The semantics of this function are equivalent to `wait()` except that
/// The semantics of this function are equivalent to [`wait`] except that
/// the thread will be blocked for roughly no longer than `dur`. This
/// method should not be used for precise timing due to anomalies such as
/// preemption or platform differences that may not cause the maximum
......@@ -175,11 +295,47 @@ pub fn wait_timeout_ms<'a, T>(&self, guard: MutexGuard<'a, T>, ms: u32)
/// measured with a monotonic clock, and not affected by the changes made to
/// the system time.
///
/// The returned `WaitTimeoutResult` value indicates if the timeout is
/// The returned [`WaitTimeoutResult`] value indicates if the timeout is
/// known to have elapsed.
///
/// Like `wait`, the lock specified will be re-acquired when this function
/// Like [`wait`], the lock specified will be re-acquired when this function
/// returns, regardless of whether the timeout elapsed or not.
///
/// [`wait`]: #method.wait
/// [`WaitTimeoutResult`]: struct.WaitTimeoutResult.html
///
/// # Examples
///
/// ```
/// use std::sync::{Arc, Mutex, Condvar};
/// use std::thread;
/// use std::time::Duration;
///
/// let pair = Arc::new((Mutex::new(false), Condvar::new()));
/// let pair2 = pair.clone();
///
/// thread::spawn(move|| {
/// let &(ref lock, ref cvar) = &*pair2;
/// let mut started = lock.lock().unwrap();
/// *started = true;
/// // We notify the condvar that the value has changed.
/// cvar.notify_one();
/// });
///
/// // wait for the thread to start up
/// let &(ref lock, ref cvar) = &*pair;
/// let mut started = lock.lock().unwrap();
/// // as long as the value inside the `Mutex` is false, we wait
/// loop {
/// let result = cvar.wait_timeout(started, Duration::from_millis(10)).unwrap();
/// // 10 milliseconds have passed, or maybe the value changed!
/// started = result.0;
/// if *started == true {
/// // We received the notification and the value has been updated, we can leave.
/// break
/// }
/// }
/// ```
#[stable(feature = "wait_timeout", since = "1.5.0")]
pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>,
dur: Duration)
......@@ -200,10 +356,40 @@ pub fn wait_timeout<'a, T>(&self, guard: MutexGuard<'a, T>,
/// Wakes up one blocked thread on this condvar.
///
/// If there is a blocked thread on this condition variable, then it will
/// be woken up from its call to `wait` or `wait_timeout`. Calls to
/// be woken up from its call to [`wait`] or [`wait_timeout`]. Calls to
/// `notify_one` are not buffered in any way.
///
/// To wake up all threads, see `notify_all()`.
/// To wake up all threads, see [`notify_all()`].
///
/// [`wait`]: #method.wait
/// [`wait_timeout`]: #method.wait_timeout
/// [`notify_all()`]: #method.notify_all
///
/// # Examples
///
/// ```
/// use std::sync::{Arc, Mutex, Condvar};
/// use std::thread;
///
/// let pair = Arc::new((Mutex::new(false), Condvar::new()));
/// let pair2 = pair.clone();
///
/// thread::spawn(move|| {
/// let &(ref lock, ref cvar) = &*pair2;
/// let mut started = lock.lock().unwrap();
/// *started = true;
/// // We notify the condvar that the value has changed.
/// cvar.notify_one();
/// });
///
/// // Wait for the thread to start up.
/// let &(ref lock, ref cvar) = &*pair;
/// let mut started = lock.lock().unwrap();
/// // As long as the value inside the `Mutex` is false, we wait.
/// while !*started {
/// started = cvar.wait(started).unwrap();
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn notify_one(&self) {
unsafe { self.inner.notify_one() }
......@@ -215,7 +401,35 @@ pub fn notify_one(&self) {
/// variable are awoken. Calls to `notify_all()` are not buffered in any
/// way.
///
/// To wake up only one thread, see `notify_one()`.
/// To wake up only one thread, see [`notify_one()`].
///
/// [`notify_one()`]: #method.notify_one
///
/// # Examples
///
/// ```
/// use std::sync::{Arc, Mutex, Condvar};
/// use std::thread;
///
/// let pair = Arc::new((Mutex::new(false), Condvar::new()));
/// let pair2 = pair.clone();
///
/// thread::spawn(move|| {
/// let &(ref lock, ref cvar) = &*pair2;
/// let mut started = lock.lock().unwrap();
/// *started = true;
/// // We notify the condvar that the value has changed.
/// cvar.notify_all();
/// });
///
/// // Wait for the thread to start up.
/// let &(ref lock, ref cvar) = &*pair;
/// let mut started = lock.lock().unwrap();
/// // As long as the value inside the `Mutex` is false, we wait.
/// while !*started {
/// started = cvar.wait(started).unwrap();
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn notify_all(&self) {
unsafe { self.inner.notify_all() }
......
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Test;
impl FnOnce<(u32, u32)> for Test {
type Output = u32;
extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 {
a + b
}
//~^^^ ERROR rust-call ABI is subject to change (see issue #29625)
}
fn main() {
assert_eq!(Test(1u32, 2u32), 3u32);
}
......@@ -14,12 +14,12 @@
#![unstable(feature="test", issue="27759")]
// @has issue_27759/unstable/index.html
// @has - '<code>test</code>'
// @has - '<code>test </code>'
// @has - '<a href="http://issue_url/27759">#27759</a>'
#[unstable(feature="test", issue="27759")]
pub mod unstable {
// @has issue_27759/unstable/fn.issue.html
// @has - '<code>test_function</code>'
// @has - '<code>test_function </code>'
// @has - '<a href="http://issue_url/1234567890">#1234567890</a>'
#[unstable(feature="test_function", issue="1234567890")]
pub fn issue() {}
......
......@@ -18,10 +18,10 @@
// @has issue_32374/struct.T.html '//*[@class="stab deprecated"]' \
// 'Deprecated since 1.0.0: text'
// @has - '<code>test</code>'
// @has - '<code>test </code>'
// @has - '<a href="http://issue_url/32374">#32374</a>'
// @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' \
// '🔬 This is a nightly-only experimental API. \(test #32374\)$'
// '🔬 This is a nightly-only experimental API. \(test #32374\)$'
#[rustc_deprecated(since = "1.0.0", reason = "text")]
#[unstable(feature = "test", issue = "32374")]
pub struct T;
......@@ -29,11 +29,11 @@
// @has issue_32374/struct.U.html '//*[@class="stab deprecated"]' \
// 'Deprecated since 1.0.0: deprecated'
// @has issue_32374/struct.U.html '//*[@class="stab unstable"]' \
// '🔬 This is a nightly-only experimental API. (test #32374)'
// '🔬 This is a nightly-only experimental API. (test #32374)'
// @has issue_32374/struct.U.html '//details' \
// '🔬 This is a nightly-only experimental API. (test #32374)'
// '🔬 This is a nightly-only experimental API. (test #32374)'
// @has issue_32374/struct.U.html '//summary' \
// '🔬 This is a nightly-only experimental API. (test #32374)'
// '🔬 This is a nightly-only experimental API. (test #32374)'
// @has issue_32374/struct.U.html '//details/p' \
// 'unstable'
#[rustc_deprecated(since = "1.0.0", reason = "deprecated")]
......
......@@ -169,8 +169,8 @@ pub fn check(path: &Path, bad: &mut bool) {
let whitelist = vec![
"abi_ptx", "simd",
"cfg_target_has_atomic",
"unboxed_closures", "stmt_expr_attributes",
"cfg_target_thread_local", "unwind_attributes"
"stmt_expr_attributes",
"cfg_target_thread_local", "unwind_attributes",
];
// Only check the number of lang features.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册