From 07416452304b2c0b41597fdfe63f4b3b00aeecd9 Mon Sep 17 00:00:00 2001 From: "leonardo.yvens" Date: Sun, 17 Sep 2017 13:04:49 -0300 Subject: [PATCH 01/18] Remove unused str_eq lang item It's not a lang item anymore. Also remove outdated note. --- src/libcore/str/mod.rs | 3 --- src/librustc/middle/lang_items.rs | 2 -- 2 files changed, 5 deletions(-) diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index d4fef45ae4e8f..bfbc0b9004ccd 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -1400,9 +1400,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/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 7a6f4fdbb03ac..2dd55fcd121a6 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -281,8 +281,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. From 203d71f50706ab401173e91d1a4c7e593e2762e7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 14 Sep 2017 00:20:04 +0200 Subject: [PATCH 02/18] Add pub visibility for methods as well --- src/librustdoc/html/render.rs | 6 ++++-- src/test/rustdoc/pub-method.rs | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 src/test/rustdoc/pub-method.rs diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 500b75ec659a1..9d1bf6663ffd1 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -2588,7 +2588,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), @@ -2600,8 +2601,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/test/rustdoc/pub-method.rs b/src/test/rustdoc/pub-method.rs new file mode 100644 index 0000000000000..5998734e4a20c --- /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() {} +} From c9099ff11b1d44a4942f448750cafe8e5c2fd915 Mon Sep 17 00:00:00 2001 From: Jack O'Connor Date: Wed, 20 Sep 2017 01:25:47 -0400 Subject: [PATCH 03/18] fix an incorrect assertion in the doc example for `std::io::copy` --- src/libstd/io/util.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libstd/io/util.rs b/src/libstd/io/util.rs index 88f4214296d9c..bff4e5caaa16f 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 From 66a31c7dc167a60bd8719e3f7bf2ae89ac781cff Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Wed, 20 Sep 2017 15:25:44 +0200 Subject: [PATCH 04/18] Make `-Z borrowck-mir` imply that `EndRegion`'s should be emitted. --- src/librustc/session/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index df5a2648e270c..bdff6535713d2 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 From 5bafba47592688e1f0dce051326d33b5bc8491ba Mon Sep 17 00:00:00 2001 From: Matt Ickstadt Date: Wed, 20 Sep 2017 14:08:30 -0500 Subject: [PATCH 05/18] Fix librusc/README.md diagram --- src/librustc/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc/README.md b/src/librustc/README.md index 59d346db4af4d..87de284d011b3 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 / | \ / | \ From 548686ff12322f948652ee6523074b2ce6d2bb06 Mon Sep 17 00:00:00 2001 From: Havvy Date: Sat, 16 Sep 2017 20:40:05 -0700 Subject: [PATCH 06/18] Document stable size_of primitives and pointer size guarantees --- src/libcore/mem.rs | 48 ++++++++++++++++++++++++++++++++++-- src/libstd/primitive_docs.rs | 8 ++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs index 3e24623dad895..e98dab739cb02 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/libstd/primitive_docs.rs b/src/libstd/primitive_docs.rs index 76ef36cc9a733..1edb35d8fe741 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 From 70ef08f213b10e514915e2ab838bc0ff03197758 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Thu, 21 Sep 2017 16:13:03 +0200 Subject: [PATCH 07/18] mir-borrowck: Add method to MIR borrowck context to retrieve the span of a given borrow --- src/librustc_mir/borrow_check.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 063cbc7755915..127ef1f0e0e5f 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1024,6 +1024,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> { From 86a7347fa1096688ff886d6bb92969ed7e20be9b Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Thu, 21 Sep 2017 16:29:54 +0200 Subject: [PATCH 08/18] mir-borrowck: Add borrow data parameter to `report_use_while_mutably_borrowed()` --- src/librustc_mir/borrow_check.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 127ef1f0e0e5f..6ec01faf00025 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,7 +914,8 @@ 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 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" From e84581192d2629be07d622736ecbe6ce95f3ece0 Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Thu, 21 Sep 2017 16:31:34 +0200 Subject: [PATCH 09/18] mir-borrowck: Add span labels to `report_use_while_mutably_borrowed()` --- src/librustc_mir/borrow_check.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index 6ec01faf00025..f718038bb0714 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -916,10 +916,15 @@ impl<'c, 'b, 'a: 'b+'c, 'gcx, 'tcx: 'a> MirBorrowckCtxt<'c, 'b, 'a, 'gcx, 'tcx> _context: Context, (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(); } From 8c1b958cf7ee4143deaf963249f6bbfd2446121e Mon Sep 17 00:00:00 2001 From: Basile Desloges Date: Thu, 21 Sep 2017 16:33:41 +0200 Subject: [PATCH 10/18] mir-borrowck: Add FIXME comment to report name of field instead of index at a later date --- src/librustc_mir/borrow_check.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_mir/borrow_check.rs b/src/librustc_mir/borrow_check.rs index f718038bb0714..5133e528b099a 100644 --- a/src/librustc_mir/borrow_check.rs +++ b/src/librustc_mir/borrow_check.rs @@ -1004,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 } => From 50534425e536f8af16b5f8e994cf1dced548afc5 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 21 Sep 2017 08:13:25 -0700 Subject: [PATCH 11/18] rustc: Don't use DelimToken::None if possible This commit fixes a regression from #44601 where lowering attribute to HIR now involves expanding interpolated tokens to their actual tokens. In that commit all interpolated tokens were surrounded with a `DelimToken::None` group of tokens, but this ended up causing regressions like #44730 where the various attribute parsers in `syntax/attr.rs` weren't ready to cope with `DelimToken::None`. Instead of fixing the parser in `attr.rs` this commit instead opts to just avoid the `DelimToken::None` in the first place, ensuring that the token stream should look the same as it did before where possible. Closes #44730 --- src/librustc/hir/lowering.rs | 20 +++++++++----------- src/test/run-pass/issue-44730.rs | 24 ++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 src/test/run-pass/issue-44730.rs diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index c7ea9c4702869..8536ff0a98819 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/test/run-pass/issue-44730.rs b/src/test/run-pass/issue-44730.rs new file mode 100644 index 0000000000000..6e8aba012552e --- /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() {} From ded73a85e2dd258e81db19d9320f87e5389ae87a Mon Sep 17 00:00:00 2001 From: Seiichi Uchida Date: Fri, 22 Sep 2017 01:19:34 +0900 Subject: [PATCH 12/18] Include unary operator to span for ExprKind::Unary --- src/libsyntax/parse/parser.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a2514a0425429..3829be40a1e3f 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)) }; From cf2bad8d4b6ffc98a1ea6378e83ad011c224ce80 Mon Sep 17 00:00:00 2001 From: Alex Burka Date: Thu, 21 Sep 2017 16:31:39 -0400 Subject: [PATCH 13/18] improve english in create_dir_all docs --- src/libstd/fs.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs index 2a916b819cca3..495f543c87590 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 /// From f9d92d219d266c3161367cc694743e9c0e6d55c7 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 21 Sep 2017 21:52:59 -0700 Subject: [PATCH 14/18] Less confusing placeholder when RefCell is exclusively borrowed Based on ExpHP's comment in https://users.rust-lang.org/t/refcell-borrow-mut-get-strange-result/12994 > it would perhaps be nicer if it didn't put something that could be > misinterpreted as a valid string value The previous Debug implementation would show: RefCell { value: "" } The new one is: RefCell { value: } --- src/libcore/fmt/mod.rs | 12 +++++++++++- src/test/run-pass/ifmt.rs | 12 ++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index cf6262bda9748..b84a1deb61144 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/test/run-pass/ifmt.rs b/src/test/run-pass/ifmt.rs index cef2f879f9cd7..08e9990511fbb 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 }"); +} From b472b2829bc3a7226af75b9a5429fcd12ac92839 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 22 Sep 2017 15:45:37 +0200 Subject: [PATCH 15/18] Add missing links for Arc --- src/liballoc/arc.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/liballoc/arc.rs b/src/liballoc/arc.rs index 4b695ad7c7933..3b7dbd813cf05 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 /// From 84dfade3ccb806d037ebe238e621cff049b2411f Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 22 Sep 2017 17:10:51 -0300 Subject: [PATCH 16/18] Link to Rust forge from CONTRIBUTING.md --- CONTRIBUTING.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c424ca7ab009e..c4335c9b767b3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -401,6 +401,7 @@ are: discuss Rust's internals * The [generated documentation for rust's compiler][gdfrustc] * The [rust reference][rr], even though it doesn't specifically talk about Rust's internals, it's a great resource nonetheless +* [Rust Forge][rustforge] contains supplementary useful documentation * Although out of date, [Tom Lee's great blog article][tlgba] is very helpful * [rustaceans.org][ro] is helpful, but mostly dedicated to IRC * The [Rust Compiler Testing Docs][rctd] @@ -412,6 +413,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 From 9276b8b9b894d8e02a7e80afcf21bffcd1b27642 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 22 Sep 2017 16:27:55 -0400 Subject: [PATCH 17/18] expand text, make link to forge more prominent --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c4335c9b767b3..c1514a7234e5f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -397,11 +397,11 @@ 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] * The [rust reference][rr], even though it doesn't specifically talk about Rust's internals, it's a great resource nonetheless -* [Rust Forge][rustforge] contains supplementary useful documentation * Although out of date, [Tom Lee's great blog article][tlgba] is very helpful * [rustaceans.org][ro] is helpful, but mostly dedicated to IRC * The [Rust Compiler Testing Docs][rctd] From f283875a780662f13d977e05de7ab5fe52604743 Mon Sep 17 00:00:00 2001 From: Lucas Morales Date: Fri, 22 Sep 2017 18:43:09 -0400 Subject: [PATCH 18/18] std::sync::RwLock docs improvement --- src/libstd/sync/rwlock.rs | 133 ++++++++++++++++++++++++++++++++++---- 1 file changed, 120 insertions(+), 13 deletions(-) diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index 5c5231f4e84a3..4757faabfb873 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>, }