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

Rollup of 14 pull requests

- Successful merges: #44554, #44648, #44658, #44712, #44717, #44726, #44745, #44746, #44749, #44759, #44770, #44773, #44776, #44778
- Failed merges:
This commit is contained in:
bors 2017-09-23 05:10:53 +00:00
commit 85a5d3ffa4
19 changed files with 309 additions and 58 deletions

View File

@ -461,6 +461,7 @@ For people new to Rust, and just starting to contribute, or even for
more seasoned developers, some useful places to look for information more seasoned developers, some useful places to look for information
are: are:
* [Rust Forge][rustforge] contains additional documentation, including write-ups of how to achieve common tasks
* The [Rust Internals forum][rif], a place to ask questions and * The [Rust Internals forum][rif], a place to ask questions and
discuss Rust's internals discuss Rust's internals
* The [generated documentation for rust's compiler][gdfrustc] * The [generated documentation for rust's compiler][gdfrustc]
@ -476,6 +477,7 @@ are:
[gsearchdocs]: https://www.google.com/search?q=site:doc.rust-lang.org+your+query+here [gsearchdocs]: https://www.google.com/search?q=site:doc.rust-lang.org+your+query+here
[rif]: http://internals.rust-lang.org [rif]: http://internals.rust-lang.org
[rr]: https://doc.rust-lang.org/book/README.html [rr]: https://doc.rust-lang.org/book/README.html
[rustforge]: https://forge.rust-lang.org/
[tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/ [tlgba]: http://tomlee.co/2014/04/a-more-detailed-tour-of-the-rust-compiler/
[ro]: http://www.rustaceans.org/ [ro]: http://www.rustaceans.org/
[rctd]: ./src/test/COMPILER_TESTS.md [rctd]: ./src/test/COMPILER_TESTS.md

View File

@ -72,13 +72,13 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
/// first: after all, isn't the point of `Arc<T>` thread safety? The key is /// first: after all, isn't the point of `Arc<T>` thread safety? The key is
/// this: `Arc<T>` makes it thread safe to have multiple ownership of the same /// this: `Arc<T>` makes it thread safe to have multiple ownership of the same
/// data, but it doesn't add thread safety to its data. Consider /// data, but it doesn't add thread safety to its data. Consider
/// `Arc<RefCell<T>>`. `RefCell<T>` isn't [`Sync`], and if `Arc<T>` was always /// `Arc<`[`RefCell<T>`]`>`. [`RefCell<T>`] isn't [`Sync`], and if `Arc<T>` was always
/// [`Send`], `Arc<RefCell<T>>` would be as well. But then we'd have a problem: /// [`Send`], `Arc<`[`RefCell<T>`]`>` would be as well. But then we'd have a problem:
/// `RefCell<T>` is not thread safe; it keeps track of the borrowing count using /// [`RefCell<T>`] is not thread safe; it keeps track of the borrowing count using
/// non-atomic operations. /// non-atomic operations.
/// ///
/// In the end, this means that you may need to pair `Arc<T>` with some sort of /// In the end, this means that you may need to pair `Arc<T>` with some sort of
/// `std::sync` type, usually `Mutex<T>`. /// [`std::sync`] type, usually [`Mutex<T>`][mutex].
/// ///
/// ## Breaking cycles with `Weak` /// ## Breaking cycles with `Weak`
/// ///
@ -106,7 +106,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
/// // a and b both point to the same memory location as foo. /// // a and b both point to the same memory location as foo.
/// ``` /// ```
/// ///
/// The `Arc::clone(&from)` syntax is the most idiomatic because it conveys more explicitly /// The [`Arc::clone(&from)`] syntax is the most idiomatic because it conveys more explicitly
/// the meaning of the code. In the example above, this syntax makes it easier to see that /// the meaning of the code. In the example above, this syntax makes it easier to see that
/// this code is creating a new reference rather than copying the whole content of foo. /// this code is creating a new reference rather than copying the whole content of foo.
/// ///
@ -141,6 +141,9 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
/// [upgrade]: struct.Weak.html#method.upgrade /// [upgrade]: struct.Weak.html#method.upgrade
/// [`None`]: ../../std/option/enum.Option.html#variant.None /// [`None`]: ../../std/option/enum.Option.html#variant.None
/// [assoc]: ../../book/first-edition/method-syntax.html#associated-functions /// [assoc]: ../../book/first-edition/method-syntax.html#associated-functions
/// [`RefCell<T>`]: ../../std/cell/struct.RefCell.html
/// [`std::sync`]: ../../std/sync/index.html
/// [`Arc::clone(&from)`]: #method.clone
/// ///
/// # Examples /// # Examples
/// ///

View File

@ -1700,8 +1700,18 @@ impl<T: ?Sized + Debug> Debug for RefCell<T> {
.finish() .finish()
} }
Err(_) => { Err(_) => {
// The RefCell is mutably borrowed so we can't look at its value
// here. Show a placeholder instead.
struct BorrowedPlaceholder;
impl Debug for BorrowedPlaceholder {
fn fmt(&self, f: &mut Formatter) -> Result {
f.write_str("<borrowed>")
}
}
f.debug_struct("RefCell") f.debug_struct("RefCell")
.field("value", &"<borrowed>") .field("value", &BorrowedPlaceholder)
.finish() .finish()
} }
} }

