Auto merge of #41591 - frewsxcv:rollup, r=frewsxcv
Rollup of 7 pull requests - Successful merges: #41438, #41523, #41526, #41546, #41556, #41572, #41578 - Failed merges:
This commit is contained in:
commit
70baf4f13e
18 changed files with 395 additions and 70 deletions
6
src/Cargo.lock
generated
6
src/Cargo.lock
generated
|
@ -269,7 +269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
|
||||
[[package]]
|
||||
name = "mdbook"
|
||||
version = "0.0.19"
|
||||
version = "0.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -425,7 +425,7 @@ name = "rustbook"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap 2.22.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mdbook 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"mdbook 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1001,7 +1001,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
"checksum lazy_static 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4732c563b9a21a406565c4747daa7b46742f082911ae4753f390dc9ec7ee1a97"
|
||||
"checksum libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)" = "88ee81885f9f04bff991e306fea7c1c60a5f0f9e409e99f6b40e3311a3363135"
|
||||
"checksum log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "5141eca02775a762cc6cd564d8d2c50f67c0ea3a372cbf1c51592b3e029e10ad"
|
||||
"checksum mdbook 0.0.19 (registry+https://github.com/rust-lang/crates.io-index)" = "2598843aeda0c5bb2e8e4d714564f1c3fc40f7844157e34563bf96ae3866b56e"
|
||||
"checksum mdbook 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "f1e2e9d848514dcfad4195788d0d42ae5153a477c191d75d5b84fab10f222fbd"
|
||||
"checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4"
|
||||
"checksum num-traits 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "e1cbfa3781f3fe73dc05321bed52a06d2d491eaa764c52335cf4399f046ece99"
|
||||
"checksum num_cpus 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca313f1862c7ec3e0dfe8ace9fa91b1d9cb5c84ace3d00f5ec4216238e93c167"
|
||||
|
|
|
@ -451,7 +451,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
|||
// So peel off one-level, turning the &T into T.
|
||||
match base_ty.builtin_deref(false, ty::NoPreference) {
|
||||
Some(t) => t.ty,
|
||||
None => { return Err(()); }
|
||||
None => {
|
||||
debug!("By-ref binding of non-derefable type {:?}", base_ty);
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => base_ty,
|
||||
|
@ -1039,6 +1042,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
|||
match base_cmt.ty.builtin_index() {
|
||||
Some(ty) => (ty, ElementKind::VecElement),
|
||||
None => {
|
||||
debug!("Explicit index of non-indexable type {:?}", base_cmt);
|
||||
return Err(());
|
||||
}
|
||||
}
|
||||
|
@ -1154,7 +1158,10 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
|
|||
PatKind::TupleStruct(hir::QPath::Resolved(_, ref path), ..) |
|
||||
PatKind::Struct(hir::QPath::Resolved(_, ref path), ..) => {
|
||||
match path.def {
|
||||
Def::Err => return Err(()),
|
||||
Def::Err => {
|
||||
debug!("access to unresolvable pattern {:?}", pat);
|
||||
return Err(())
|
||||
}
|
||||
Def::Variant(variant_did) |
|
||||
Def::VariantCtor(variant_did, ..) => {
|
||||
// univariant enums do not need downcasts
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
use borrowck::BorrowckCtxt;
|
||||
use rustc::middle::mem_categorization as mc;
|
||||
use rustc::middle::mem_categorization::Categorization;
|
||||
use rustc::middle::mem_categorization::NoteClosureEnv;
|
||||
use rustc::middle::mem_categorization::InteriorOffsetKind as Kind;
|
||||
use rustc::ty;
|
||||
use syntax::ast;
|
||||
|
@ -71,10 +72,12 @@ fn report_move_errors<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
|
|||
let mut err = report_cannot_move_out_of(bccx, error.move_from.clone());
|
||||
let mut is_first_note = true;
|
||||
for move_to in &error.move_to_places {
|
||||
err = note_move_destination(err, move_to.span,
|
||||
move_to.name, is_first_note);
|
||||
err = note_move_destination(err, move_to.span, move_to.name, is_first_note);
|
||||
is_first_note = false;
|
||||
}
|
||||
if let NoteClosureEnv(upvar_id) = error.move_from.note {
|
||||
err.span_label(bccx.tcx.hir.span(upvar_id.var_id), &"captured outer variable");
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -375,6 +375,9 @@ impl Handler {
|
|||
panic!(ExplicitBug);
|
||||
}
|
||||
pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
|
||||
if self.treat_err_as_bug {
|
||||
self.span_bug(sp, msg);
|
||||
}
|
||||
let mut delayed = self.delayed_span_bug.borrow_mut();
|
||||
*delayed = Some((sp.into(), msg.to_string()));
|
||||
}
|
||||
|
|
|
@ -516,6 +516,8 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||
};
|
||||
|
||||
let index_expr_ty = self.node_ty(index_expr.id);
|
||||
let adjusted_base_ty = self.resolve_type_vars_if_possible(&adjusted_base_ty);
|
||||
let index_expr_ty = self.resolve_type_vars_if_possible(&index_expr_ty);
|
||||
|
||||
let result = self.try_index_step(ty::MethodCall::expr(expr.id),
|
||||
expr,
|
||||
|
@ -531,6 +533,15 @@ impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
|
|||
|
||||
let expr_ty = self.node_ty(expr.id);
|
||||
self.demand_suptype(expr.span, expr_ty, return_ty);
|
||||
} else {
|
||||
// We could not perform a mutable index. Re-apply the
|
||||
// immutable index adjustments - borrowck will detect
|
||||
// this as an error.
|
||||
if let Some(adjustment) = adjustment {
|
||||
self.apply_adjustment(expr.id, adjustment);
|
||||
}
|
||||
self.tcx.sess.delay_span_bug(
|
||||
expr.span, "convert_lvalue_derefs_to_mutable failed");
|
||||
}
|
||||
}
|
||||
hir::ExprUnary(hir::UnDeref, ref base_expr) => {
|
||||
|
|
|
@ -72,24 +72,23 @@ pub struct TcpStream(net_imp::TcpStream);
|
|||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// ```
|
||||
/// # use std::io;
|
||||
/// use std::net::{TcpListener, TcpStream};
|
||||
///
|
||||
/// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
|
||||
///
|
||||
/// fn handle_client(stream: TcpStream) {
|
||||
/// // ...
|
||||
/// }
|
||||
///
|
||||
/// # fn process() -> io::Result<()> {
|
||||
/// let listener = TcpListener::bind("127.0.0.1:80").unwrap();
|
||||
///
|
||||
/// // accept connections and process them serially
|
||||
/// for stream in listener.incoming() {
|
||||
/// match stream {
|
||||
/// Ok(stream) => {
|
||||
/// handle_client(stream);
|
||||
/// }
|
||||
/// Err(e) => { /* connection failed */ }
|
||||
/// }
|
||||
/// handle_client(stream?);
|
||||
/// }
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct TcpListener(net_imp::TcpListener);
|
||||
|
|
|
@ -297,12 +297,14 @@ mod sync;
|
|||
mod mpsc_queue;
|
||||
mod spsc_queue;
|
||||
|
||||
/// The receiving-half of Rust's channel type. This half can only be owned by
|
||||
/// one thread.
|
||||
/// The receiving half of Rust's [`channel`][] (or [`sync_channel`]) type.
|
||||
/// This half can only be owned by one thread.
|
||||
///
|
||||
/// Messages sent to the channel can be retrieved using [`recv`].
|
||||
///
|
||||
/// [`recv`]: ../../../std/sync/mpsc/struct.Receiver.html#method.recv
|
||||
/// [`channel`]: fn.channel.html
|
||||
/// [`sync_channel`]: fn.sync_channel.html
|
||||
/// [`recv`]: struct.Receiver.html#method.recv
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -336,51 +338,128 @@ unsafe impl<T: Send> Send for Receiver<T> { }
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> !Sync for Receiver<T> { }
|
||||
|
||||
/// An iterator over messages on a receiver, this iterator will block whenever
|
||||
/// [`next`] is called, waiting for a new message, and [`None`] will be returned
|
||||
/// An iterator over messages on a [`Receiver`], created by [`iter`].
|
||||
///
|
||||
/// This iterator will block whenever [`next`] is called,
|
||||
/// waiting for a new message, and [`None`] will be returned
|
||||
/// when the corresponding channel has hung up.
|
||||
///
|
||||
/// [`iter`]: struct.Receiver.html#method.iter
|
||||
/// [`Receiver`]: struct.Receiver.html
|
||||
/// [`next`]: ../../../std/iter/trait.Iterator.html#tymethod.next
|
||||
/// [`None`]: ../../../std/option/enum.Option.html#variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::sync::mpsc::channel;
|
||||
/// use std::thread;
|
||||
///
|
||||
/// let (send, recv) = channel();
|
||||
///
|
||||
/// thread::spawn(move || {
|
||||
/// send.send(1u8).unwrap();
|
||||
/// send.send(2u8).unwrap();
|
||||
/// send.send(3u8).unwrap();
|
||||
/// });
|
||||
///
|
||||
/// for x in recv.iter() {
|
||||
/// println!("Got: {}", x);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct Iter<'a, T: 'a> {
|
||||
rx: &'a Receiver<T>
|
||||
}
|
||||
|
||||
/// An iterator that attempts to yield all pending values for a receiver.
|
||||
/// [`None`] will be returned when there are no pending values remaining or if
|
||||
/// the corresponding channel has hung up.
|
||||
/// An iterator that attempts to yield all pending values for a [`Receiver`],
|
||||
/// created by [`try_iter`].
|
||||
///
|
||||
/// This Iterator will never block the caller in order to wait for data to
|
||||
/// [`None`] will be returned when there are no pending values remaining or
|
||||
/// if the corresponding channel has hung up.
|
||||
///
|
||||
/// This iterator will never block the caller in order to wait for data to
|
||||
/// become available. Instead, it will return [`None`].
|
||||
///
|
||||
/// [`Receiver`]: struct.Receiver.html
|
||||
/// [`try_iter`]: struct.Receiver.html#method.try_iter
|
||||
/// [`None`]: ../../../std/option/enum.Option.html#variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::sync::mpsc::channel;
|
||||
/// use std::thread;
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let (sender, receiver) = channel();
|
||||
///
|
||||
/// // Nothing is in the buffer yet
|
||||
/// assert!(receiver.try_iter().next().is_none());
|
||||
/// println!("Nothing in the buffer...");
|
||||
///
|
||||
/// thread::spawn(move || {
|
||||
/// sender.send(1).unwrap();
|
||||
/// sender.send(2).unwrap();
|
||||
/// sender.send(3).unwrap();
|
||||
/// });
|
||||
///
|
||||
/// println!("Going to sleep...");
|
||||
/// thread::sleep(Duration::from_secs(2)); // block for two seconds
|
||||
///
|
||||
/// for x in receiver.try_iter() {
|
||||
/// println!("Got: {}", x);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "receiver_try_iter", since = "1.15.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct TryIter<'a, T: 'a> {
|
||||
rx: &'a Receiver<T>
|
||||
}
|
||||
|
||||
/// An owning iterator over messages on a receiver, this iterator will block
|
||||
/// whenever [`next`] is called, waiting for a new message, and [`None`] will be
|
||||
/// returned when the corresponding channel has hung up.
|
||||
/// An owning iterator over messages on a [`Receiver`],
|
||||
/// created by **Receiver::into_iter**.
|
||||
///
|
||||
/// This iterator will block whenever [`next`]
|
||||
/// is called, waiting for a new message, and [`None`] will be
|
||||
/// returned if the corresponding channel has hung up.
|
||||
///
|
||||
/// [`Receiver`]: struct.Receiver.html
|
||||
/// [`next`]: ../../../std/iter/trait.Iterator.html#tymethod.next
|
||||
/// [`None`]: ../../../std/option/enum.Option.html#variant.None
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::sync::mpsc::channel;
|
||||
/// use std::thread;
|
||||
///
|
||||
/// let (send, recv) = channel();
|
||||
///
|
||||
/// thread::spawn(move || {
|
||||
/// send.send(1u8).unwrap();
|
||||
/// send.send(2u8).unwrap();
|
||||
/// send.send(3u8).unwrap();
|
||||
/// });
|
||||
///
|
||||
/// for x in recv.into_iter() {
|
||||
/// println!("Got: {}", x);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "receiver_into_iter", since = "1.1.0")]
|
||||
#[derive(Debug)]
|
||||
pub struct IntoIter<T> {
|
||||
rx: Receiver<T>
|
||||
}
|
||||
|
||||
/// The sending-half of Rust's asynchronous channel type. This half can only be
|
||||
/// The sending-half of Rust's asynchronous [`channel`] type. This half can only be
|
||||
/// owned by one thread, but it can be cloned to send to other threads.
|
||||
///
|
||||
/// Messages can be sent through this channel with [`send`].
|
||||
///
|
||||
/// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
|
||||
/// [`channel`]: fn.channel.html
|
||||
/// [`send`]: struct.Sender.html#method.send
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -419,12 +498,55 @@ unsafe impl<T: Send> Send for Sender<T> { }
|
|||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
impl<T> !Sync for Sender<T> { }
|
||||
|
||||
/// The sending-half of Rust's synchronous channel type. This half can only be
|
||||
/// owned by one thread, but it can be cloned to send to other threads.
|
||||
/// The sending-half of Rust's synchronous [`sync_channel`] type.
|
||||
/// This half can only be owned by one thread, but it can be cloned
|
||||
/// to send to other threads.
|
||||
///
|
||||
/// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
|
||||
/// [`SyncSender::send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send
|
||||
/// Messages can be sent through this channel with [`send`] or [`try_send`].
|
||||
///
|
||||
/// [`send`] will block if there is no space in the internal buffer.
|
||||
///
|
||||
/// [`sync_channel`]: fn.sync_channel.html
|
||||
/// [`send`]: struct.SyncSender.html#method.send
|
||||
/// [`try_send`]: struct.SyncSender.html#method.try_send
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::sync::mpsc::sync_channel;
|
||||
/// use std::thread;
|
||||
///
|
||||
/// // Create a sync_channel with buffer size 2
|
||||
/// let (sync_sender, receiver) = sync_channel(2);
|
||||
/// let sync_sender2 = sync_sender.clone();
|
||||
///
|
||||
/// // First thread owns sync_sender
|
||||
/// thread::spawn(move || {
|
||||
/// sync_sender.send(1).unwrap();
|
||||
/// sync_sender.send(2).unwrap();
|
||||
/// });
|
||||
///
|
||||
/// // Second thread owns sync_sender2
|
||||
/// thread::spawn(move || {
|
||||
/// sync_sender2.send(3).unwrap();
|
||||
/// // thread will now block since the buffer is full
|
||||
/// println!("Thread unblocked!");
|
||||
/// });
|
||||
///
|
||||
/// let mut msg;
|
||||
///
|
||||
/// msg = receiver.recv().unwrap();
|
||||
/// println!("message {} received", msg);
|
||||
///
|
||||
/// // "Thread unblocked!" will be printed now
|
||||
///
|
||||
/// msg = receiver.recv().unwrap();
|
||||
/// println!("message {} received", msg);
|
||||
///
|
||||
/// msg = receiver.recv().unwrap();
|
||||
///
|
||||
/// println!("message {} received", msg);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub struct SyncSender<T> {
|
||||
inner: Arc<sync::Packet<T>>,
|
||||
|
@ -823,8 +945,9 @@ impl<T> SyncSender<T> {
|
|||
/// Note that a successful send does *not* guarantee that the receiver will
|
||||
/// ever see the data if there is a buffer on this channel. Items may be
|
||||
/// enqueued in the internal buffer for the receiver to receive at a later
|
||||
/// time. If the buffer size is 0, however, it can be guaranteed that the
|
||||
/// receiver has indeed received the data if this function returns success.
|
||||
/// time. If the buffer size is 0, however, the channel becomes a rendezvous
|
||||
/// channel and it guarantees that the receiver has indeed received
|
||||
/// the data if this function returns success.
|
||||
///
|
||||
/// This function will never panic, but it may return [`Err`] if the
|
||||
/// [`Receiver`] has disconnected and is no longer able to receive
|
||||
|
@ -832,6 +955,27 @@ impl<T> SyncSender<T> {
|
|||
///
|
||||
/// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
|
||||
/// [`Receiver`]: ../../../std/sync/mpsc/struct.Receiver.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::sync::mpsc::sync_channel;
|
||||
/// use std::thread;
|
||||
///
|
||||
/// // Create a rendezvous sync_channel with buffer size 0
|
||||
/// let (sync_sender, receiver) = sync_channel(0);
|
||||
///
|
||||
/// thread::spawn(move || {
|
||||
/// println!("sending message...");
|
||||
/// sync_sender.send(1).unwrap();
|
||||
/// // Thread is now blocked until the message is received
|
||||
///
|
||||
/// println!("...message received!");
|
||||
/// });
|
||||
///
|
||||
/// let msg = receiver.recv().unwrap();
|
||||
/// assert_eq!(1, msg);
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn send(&self, t: T) -> Result<(), SendError<T>> {
|
||||
self.inner.send(t).map_err(SendError)
|
||||
|
@ -844,11 +988,48 @@ impl<T> SyncSender<T> {
|
|||
/// data. Compared with [`send`], this function has two failure cases
|
||||
/// instead of one (one for disconnection, one for a full buffer).
|
||||
///
|
||||
/// See [`SyncSender::send`] for notes about guarantees of whether the
|
||||
/// See [`send`] for notes about guarantees of whether the
|
||||
/// receiver has received the data or not if this function is successful.
|
||||
///
|
||||
/// [`send`]: ../../../std/sync/mpsc/struct.Sender.html#method.send
|
||||
/// [`SyncSender::send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send
|
||||
/// [`send`]: ../../../std/sync/mpsc/struct.SyncSender.html#method.send
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::sync::mpsc::sync_channel;
|
||||
/// use std::thread;
|
||||
///
|
||||
/// // Create a sync_channel with buffer size 1
|
||||
/// let (sync_sender, receiver) = sync_channel(1);
|
||||
/// let sync_sender2 = sync_sender.clone();
|
||||
///
|
||||
/// // First thread owns sync_sender
|
||||
/// thread::spawn(move || {
|
||||
/// sync_sender.send(1).unwrap();
|
||||
/// sync_sender.send(2).unwrap();
|
||||
/// // Thread blocked
|
||||
/// });
|
||||
///
|
||||
/// // Second thread owns sync_sender2
|
||||
/// thread::spawn(move || {
|
||||
/// // This will return an error and send
|
||||
/// // no message if the buffer is full
|
||||
/// sync_sender2.try_send(3).is_err();
|
||||
/// });
|
||||
///
|
||||
/// let mut msg;
|
||||
/// msg = receiver.recv().unwrap();
|
||||
/// println!("message {} received", msg);
|
||||
///
|
||||
/// msg = receiver.recv().unwrap();
|
||||
/// println!("message {} received", msg);
|
||||
///
|
||||
/// // Third message may have never been sent
|
||||
/// match receiver.try_recv() {
|
||||
/// Ok(msg) => println!("message {} received", msg),
|
||||
/// Err(_) => println!("the third message was never sent"),
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
|
||||
self.inner.try_send(t)
|
||||
|
@ -894,6 +1075,21 @@ impl<T> Receiver<T> {
|
|||
///
|
||||
/// This is useful for a flavor of "optimistic check" before deciding to
|
||||
/// block on a receiver.
|
||||
///
|
||||
/// Compared with [`recv`], this function has two failure cases instead of one
|
||||
/// (one for disconnection, one for an empty buffer).
|
||||
///
|
||||
/// [`recv`]: struct.Receiver.html#method.recv
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::sync::mpsc::{Receiver, channel};
|
||||
///
|
||||
/// let (_, receiver): (_, Receiver<i32>) = channel();
|
||||
///
|
||||
/// assert!(receiver.try_recv().is_err());
|
||||
/// ```
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
pub fn try_recv(&self) -> Result<T, TryRecvError> {
|
||||
loop {
|
||||
|
@ -949,8 +1145,8 @@ impl<T> Receiver<T> {
|
|||
///
|
||||
/// This function will always block the current thread if there is no data
|
||||
/// available and it's possible for more data to be sent. Once a message is
|
||||
/// sent to the corresponding [`Sender`], then this receiver will wake up and
|
||||
/// return that message.
|
||||
/// sent to the corresponding [`Sender`][] (or [`SyncSender`]), then this
|
||||
/// receiver will wake up and return that message.
|
||||
///
|
||||
/// If the corresponding [`Sender`] has disconnected, or it disconnects while
|
||||
/// this call is blocking, this call will wake up and return [`Err`] to
|
||||
|
@ -958,7 +1154,8 @@ impl<T> Receiver<T> {
|
|||
/// However, since channels are buffered, messages sent before the disconnect
|
||||
/// will still be properly received.
|
||||
///
|
||||
/// [`Sender`]: ../../../std/sync/mpsc/struct.Sender.html
|
||||
/// [`Sender`]: struct.Sender.html
|
||||
/// [`SyncSender`]: struct.SyncSender.html
|
||||
/// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -1040,8 +1237,8 @@ impl<T> Receiver<T> {
|
|||
///
|
||||
/// This function will always block the current thread if there is no data
|
||||
/// available and it's possible for more data to be sent. Once a message is
|
||||
/// sent to the corresponding [`Sender`], then this receiver will wake up and
|
||||
/// return that message.
|
||||
/// sent to the corresponding [`Sender`][] (or [`SyncSender`]), then this
|
||||
/// receiver will wake up and return that message.
|
||||
///
|
||||
/// If the corresponding [`Sender`] has disconnected, or it disconnects while
|
||||
/// this call is blocking, this call will wake up and return [`Err`] to
|
||||
|
@ -1049,7 +1246,8 @@ impl<T> Receiver<T> {
|
|||
/// However, since channels are buffered, messages sent before the disconnect
|
||||
/// will still be properly received.
|
||||
///
|
||||
/// [`Sender`]: ../../../std/sync/mpsc/struct.Sender.html
|
||||
/// [`Sender`]: struct.Sender.html
|
||||
/// [`SyncSender`]: struct.SyncSender.html
|
||||
/// [`Err`]: ../../../std/result/enum.Result.html#variant.Err
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -1163,6 +1361,33 @@ impl<T> Receiver<T> {
|
|||
/// user by waiting for values.
|
||||
///
|
||||
/// [`panic!`]: ../../../std/macro.panic.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// use std::sync::mpsc::channel;
|
||||
/// use std::thread;
|
||||
/// use std::time::Duration;
|
||||
///
|
||||
/// let (sender, receiver) = channel();
|
||||
///
|
||||
/// // Nothing is in the buffer yet
|
||||
/// assert!(receiver.try_iter().next().is_none());
|
||||
/// println!("Nothing in the buffer...");
|
||||
///
|
||||
/// thread::spawn(move || {
|
||||
/// sender.send(1).unwrap();
|
||||
/// sender.send(2).unwrap();
|
||||
/// sender.send(3).unwrap();
|
||||
/// });
|
||||
///
|
||||
/// println!("Going to sleep...");
|
||||
/// thread::sleep(Duration::from_secs(2)); // block for two seconds
|
||||
///
|
||||
/// for x in receiver.try_iter() {
|
||||
/// println!("Got: {}", x);
|
||||
/// }
|
||||
/// ```
|
||||
#[stable(feature = "receiver_try_iter", since = "1.15.0")]
|
||||
pub fn try_iter(&self) -> TryIter<T> {
|
||||
TryIter { rx: self }
|
||||
|
|
2
src/llvm
2
src/llvm
|
@ -1 +1 @@
|
|||
Subproject commit 878af191434cd716eeb13c2be7a2b1e21abf2749
|
||||
Subproject commit 15745af7683844e43bdec966072b8e7b44772450
|
|
@ -1,4 +1,4 @@
|
|||
# If this file is modified, then llvm will be (optionally) cleaned and then rebuilt.
|
||||
# The actual contents of this file do not matter, but to trigger a change on the
|
||||
# build bots then the contents should be changed so git updates the mtime.
|
||||
2017-04-25
|
||||
2017-04-26
|
||||
|
|
26
src/test/run-pass/issue-41498.rs
Normal file
26
src/test/run-pass/issue-41498.rs
Normal file
|
@ -0,0 +1,26 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
// regression test for issue #41498.
|
||||
|
||||
struct S;
|
||||
impl S {
|
||||
fn mutate(&mut self) {}
|
||||
}
|
||||
|
||||
fn call_and_ref<T, F: FnOnce() -> T>(x: &mut Option<T>, f: F) -> &mut T {
|
||||
*x = Some(f());
|
||||
x.as_mut().unwrap()
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut n = None;
|
||||
call_and_ref(&mut n, || [S])[0].mutate();
|
||||
}
|
|
@ -11,7 +11,7 @@
|
|||
// check that borrowck looks inside consts/statics
|
||||
|
||||
static FN : &'static (Fn() -> (Box<Fn()->Box<i32>>) + Sync) = &|| {
|
||||
let x = Box::new(0);
|
||||
let x = Box::new(0); //~ NOTE moved
|
||||
Box::new(|| x) //~ ERROR cannot move out of captured outer variable
|
||||
};
|
||||
|
10
src/test/ui/borrowck/borrowck-in-static.stderr
Normal file
10
src/test/ui/borrowck/borrowck-in-static.stderr
Normal file
|
@ -0,0 +1,10 @@
|
|||
error[E0507]: cannot move out of captured outer variable in an `Fn` closure
|
||||
--> $DIR/borrowck-in-static.rs:15:17
|
||||
|
|
||||
14 | let x = Box::new(0); //~ NOTE moved
|
||||
| - captured outer variable
|
||||
15 | Box::new(|| x) //~ ERROR cannot move out of captured outer variable
|
||||
| ^ cannot move out of captured outer variable in an `Fn` closure
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -16,7 +16,7 @@ fn call<F>(f: F) where F : Fn() {
|
|||
}
|
||||
|
||||
fn main() {
|
||||
let y = vec![format!("World")];
|
||||
let y = vec![format!("World")]; //~ NOTE moved
|
||||
call(|| {
|
||||
y.into_iter();
|
||||
//~^ ERROR cannot move out of captured outer variable in an `Fn` closure
|
|
@ -0,0 +1,11 @@
|
|||
error[E0507]: cannot move out of captured outer variable in an `Fn` closure
|
||||
--> $DIR/unboxed-closures-move-upvar-from-non-once-ref-closure.rs:21:9
|
||||
|
|
||||
19 | let y = vec![format!("World")]; //~ NOTE moved
|
||||
| - captured outer variable
|
||||
20 | call(|| {
|
||||
21 | y.into_iter();
|
||||
| ^ cannot move out of captured outer variable in an `Fn` closure
|
||||
|
||||
error: aborting due to previous error
|
||||
|
|
@ -21,8 +21,11 @@ struct Test<'a> {
|
|||
fn call<F>(mut f: F) where F: FnMut(Fn) {
|
||||
f(Box::new(|| {
|
||||
//~^ ERROR: cannot borrow `f` as mutable more than once
|
||||
//~| NOTE first mutable borrow occurs here
|
||||
//~| NOTE second mutable borrow occurs here
|
||||
f((Box::new(|| {})))
|
||||
}));
|
||||
//~^ NOTE first borrow ends here
|
||||
}
|
||||
|
||||
fn test1() {
|
||||
|
@ -32,7 +35,10 @@ fn test1() {
|
|||
}
|
||||
|
||||
fn test2<F>(f: &F) where F: FnMut() {
|
||||
(*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable
|
||||
//~^ NOTE use `&mut F` here to make mutable
|
||||
(*f)();
|
||||
//~^ ERROR cannot borrow immutable borrowed content `*f` as mutable
|
||||
//~| NOTE cannot borrow as mutable
|
||||
}
|
||||
|
||||
fn test3<F>(f: &mut F) where F: FnMut() {
|
||||
|
@ -40,7 +46,10 @@ fn test3<F>(f: &mut F) where F: FnMut() {
|
|||
}
|
||||
|
||||
fn test4(f: &Test) {
|
||||
f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable
|
||||
//~^ NOTE use `&mut Test` here to make mutable
|
||||
f.f.call_mut(())
|
||||
//~^ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable
|
||||
//~| NOTE cannot borrow as mutable
|
||||
}
|
||||
|
||||
fn test5(f: &mut Test) {
|
||||
|
@ -57,10 +66,14 @@ fn test6() {
|
|||
fn test7() {
|
||||
fn foo<F>(_: F) where F: FnMut(Box<FnMut(isize)>, isize) {}
|
||||
let mut f = |g: Box<FnMut(isize)>, b: isize| {};
|
||||
//~^ NOTE moved
|
||||
f(Box::new(|a| {
|
||||
//~^ NOTE borrow of `f` occurs here
|
||||
foo(f);
|
||||
//~^ ERROR cannot move `f` into closure because it is borrowed
|
||||
//~| ERROR cannot move out of captured outer variable in an `FnMut` closure
|
||||
//~| NOTE move into closure occurs here
|
||||
//~| NOTE cannot move out of captured outer variable in an `FnMut` closure
|
||||
}), 3);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,40 +5,46 @@ error[E0499]: cannot borrow `f` as mutable more than once at a time
|
|||
| - ^^ second mutable borrow occurs here
|
||||
| |
|
||||
| first mutable borrow occurs here
|
||||
23 | //~^ ERROR: cannot borrow `f` as mutable more than once
|
||||
24 | f((Box::new(|| {})))
|
||||
...
|
||||
26 | f((Box::new(|| {})))
|
||||
| - borrow occurs due to use of `f` in closure
|
||||
25 | }));
|
||||
27 | }));
|
||||
| - first borrow ends here
|
||||
|
||||
error: cannot borrow immutable borrowed content `*f` as mutable
|
||||
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:35:5
|
||||
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:39:5
|
||||
|
|
||||
34 | fn test2<F>(f: &F) where F: FnMut() {
|
||||
37 | fn test2<F>(f: &F) where F: FnMut() {
|
||||
| -- use `&mut F` here to make mutable
|
||||
35 | (*f)(); //~ ERROR: cannot borrow immutable borrowed content `*f` as mutable
|
||||
38 | //~^ NOTE use `&mut F` here to make mutable
|
||||
39 | (*f)();
|
||||
| ^^^^ cannot borrow as mutable
|
||||
|
||||
error: cannot borrow immutable `Box` content `*f.f` as mutable
|
||||
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:43:5
|
||||
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:50:5
|
||||
|
|
||||
42 | fn test4(f: &Test) {
|
||||
48 | fn test4(f: &Test) {
|
||||
| ----- use `&mut Test` here to make mutable
|
||||
43 | f.f.call_mut(()) //~ ERROR: cannot borrow immutable `Box` content `*f.f` as mutable
|
||||
49 | //~^ NOTE use `&mut Test` here to make mutable
|
||||
50 | f.f.call_mut(())
|
||||
| ^^^ cannot borrow as mutable
|
||||
|
||||
error[E0504]: cannot move `f` into closure because it is borrowed
|
||||
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:61:13
|
||||
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:72:13
|
||||
|
|
||||
60 | f(Box::new(|a| {
|
||||
70 | f(Box::new(|a| {
|
||||
| - borrow of `f` occurs here
|
||||
61 | foo(f);
|
||||
71 | //~^ NOTE borrow of `f` occurs here
|
||||
72 | foo(f);
|
||||
| ^ move into closure occurs here
|
||||
|
||||
error[E0507]: cannot move out of captured outer variable in an `FnMut` closure
|
||||
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:61:13
|
||||
--> $DIR/borrowck-call-is-borrow-issue-12224.rs:72:13
|
||||
|
|
||||
61 | foo(f);
|
||||
68 | let mut f = |g: Box<FnMut(isize)>, b: isize| {};
|
||||
| ----- captured outer variable
|
||||
...
|
||||
72 | foo(f);
|
||||
| ^ cannot move out of captured outer variable in an `FnMut` closure
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
|
|
@ -8,5 +8,5 @@ license = "MIT/Apache-2.0"
|
|||
clap = "2.19.3"
|
||||
|
||||
[dependencies.mdbook]
|
||||
version = "0.0.19"
|
||||
version = "0.0.21"
|
||||
default-features = false
|
||||
|
|
|
@ -53,8 +53,7 @@ fn main() {
|
|||
|
||||
// Build command implementation
|
||||
fn build(args: &ArgMatches) -> Result<(), Box<Error>> {
|
||||
let book_dir = get_book_dir(args);
|
||||
let book = MDBook::new(&book_dir).read_config();
|
||||
let book = build_mdbook_struct(args);
|
||||
|
||||
let mut book = match args.value_of("dest-dir") {
|
||||
Some(dest_dir) => book.set_dest(Path::new(dest_dir)),
|
||||
|
@ -67,14 +66,26 @@ fn build(args: &ArgMatches) -> Result<(), Box<Error>> {
|
|||
}
|
||||
|
||||
fn test(args: &ArgMatches) -> Result<(), Box<Error>> {
|
||||
let book_dir = get_book_dir(args);
|
||||
let mut book = MDBook::new(&book_dir).read_config();
|
||||
let mut book = build_mdbook_struct(args);
|
||||
|
||||
try!(book.test());
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build_mdbook_struct(args: &ArgMatches) -> mdbook::MDBook {
|
||||
let book_dir = get_book_dir(args);
|
||||
let mut book = MDBook::new(&book_dir).read_config();
|
||||
|
||||
// By default mdbook will attempt to create non-existent files referenced
|
||||
// from SUMMARY.md files. This is problematic on CI where we mount the
|
||||
// source directory as readonly. To avoid any issues, we'll disabled
|
||||
// mdbook's implicit file creation feature.
|
||||
book.create_missing = false;
|
||||
|
||||
book
|
||||
}
|
||||
|
||||
fn get_book_dir(args: &ArgMatches) -> PathBuf {
|
||||
if let Some(dir) = args.value_of("dir") {
|
||||
// Check if path is relative from current dir, or absolute...
|
||||
|
|
Loading…
Add table
Reference in a new issue