diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 72144f22f5c..3834c54d6c4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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 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 discuss Rust's internals * 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 [rif]: http://internals.rust-lang.org [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/ [ro]: http://www.rustaceans.org/ [rctd]: ./src/test/COMPILER_TESTS.md diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 4b695ad7c79..3b7dbd813cf 100644 --- a/src/liballoc/arc.rs +++ b/src/liballoc/arc.rs @@ -72,13 +72,13 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize; /// first: after all, isn't the point of `Arc` thread safety? The key is /// this: `Arc` makes it thread safe to have multiple ownership of the same /// data, but it doesn't add thread safety to its data. Consider -/// `Arc>`. `RefCell` isn't [`Sync`], and if `Arc` was always -/// [`Send`], `Arc>` would be as well. But then we'd have a problem: -/// `RefCell` is not thread safe; it keeps track of the borrowing count using +/// `Arc<`[`RefCell`]`>`. [`RefCell`] isn't [`Sync`], and if `Arc` was always +/// [`Send`], `Arc<`[`RefCell`]`>` would be as well. But then we'd have a problem: +/// [`RefCell`] is not thread safe; it keeps track of the borrowing count using /// non-atomic operations. /// /// In the end, this means that you may need to pair `Arc` with some sort of -/// `std::sync` type, usually `Mutex`. +/// [`std::sync`] type, usually [`Mutex`][mutex]. /// /// ## 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. /// ``` /// -/// 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 /// 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 /// [`None`]: ../../std/option/enum.Option.html#variant.None /// [assoc]: ../../book/first-edition/method-syntax.html#associated-functions +/// [`RefCell`]: ../../std/cell/struct.RefCell.html +/// [`std::sync`]: ../../std/sync/index.html +/// [`Arc::clone(&from)`]: #method.clone /// /// # Examples /// diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index cf6262bda97..b84a1deb611 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1700,8 +1700,18 @@ impl Debug for RefCell { .finish() } 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("") + } + } + f.debug_struct("RefCell") - .field("value", &"") + .field("value", &BorrowedPlaceholder) .finish() } } diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 34994dc3b70..669b93120cf 100644 --- a/src/libcore/mem.rs +++ b/src/libcore/mem.rs @@ -177,15 +177,59 @@ pub fn forget(t: T) { /// Returns the size of a type in bytes. /// -/// More specifically, this is the offset in bytes between successive -/// items of the same type, including alignment padding. +/// More specifically, this is the offset in bytes between successive elements +/// 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::()`. +/// +/// 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::\() +/// ---- | --------------- +/// () | 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`, `Option<&T>`, and `Option>` 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 /// /// ``` /// use std::mem; /// +/// // Some primitives /// assert_eq!(4, mem::size_of::()); +/// assert_eq!(8, mem::size_of::()); +/// 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::>()); +/// assert_eq!(mem::size_of::<&i32>(), mem::size_of::>()); +/// assert_eq!(mem::size_of::>(), mem::size_of::>>()); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index c24cdb30bad..5d0cefa1013 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1399,9 +1399,6 @@ Section: Comparing strings */ /// 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] fn eq_slice(a: &str, b: &str) -> bool { a.as_bytes() == b.as_bytes() diff --git a/src/librustc/README.md b/src/librustc/README.md index 59d346db4af..87de284d011 100644 --- a/src/librustc/README.md +++ b/src/librustc/README.md @@ -37,7 +37,7 @@ incremental improves that may change.) The dependency structure of these crates is roughly a diamond: -```` +``` rustc_driver / | \ / | \ diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 465520ea034..fd3050f9b9e 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -65,7 +65,7 @@ use syntax::codemap::{self, respan, Spanned, CompilerDesugaringKind}; use syntax::std_inject; use syntax::symbol::{Symbol, keywords}; 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::visit::{self, Visitor}; use syntax_pos::Span; @@ -606,10 +606,12 @@ impl<'a> LoweringContext<'a> { } 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 { TokenTree::Token(span, token) => { self.lower_token(token, span) @@ -618,23 +620,19 @@ impl<'a> LoweringContext<'a> { TokenTree::Delimited(span, Delimited { delim: delimited.delim, 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 { 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 = self.lower_token_stream(tts); - TokenTree::Delimited(span, Delimited { - delim: DelimToken::NoDelim, - tts: tts.into(), - }) + self.lower_token_stream(tts) } fn lower_arm(&mut self, arm: &Arm) -> hir::Arm { diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 0c0b9697338..679c4f17a6c 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -280,8 +280,6 @@ language_item_table! { EqTraitLangItem, "eq", eq_trait; OrdTraitLangItem, "ord", ord_trait; - StrEqFnLangItem, "str_eq", str_eq_fn; - // A number of panic-related lang items. The `panic` item corresponds to // divide-by-zero and various panic cases with `match`. The // `panic_bounds_check` item is for indexing arrays. diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 96f46b270a1..e87443619ec 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -411,7 +411,8 @@ impl Session { } pub fn emit_end_regions(&self) -> bool { 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 { self.opts.cg.lto diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 063cbc77559..5133e528b09 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -419,7 +419,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> self.each_borrow_involving_path( context, lvalue_span.0, flow_state, |this, _idx, borrow| { 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 } else { 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, _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( - span, &self.describe_lvalue(lvalue), Origin::Mir); - // FIXME 1: add span_label for "borrow of `()` occurs here" - // FIXME 2: add span_label for "use of `{}` occurs here" + span, &described_lvalue, Origin::Mir); + + err.span_label(borrow_span, format!("borrow of `{}` occurs here", described_lvalue)); + err.span_label(span, format!("use of borrowed `{}`", described_lvalue)); + err.emit(); } @@ -998,7 +1004,7 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> ProjectionElem::Downcast(..) => ("", format!(""), None), // (dont emit downcast info) ProjectionElem::Field(field, _ty) => - ("", format!(".{}", field.index()), None), + ("", format!(".{}", field.index()), None), // FIXME: report name of field ProjectionElem::Index(index) => ("", format!(""), Some(index)), 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> { diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index e1e52b9428a..485e75443fe 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2621,7 +2621,8 @@ fn render_assoc_item(w: &mut fmt::Formatter, 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), UnsafetySpace(unsafety), AbiSpace(abi), @@ -2633,8 +2634,9 @@ fn render_assoc_item(w: &mut fmt::Formatter, } else { (0, true) }; - write!(w, "{}{}{}fn {name}\ + write!(w, "{}{}{}{}fn {name}\ {generics}{decl}{where_clause}", + VisSpace(&meth.visibility), ConstnessSpace(constness), UnsafetySpace(unsafety), AbiSpace(abi), diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 99162766081..91600b01298 100644 --- a/src/libstd/fs.rs +++ b/src/libstd/fs.rs @@ -1595,9 +1595,9 @@ pub fn create_dir>(path: P) -> io::Result<()> { /// /// 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. -/// Such cases are considered success. In other words: calling `create_dir_all` -/// concurrently from multiple threads or processes is guaranteed to not fail -/// due to race itself. +/// Such cases are considered to be successful. That is, calling `create_dir_all` +/// concurrently from multiple threads or processes is guaranteed not to fail +/// due to a race condition with itself. /// /// # Examples /// diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index e20f249d3ea..45d281ee34a 100644 --- a/src/libstd/io/util.rs +++ b/src/libstd/io/util.rs @@ -40,9 +40,10 @@ use mem; /// /// io::copy(&mut reader, &mut writer)?; /// -/// assert_eq!(reader, &writer[..]); +/// assert_eq!(&b"hello"[..], &writer[..]); /// # Ok(()) /// # } +/// # foo().unwrap(); /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn copy(reader: &mut R, writer: &mut W) -> io::Result diff --git a/src/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 76ef36cc9a7..1edb35d8fe7 100644 --- a/src/libstd/primitive_docs.rs +++ b/src/libstd/primitive_docs.rs @@ -710,6 +710,10 @@ mod prim_u128 { } // /// 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).* /// /// However, please note that examples are shared between primitive integer @@ -722,6 +726,10 @@ mod prim_isize { } // /// 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).* /// /// However, please note that examples are shared between primitive integer diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 5c5231f4e84..4757faabfb8 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -24,19 +24,24 @@ use sys_common::rwlock as sys; /// of the underlying data (exclusive access) and the read portion of this lock /// 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 /// system's implementation, and this type does not guarantee that any /// particular policy will be used. /// /// 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 -/// allow concurrent access through readers. The RAII guards returned from the -/// locking methods implement `Deref` (and `DerefMut` for the `write` methods) -/// to allow access to the contained of the lock. +/// required that `T` satisfies [`Send`] to be shared across threads and +/// [`Sync`] to allow concurrent access through readers. The RAII guards +/// returned from the locking methods implement [`Deref`][] (and [`DerefMut`] +/// for the `write` methods) to allow access to the contained of the lock. /// /// # 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 /// exclusively (write mode). If a panic occurs in any reader, then the lock /// will not be poisoned. @@ -63,6 +68,12 @@ use sys_common::rwlock as sys; /// assert_eq!(*w, 6); /// } // 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")] pub struct RwLock { inner: Box, @@ -154,6 +165,24 @@ impl RwLock { /// # Panics /// /// 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] #[stable(feature = "rust1", since = "1.0.0")] pub fn read(&self) -> LockResult> { @@ -180,6 +209,19 @@ impl RwLock { /// is poisoned whenever a writer panics while holding an exclusive lock. An /// error will only be returned if the lock would have otherwise been /// acquired. + /// + /// # Examples + /// + /// ``` + /// use std::sync::RwLock; + /// + /// let lock = RwLock::new(1); + /// + /// match lock.try_read() { + /// Ok(n) => assert_eq!(*n, 1), + /// Err(_) => unreachable!(), + /// }; + /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn try_read(&self) -> TryLockResult> { @@ -210,6 +252,19 @@ impl RwLock { /// # Panics /// /// 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] #[stable(feature = "rust1", since = "1.0.0")] pub fn write(&self) -> LockResult> { @@ -236,6 +291,19 @@ impl RwLock { /// is poisoned whenever a writer panics while holding an exclusive lock. An /// error will only be returned if the lock would have otherwise been /// 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] #[stable(feature = "rust1", since = "1.0.0")] pub fn try_write(&self) -> TryLockResult> { @@ -253,6 +321,22 @@ impl RwLock { /// If another thread is active, the lock can still become poisoned at any /// time. You should not trust a `false` value for program correctness /// 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] #[stable(feature = "sync_poison", since = "1.2.0")] pub fn is_poisoned(&self) -> bool { @@ -267,6 +351,19 @@ impl RwLock { /// is poisoned whenever a writer panics while holding an exclusive lock. An /// error will only be returned if the lock would have otherwise been /// 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")] pub fn into_inner(self) -> LockResult where T: Sized { // We know statically that there are no outstanding references to @@ -282,7 +379,7 @@ impl RwLock { (ptr::read(inner), ptr::read(poison), ptr::read(data)) }; mem::forget(self); - inner.destroy(); // Keep in sync with the `Drop` impl. + inner.destroy(); // Keep in sync with the `Drop` impl. drop(inner); poison::map_result(poison.borrow(), |_| data.into_inner()) @@ -300,6 +397,16 @@ impl RwLock { /// is poisoned whenever a writer panics while holding an exclusive lock. An /// error will only be returned if the lock would have otherwise been /// 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")] pub fn get_mut(&mut self) -> LockResult<&mut T> { // We know statically that there are no other references to `self`, so @@ -486,7 +593,7 @@ mod tests { fn test_rw_arc_poison_wr() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); - let _: Result<(), _> = thread::spawn(move|| { + let _: Result<(), _> = thread::spawn(move || { let _lock = arc2.write().unwrap(); panic!(); }).join(); @@ -498,7 +605,7 @@ mod tests { let arc = Arc::new(RwLock::new(1)); assert!(!arc.is_poisoned()); let arc2 = arc.clone(); - let _: Result<(), _> = thread::spawn(move|| { + let _: Result<(), _> = thread::spawn(move || { let _lock = arc2.write().unwrap(); panic!(); }).join(); @@ -510,7 +617,7 @@ mod tests { fn test_rw_arc_no_poison_rr() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); - let _: Result<(), _> = thread::spawn(move|| { + let _: Result<(), _> = thread::spawn(move || { let _lock = arc2.read().unwrap(); panic!(); }).join(); @@ -521,7 +628,7 @@ mod tests { fn test_rw_arc_no_poison_rw() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); - let _: Result<(), _> = thread::spawn(move|| { + let _: Result<(), _> = thread::spawn(move || { let _lock = arc2.read().unwrap(); panic!() }).join(); @@ -535,7 +642,7 @@ mod tests { let arc2 = arc.clone(); let (tx, rx) = channel(); - thread::spawn(move|| { + thread::spawn(move || { let mut lock = arc2.write().unwrap(); for _ in 0..10 { let tmp = *lock; @@ -550,7 +657,7 @@ mod tests { let mut children = Vec::new(); for _ in 0..5 { let arc3 = arc.clone(); - children.push(thread::spawn(move|| { + children.push(thread::spawn(move || { let lock = arc3.read().unwrap(); assert!(*lock >= 0); })); @@ -571,7 +678,7 @@ mod tests { fn test_rw_arc_access_in_unwind() { let arc = Arc::new(RwLock::new(1)); let arc2 = arc.clone(); - let _ = thread::spawn(move|| -> () { + let _ = thread::spawn(move || -> () { struct Unwinder { i: Arc>, } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a2514a04254..3829be40a1e 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2632,7 +2632,7 @@ impl<'a> Parser<'a> { self.bump(); let e = self.parse_prefix_expr(None); 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 `~` token::Tilde => { @@ -2645,26 +2645,26 @@ impl<'a> Parser<'a> { err.span_label(span_of_tilde, "did you mean `!`?"); err.help("use `!` instead of `~` if you meant to perform bitwise negation"); err.emit(); - (span, self.mk_unary(UnOp::Not, e)) + (lo.to(span), self.mk_unary(UnOp::Not, e)) } token::BinOp(token::Minus) => { self.bump(); let e = self.parse_prefix_expr(None); 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) => { self.bump(); let e = self.parse_prefix_expr(None); 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 => { self.expect_and()?; let m = self.parse_mutability(); let e = self.parse_prefix_expr(None); 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) => { self.bump(); @@ -2675,13 +2675,13 @@ impl<'a> Parser<'a> { let blk = self.parse_block()?; let span = blk.span; 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) => { self.bump(); let e = self.parse_prefix_expr(None); 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)) }; diff --git a/src/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index cef2f879f9c..08e9990511f 100644 --- a/src/test/run-pass/ifmt.rs +++ b/src/test/run-pass/ifmt.rs @@ -13,6 +13,7 @@ #![allow(unused_features)] #![feature(box_syntax)] +use std::cell::RefCell; use std::fmt::{self, Write}; use std::usize; @@ -240,6 +241,8 @@ pub fn main() { // test that trailing commas are acceptable format!("{}", "test",); format!("{foo}", foo="test",); + + test_refcell(); } // 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()), "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: }"); + drop(borrow); + assert_eq!(format!("{:?}", refcell), "RefCell { value: 5 }"); +} diff --git a/src/test/run-pass/issue-44730.rs b/src/test/run-pass/issue-44730.rs new file mode 100644 index 00000000000..6e8aba01255 --- /dev/null +++ b/src/test/run-pass/issue-44730.rs @@ -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 or the MIT license +// , 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() {} diff --git a/src/test/rustdoc/pub-method.rs b/src/test/rustdoc/pub-method.rs new file mode 100644 index 00000000000..5998734e4a2 --- /dev/null +++ b/src/test/rustdoc/pub-method.rs @@ -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 or the MIT license +// , 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() {} +}