View File

@ -177,15 +177,59 @@ pub fn forget<T>(t: T) {
/// Returns the size of a type in bytes. /// Returns the size of a type in bytes.
/// ///
/// More specifically, this is the offset in bytes between successive /// More specifically, this is the offset in bytes between successive elements
/// items of the same type, including alignment padding. /// in an array with that item type including alignment padding. Thus, for any
/// type `T` and length `n`, `[T; n]` has a size of `n * size_of::<T>()`.
///
/// In general, the size of a type is not stable across compilations, but
/// specific types such as primitives are.
///
/// The following table gives the size for primitives.
///
/// Type | size_of::\<Type>()
/// ---- | ---------------
/// () | 0
/// u8 | 1
/// u16 | 2
/// u32 | 4
/// u64 | 8
/// i8 | 1
/// i16 | 2
/// i32 | 4
/// i64 | 8
/// f32 | 4
/// f64 | 8
/// char | 4
///
/// Furthermore, `usize` and `isize` have the same size.
///
/// The types `*const T`, `&T`, `Box<T>`, `Option<&T>`, and `Option<Box<T>>` all have
/// the same size. If `T` is Sized, all of those types have the same size as `usize`.
///
/// The mutability of a pointer does not change its size. As such, `&T` and `&mut T`
/// have the same size. Likewise for `*const T` and `*mut T`.
/// ///
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// use std::mem; /// use std::mem;
/// ///
/// // Some primitives
/// assert_eq!(4, mem::size_of::<i32>()); /// assert_eq!(4, mem::size_of::<i32>());
/// assert_eq!(8, mem::size_of::<f64>());
/// assert_eq!(0, mem::size_of::<()>());
///
/// // Some arrays
/// assert_eq!(8, mem::size_of::<[i32; 2]>());
/// assert_eq!(12, mem::size_of::<[i32; 3]>());
/// assert_eq!(0, mem::size_of::<[i32; 0]>());
///
///
/// // Pointer size equality
/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<*const i32>());
/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Box<i32>>());
/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::<Option<&i32>>());
/// assert_eq!(mem::size_of::<Box<i32>>(), mem::size_of::<Option<Box<i32>>>());
/// ``` /// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]

View File

