mirror of https://github.com/rust-lang/rust.git
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:
commit
85a5d3ffa4
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
///
|
///
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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")]
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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
|
||||||
/ | \
|
/ | \
|
||||||
/ | \
|
/ | \
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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> {
|
||||||
|
|
|
@ -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),
|
||||||
|
|
|
@ -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
|
||||||
///
|
///
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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))
|
||||||
};
|
};
|
||||||
|
|
|
@ -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 }");
|
||||||
|
}
|
||||||
|
|
|
@ -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() {}
|
|
@ -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() {}
|
||||||
|
}
|
Loading…
Reference in New Issue