@ -1399,9 +1399,6 @@ Section: Comparing strings
*/ */
/// Bytewise slice equality /// Bytewise slice equality
/// NOTE: This function is (ab)used in rustc::middle::trans::_match
/// to compare &[u8] byte slices that are not necessarily valid UTF-8.
#[lang = "str_eq"]
#[inline] #[inline]
fn eq_slice(a: &str, b: &str) -> bool { fn eq_slice(a: &str, b: &str) -> bool {
a.as_bytes() == b.as_bytes() a.as_bytes() == b.as_bytes()

View File

@ -37,7 +37,7 @@ incremental improves that may change.)
The dependency structure of these crates is roughly a diamond: The dependency structure of these crates is roughly a diamond:
```` ```
rustc_driver rustc_driver
/ | \ / | \
/ | \ / | \

View File

@ -65,7 +65,7 @@ use syntax::codemap::{self, respan, Spanned, CompilerDesugaringKind};
use syntax::std_inject; use syntax::std_inject;
use syntax::symbol::{Symbol, keywords}; use syntax::symbol::{Symbol, keywords};
use syntax::tokenstream::{TokenStream, TokenTree, Delimited}; use syntax::tokenstream::{TokenStream, TokenTree, Delimited};
use syntax::parse::token::{Token, DelimToken}; use syntax::parse::token::Token;
use syntax::util::small_vector::SmallVector; use syntax::util::small_vector::SmallVector;
use syntax::visit::{self, Visitor}; use syntax::visit::{self, Visitor};
use syntax_pos::Span; use syntax_pos::Span;
@ -606,10 +606,12 @@ impl<'a> LoweringContext<'a> {
} }
fn lower_token_stream(&mut self, tokens: TokenStream) -> TokenStream { fn lower_token_stream(&mut self, tokens: TokenStream) -> TokenStream {
tokens.into_trees().map(|tree| self.lower_token_tree(tree)).collect() tokens.into_trees()
.flat_map(|tree| self.lower_token_tree(tree).into_trees())
.collect()
} }
fn lower_token_tree(&mut self, tree: TokenTree) -> TokenTree { fn lower_token_tree(&mut self, tree: TokenTree) -> TokenStream {
match tree { match tree {
TokenTree::Token(span, token) => { TokenTree::Token(span, token) => {
self.lower_token(token, span) self.lower_token(token, span)
@ -618,23 +620,19 @@ impl<'a> LoweringContext<'a> {
TokenTree::Delimited(span, Delimited { TokenTree::Delimited(span, Delimited {
delim: delimited.delim, delim: delimited.delim,
tts: self.lower_token_stream(delimited.tts.into()).into(), tts: self.lower_token_stream(delimited.tts.into()).into(),
}) }).into()
} }
} }
} }
fn lower_token(&mut self, token: Token, span: Span) -> TokenTree { fn lower_token(&mut self, token: Token, span: Span) -> TokenStream {
match token { match token {
Token::Interpolated(_) => {} Token::Interpolated(_) => {}
other => return TokenTree::Token(span, other), other => return TokenTree::Token(span, other).into(),
} }
let tts = token.interpolated_to_tokenstream(&self.sess.parse_sess, span); let tts = token.interpolated_to_tokenstream(&self.sess.parse_sess, span);
let tts = self.lower_token_stream(tts); self.lower_token_stream(tts)
TokenTree::Delimited(span, Delimited {
delim: DelimToken::NoDelim,
tts: tts.into(),
})
} }
fn lower_arm(&mut self, arm: &Arm) -> hir::Arm { fn lower_arm(&mut self, arm: &Arm) -> hir::Arm {

View File

@ -280,8 +280,6 @@ language_item_table! {
EqTraitLangItem, "eq", eq_trait; EqTraitLangItem, "eq", eq_trait;
OrdTraitLangItem, "ord", ord_trait; OrdTraitLangItem, "ord", ord_trait;
StrEqFnLangItem, "str_eq", str_eq_fn;
// A number of panic-related lang items. The `panic` item corresponds to // A number of panic-related lang items. The `panic` item corresponds to
// divide-by-zero and various panic cases with `match`. The // divide-by-zero and various panic cases with `match`. The
// `panic_bounds_check` item is for indexing arrays. // `panic_bounds_check` item is for indexing arrays.

View File

@ -411,7 +411,8 @@ impl Session {
} }
pub fn emit_end_regions(&self) -> bool { pub fn emit_end_regions(&self) -> bool {
self.opts.debugging_opts.emit_end_regions || self.opts.debugging_opts.emit_end_regions ||
(self.opts.debugging_opts.mir_emit_validate > 0) (self.opts.debugging_opts.mir_emit_validate > 0) ||
self.opts.debugging_opts.borrowck_mir
} }
pub fn lto(&self) -> bool { pub fn lto(&self) -> bool {
self.opts.cg.lto self.opts.cg.lto

View File

@ -419,7 +419,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
self.each_borrow_involving_path( self.each_borrow_involving_path(
context, lvalue_span.0, flow_state, |this, _idx, borrow| { context, lvalue_span.0, flow_state, |this, _idx, borrow| {
if !borrow.compatible_with(BorrowKind::Shared) { if !borrow.compatible_with(BorrowKind::Shared) {
this.report_use_while_mutably_borrowed(context, lvalue_span); this.report_use_while_mutably_borrowed(context, lvalue_span, borrow);
Control::Break Control::Break
} else { } else {
Control::Continue Control::Continue
@ -914,11 +914,17 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
fn report_use_while_mutably_borrowed(&mut self, fn report_use_while_mutably_borrowed(&mut self,
_context: Context, _context: Context,
(lvalue, span): (&Lvalue, Span)) { (lvalue, span): (&Lvalue, Span),
borrow : &BorrowData) {
let described_lvalue = self.describe_lvalue(lvalue);
let borrow_span = self.retrieve_borrow_span(borrow);
let mut err = self.tcx.cannot_use_when_mutably_borrowed( let mut err = self.tcx.cannot_use_when_mutably_borrowed(
span, &self.describe_lvalue(lvalue), Origin::Mir); span, &described_lvalue, Origin::Mir);
// FIXME 1: add span_label for "borrow of `()` occurs here"
// FIXME 2: add span_label for "use of `{}` occurs here" err.span_label(borrow_span, format!("borrow of `{}` occurs here", described_lvalue));
err.span_label(span, format!("use of borrowed `{}`", described_lvalue));
err.emit(); err.emit();
} }
@ -998,7 +1004,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
ProjectionElem::Downcast(..) => ProjectionElem::Downcast(..) =>
("", format!(""), None), // (dont emit downcast info) ("", format!(""), None), // (dont emit downcast info)
ProjectionElem::Field(field, _ty) => ProjectionElem::Field(field, _ty) =>
("", format!(".{}", field.index()), None), ("", format!(".{}", field.index()), None), // FIXME: report name of field
ProjectionElem::Index(index) => ProjectionElem::Index(index) =>
("", format!(""), Some(index)), ("", format!(""), Some(index)),
ProjectionElem::ConstantIndex { offset, min_length, from_end: true } => ProjectionElem::ConstantIndex { offset, min_length, from_end: true } =>
@ -1024,6 +1030,13 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx>
} }
} }
} }
// Retrieve span of given borrow from the current MIR representation
fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span {
self.mir.basic_blocks()[borrow.location.block]
.statements[borrow.location.statement_index]
.source_info.span
}
} }
impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> { impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> {

View File

@ -2621,7 +2621,8 @@ fn render_assoc_item(w: &mut fmt::Formatter,
href(did).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor) href(did).map(|p| format!("{}#{}.{}", p.0, ty, name)).unwrap_or(anchor)
} }
}; };
let mut head_len = format!("{}{}{:#}fn {}{:#}", let mut head_len = format!("{}{}{}{:#}fn {}{:#}",
VisSpace(&meth.visibility),
ConstnessSpace(constness), ConstnessSpace(constness),
UnsafetySpace(unsafety), UnsafetySpace(unsafety),
AbiSpace(abi), AbiSpace(abi),
@ -2633,8 +2634,9 @@ fn render_assoc_item(w: &mut fmt::Formatter,
} else { } else {
(0, true) (0, true)
}; };
write!(w, "{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\ write!(w, "{}{}{}{}fn <a href='{href}' class='fnname'>{name}</a>\
{generics}{decl}{where_clause}", {generics}{decl}{where_clause}",
VisSpace(&meth.visibility),
ConstnessSpace(constness), ConstnessSpace(constness),
UnsafetySpace(unsafety), UnsafetySpace(unsafety),
AbiSpace(abi), AbiSpace(abi),

View File

@ -1595,9 +1595,9 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
/// ///
/// Notable exception is made for situations where any of the directories /// Notable exception is made for situations where any of the directories
/// specified in the `path` could not be created as it was being created concurrently. /// specified in the `path` could not be created as it was being created concurrently.
/// Such cases are considered success. In other words: calling `create_dir_all` /// Such cases are considered to be successful. That is, calling `create_dir_all`
/// concurrently from multiple threads or processes is guaranteed to not fail /// concurrently from multiple threads or processes is guaranteed not to fail
/// due to race itself. /// due to a race condition with itself.
/// ///
/// # Examples /// # Examples
/// ///

View File

@ -40,9 +40,10 @@ use mem;
/// ///
/// io::copy(&mut reader, &mut writer)?; /// io::copy(&mut reader, &mut writer)?;
/// ///
/// assert_eq!(reader, &writer[..]); /// assert_eq!(&b"hello"[..], &writer[..]);
/// # Ok(()) /// # Ok(())
/// # } /// # }
/// # foo().unwrap();
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64> pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> io::Result<u64>

View File

@ -710,6 +710,10 @@ mod prim_u128 { }
// //
/// The pointer-sized signed integer type. /// The pointer-sized signed integer type.
/// ///
/// The size of this primitive is how many bytes it takes to reference any
/// location in memory. For example, on a 32 bit target, this is 4 bytes
/// and on a 64 bit target, this is 8 bytes.
///
/// *[See also the `std::isize` module](isize/index.html).* /// *[See also the `std::isize` module](isize/index.html).*
/// ///
/// However, please note that examples are shared between primitive integer /// However, please note that examples are shared between primitive integer
@ -722,6 +726,10 @@ mod prim_isize { }
// //
/// The pointer-sized unsigned integer type. /// The pointer-sized unsigned integer type.
/// ///
/// The size of this primitive is how many bytes it takes to reference any
/// location in memory. For example, on a 32 bit target, this is 4 bytes
/// and on a 64 bit target, this is 8 bytes.
///
/// *[See also the `std::usize` module](usize/index.html).* /// *[See also the `std::usize` module](usize/index.html).*
/// ///
/// However, please note that examples are shared between primitive integer /// However, please note that examples are shared between primitive integer

View File

@ -24,19 +24,24 @@ use sys_common::rwlock as sys;
/// of the underlying data (exclusive access) and the read portion of this lock /// of the underlying data (exclusive access) and the read portion of this lock
/// typically allows for read-only access (shared access). /// typically allows for read-only access (shared access).
/// ///
/// In comparison, a [`Mutex`] does not distinguish between readers or writers
/// that aquire the lock, therefore blocking any threads waiting for the lock to
/// become available. An `RwLock` will allow any number of readers to aquire the
/// lock as long as a writer is not holding the lock.
///
/// The priority policy of the lock is dependent on the underlying operating /// The priority policy of the lock is dependent on the underlying operating
/// system's implementation, and this type does not guarantee that any /// system's implementation, and this type does not guarantee that any
/// particular policy will be used. /// particular policy will be used.
/// ///
/// The type parameter `T` represents the data that this lock protects. It is /// The type parameter `T` represents the data that this lock protects. It is
/// required that `T` satisfies `Send` to be shared across threads and `Sync` to /// required that `T` satisfies [`Send`] to be shared across threads and
/// allow concurrent access through readers. The RAII guards returned from the /// [`Sync`] to allow concurrent access through readers. The RAII guards
/// locking methods implement `Deref` (and `DerefMut` for the `write` methods) /// returned from the locking methods implement [`Deref`][] (and [`DerefMut`]
/// to allow access to the contained of the lock. /// for the `write` methods) to allow access to the contained of the lock.
/// ///
/// # Poisoning /// # Poisoning
/// ///
/// An `RwLock`, like `Mutex`, will become poisoned on a panic. Note, however, /// An `RwLock`, like [`Mutex`], will become poisoned on a panic. Note, however,
/// that an `RwLock` may only be poisoned if a panic occurs while it is locked /// that an `RwLock` may only be poisoned if a panic occurs while it is locked
/// exclusively (write mode). If a panic occurs in any reader, then the lock /// exclusively (write mode). If a panic occurs in any reader, then the lock
/// will not be poisoned. /// will not be poisoned.
@ -63,6 +68,12 @@ use sys_common::rwlock as sys;
/// assert_eq!(*w, 6); /// assert_eq!(*w, 6);
/// } // write lock is dropped here /// } // write lock is dropped here
/// ``` /// ```
///
/// [`Deref`]: ../../std/ops/trait.Deref.html
/// [`DerefMut`]: ../../std/ops/trait.DerefMut.html
/// [`Send`]: ../../std/marker/trait.Send.html
/// [`Sync`]: ../../std/marker/trait.Sync.html
/// [`Mutex`]: struct.Mutex.html
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub struct RwLock<T: ?Sized> { pub struct RwLock<T: ?Sized> {
inner: Box<sys::RWLock>, inner: Box<sys::RWLock>,
@ -154,6 +165,24 @@ impl<T: ?Sized> RwLock<T> {
/// # Panics /// # Panics
/// ///
/// This function might panic when called if the lock is already held by the current thread. /// This function might panic when called if the lock is already held by the current thread.
///
/// # Examples
///
/// ```
/// use std::sync::{Arc, RwLock};
/// use std::thread;
///
/// let lock = Arc::new(RwLock::new(1));
/// let c_lock = lock.clone();
///
/// let n = lock.read().unwrap();
/// assert_eq!(*n, 1);
///
/// thread::spawn(move || {
/// let r = c_lock.read();
/// assert!(r.is_ok());
/// }).join().unwrap();
/// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn read(&self) -> LockResult<RwLockReadGuard<T>> { pub fn read(&self) -> LockResult<RwLockReadGuard<T>> {
@ -180,6 +209,19 @@ impl<T: ?Sized> RwLock<T> {
/// is poisoned whenever a writer panics while holding an exclusive lock. An /// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been /// error will only be returned if the lock would have otherwise been
/// acquired. /// acquired.
///
/// # Examples
///
/// ```
/// use std::sync::RwLock;
///
/// let lock = RwLock::new(1);
///
/// match lock.try_read() {
/// Ok(n) => assert_eq!(*n, 1),
/// Err(_) => unreachable!(),
/// };
/// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> { pub fn try_read(&self) -> TryLockResult<RwLockReadGuard<T>> {
@ -210,6 +252,19 @@ impl<T: ?Sized> RwLock<T> {
/// # Panics /// # Panics
/// ///
/// This function might panic when called if the lock is already held by the current thread. /// This function might panic when called if the lock is already held by the current thread.
///
/// # Examples
///
/// ```
/// use std::sync::RwLock;
///
/// let lock = RwLock::new(1);
///
/// let mut n = lock.write().unwrap();
/// *n = 2;
///
/// assert!(lock.try_read().is_err());
/// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> { pub fn write(&self) -> LockResult<RwLockWriteGuard<T>> {
@ -236,6 +291,19 @@ impl<T: ?Sized> RwLock<T> {
/// is poisoned whenever a writer panics while holding an exclusive lock. An /// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been /// error will only be returned if the lock would have otherwise been
/// acquired. /// acquired.
///
/// # Examples
///
/// ```
/// use std::sync::RwLock;
///
/// let lock = RwLock::new(1);
///
/// let n = lock.read().unwrap();
/// assert_eq!(*n, 1);
///
/// assert!(lock.try_write().is_err());
/// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> { pub fn try_write(&self) -> TryLockResult<RwLockWriteGuard<T>> {
@ -253,6 +321,22 @@ impl<T: ?Sized> RwLock<T> {
/// If another thread is active, the lock can still become poisoned at any /// If another thread is active, the lock can still become poisoned at any
/// time. You should not trust a `false` value for program correctness /// time. You should not trust a `false` value for program correctness
/// without additional synchronization. /// without additional synchronization.
///
/// # Examples
///
/// ```
/// use std::sync::{Arc, RwLock};
/// use std::thread;
///
/// let lock = Arc::new(RwLock::new(0));
/// let c_lock = lock.clone();
///
/// let _ = thread::spawn(move || {
/// let _lock = c_lock.write().unwrap();
/// panic!(); // the lock gets poisoned
/// }).join();
/// assert_eq!(lock.is_poisoned(), true);
/// ```
#[inline] #[inline]
#[stable(feature = "sync_poison", since = "1.2.0")] #[stable(feature = "sync_poison", since = "1.2.0")]
pub fn is_poisoned(&self) -> bool { pub fn is_poisoned(&self) -> bool {
@ -267,6 +351,19 @@ impl<T: ?Sized> RwLock<T> {
/// is poisoned whenever a writer panics while holding an exclusive lock. An /// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been /// error will only be returned if the lock would have otherwise been
/// acquired. /// acquired.
///
/// # Examples
///
/// ```
/// use std::sync::RwLock;
///
/// let lock = RwLock::new(String::new());
/// {
/// let mut s = lock.write().unwrap();
/// *s = "modified".to_owned();
/// }
/// assert_eq!(lock.into_inner().unwrap(), "modified");
/// ```
#[stable(feature = "rwlock_into_inner", since = "1.6.0")] #[stable(feature = "rwlock_into_inner", since = "1.6.0")]
pub fn into_inner(self) -> LockResult<T> where T: Sized { pub fn into_inner(self) -> LockResult<T> where T: Sized {
// We know statically that there are no outstanding references to // We know statically that there are no outstanding references to
@ -300,6 +397,16 @@ impl<T: ?Sized> RwLock<T> {
/// is poisoned whenever a writer panics while holding an exclusive lock. An /// is poisoned whenever a writer panics while holding an exclusive lock. An
/// error will only be returned if the lock would have otherwise been /// error will only be returned if the lock would have otherwise been
/// acquired. /// acquired.
///
/// # Examples
///
/// ```
/// use std::sync::RwLock;
///
/// let mut lock = RwLock::new(0);
/// *lock.get_mut().unwrap() = 10;
/// assert_eq!(*lock.read().unwrap(), 10);
/// ```
#[stable(feature = "rwlock_get_mut", since = "1.6.0")] #[stable(feature = "rwlock_get_mut", since = "1.6.0")]
pub fn get_mut(&mut self) -> LockResult<&mut T> { pub fn get_mut(&mut self) -> LockResult<&mut T> {
// We know statically that there are no other references to `self`, so // We know statically that there are no other references to `self`, so

View File

@ -2632,7 +2632,7 @@ impl<'a> Parser<'a> {
self.bump(); self.bump();
let e = self.parse_prefix_expr(None); let e = self.parse_prefix_expr(None);
let (span, e) = self.interpolated_or_expr_span(e)?; let (span, e) = self.interpolated_or_expr_span(e)?;
(span, self.mk_unary(UnOp::Not, e)) (lo.to(span), self.mk_unary(UnOp::Not, e))
} }
// Suggest `!` for bitwise negation when encountering a `~` // Suggest `!` for bitwise negation when encountering a `~`
token::Tilde => { token::Tilde => {
@ -2645,26 +2645,26 @@ impl<'a> Parser<'a> {
err.span_label(span_of_tilde, "did you mean `!`?"); err.span_label(span_of_tilde, "did you mean `!`?");
err.help("use `!` instead of `~` if you meant to perform bitwise negation"); err.help("use `!` instead of `~` if you meant to perform bitwise negation");
err.emit(); err.emit();
(span, self.mk_unary(UnOp::Not, e)) (lo.to(span), self.mk_unary(UnOp::Not, e))
} }
token::BinOp(token::Minus) => { token::BinOp(token::Minus) => {
self.bump(); self.bump();
let e = self.parse_prefix_expr(None); let e = self.parse_prefix_expr(None);
let (span, e) = self.interpolated_or_expr_span(e)?; let (span, e) = self.interpolated_or_expr_span(e)?;
(span, self.mk_unary(UnOp::Neg, e)) (lo.to(span), self.mk_unary(UnOp::Neg, e))
} }
token::BinOp(token::Star) => { token::BinOp(token::Star) => {
self.bump(); self.bump();
let e = self.parse_prefix_expr(None); let e = self.parse_prefix_expr(None);
let (span, e) = self.interpolated_or_expr_span(e)?; let (span, e) = self.interpolated_or_expr_span(e)?;
(span, self.mk_unary(UnOp::Deref, e)) (lo.to(span), self.mk_unary(UnOp::Deref, e))
} }
token::BinOp(token::And) | token::AndAnd => { token::BinOp(token::And) | token::AndAnd => {
self.expect_and()?; self.expect_and()?;
let m = self.parse_mutability(); let m = self.parse_mutability();
let e = self.parse_prefix_expr(None); let e = self.parse_prefix_expr(None);
let (span, e) = self.interpolated_or_expr_span(e)?; let (span, e) = self.interpolated_or_expr_span(e)?;
(span, ExprKind::AddrOf(m, e)) (lo.to(span), ExprKind::AddrOf(m, e))
} }
token::Ident(..) if self.token.is_keyword(keywords::In) => { token::Ident(..) if self.token.is_keyword(keywords::In) => {
self.bump(); self.bump();
@ -2675,13 +2675,13 @@ impl<'a> Parser<'a> {
let blk = self.parse_block()?; let blk = self.parse_block()?;
let span = blk.span; let span = blk.span;
let blk_expr = self.mk_expr(span, ExprKind::Block(blk), ThinVec::new()); let blk_expr = self.mk_expr(span, ExprKind::Block(blk), ThinVec::new());
(span, ExprKind::InPlace(place, blk_expr)) (lo.to(span), ExprKind::InPlace(place, blk_expr))
} }
token::Ident(..) if self.token.is_keyword(keywords::Box) => { token::Ident(..) if self.token.is_keyword(keywords::Box) => {
self.bump(); self.bump();
let e = self.parse_prefix_expr(None); let e = self.parse_prefix_expr(None);
let (span, e) = self.interpolated_or_expr_span(e)?; let (span, e) = self.interpolated_or_expr_span(e)?;
(span, ExprKind::Box(e)) (lo.to(span), ExprKind::Box(e))
} }
_ => return self.parse_dot_or_call_expr(Some(attrs)) _ => return self.parse_dot_or_call_expr(Some(attrs))
}; };

View File

@ -13,6 +13,7 @@
#![allow(unused_features)] #![allow(unused_features)]
#![feature(box_syntax)] #![feature(box_syntax)]
use std::cell::RefCell;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use std::usize; use std::usize;
@ -240,6 +241,8 @@ pub fn main() {
// test that trailing commas are acceptable // test that trailing commas are acceptable
format!("{}", "test",); format!("{}", "test",);
format!("{foo}", foo="test",); format!("{foo}", foo="test",);
test_refcell();
} }
// Basic test to make sure that we can invoke the `write!` macro with an // Basic test to make sure that we can invoke the `write!` macro with an
@ -319,3 +322,12 @@ fn test_once() {
assert_eq!(format!("{0} {0} {0} {a} {a} {a}", foo(), a=foo()), assert_eq!(format!("{0} {0} {0} {a} {a} {a}", foo(), a=foo()),
"1 1 1 2 2 2".to_string()); "1 1 1 2 2 2".to_string());
} }
fn test_refcell() {
let refcell = RefCell::new(5);
assert_eq!(format!("{:?}", refcell), "RefCell { value: 5 }");
let borrow = refcell.borrow_mut();
assert_eq!(format!("{:?}", refcell), "RefCell { value: <borrowed> }");
drop(borrow);
assert_eq!(format!("{:?}", refcell), "RefCell { value: 5 }");
}

View File

@ -0,0 +1,24 @@
// 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.
//! dox
#![deny(missing_docs)]
macro_rules! doc {
($e:expr) => (
#[doc = $e]
pub struct Foo;
)
}
doc!("a");
fn main() {}

View File

@ -0,0 +1,31 @@
// 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.
// ignore-tidy-linelength
// compile-flags: --no-defaults --passes collapse-docs --passes unindent-comments --passes strip-priv-imports
#![crate_name = "foo"]
// @has foo/fn.bar.html
// @has - '//*[@class="rust fn"]' 'pub fn bar() -> '
/// foo
pub fn bar() -> usize {
2
}
// @has foo/struct.Foo.html
// @has - '//*[@class="method"]' 'pub fn new()'
// @has - '//*[@class="method"]' 'fn not_pub()'
pub struct Foo(usize);
impl Foo {
pub fn new() -> Foo { Foo(0) }
fn not_pub() {}
}