diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index b7be8042ea49f..8a45715e89c91 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -867,12 +867,10 @@ impl Arc { unsafe fn drop_slow(&mut self) { // Destroy the data at this time, even though we may not free the box // allocation itself (there may still be weak pointers lying around). - ptr::drop_in_place(&mut self.ptr.as_mut().data); + ptr::drop_in_place(Self::get_mut_unchecked(self)); - if self.inner().weak.fetch_sub(1, Release) == 1 { - acquire!(self.inner().weak); - Global.dealloc(self.ptr.cast(), Layout::for_value(self.ptr.as_ref())) - } + // Drop the weak ref collectively held by all strong references + drop(Weak { ptr: self.ptr }); } #[inline] @@ -1204,7 +1202,7 @@ impl Arc { // As with `get_mut()`, the unsafety is ok because our reference was // either unique to begin with, or became one upon cloning the contents. - unsafe { &mut this.ptr.as_mut().data } + unsafe { Self::get_mut_unchecked(this) } } } @@ -1280,7 +1278,9 @@ impl Arc { #[inline] #[unstable(feature = "get_mut_unchecked", issue = "63292")] pub unsafe fn get_mut_unchecked(this: &mut Self) -> &mut T { - &mut this.ptr.as_mut().data + // We are careful to *not* create a reference covering the "count" fields, as + // this would alias with concurrent access to the reference counts (e.g. by `Weak`). + &mut (*this.ptr.as_ptr()).data } /// Determine whether this is the unique reference (including weak refs) to @@ -1571,6 +1571,13 @@ impl Weak { } } +/// Helper type to allow accessing the reference counts without +/// making any assertions about the data field. +struct WeakInner<'a> { + weak: &'a atomic::AtomicUsize, + strong: &'a atomic::AtomicUsize, +} + impl Weak { /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying /// dropping of the inner value if successful. @@ -1678,8 +1685,18 @@ impl Weak { /// Returns `None` when the pointer is dangling and there is no allocated `ArcInner`, /// (i.e., when this `Weak` was created by `Weak::new`). #[inline] - fn inner(&self) -> Option<&ArcInner> { - if is_dangling(self.ptr) { None } else { Some(unsafe { self.ptr.as_ref() }) } + fn inner(&self) -> Option> { + if is_dangling(self.ptr) { + None + } else { + // We are careful to *not* create a reference covering the "data" field, as + // the field may be mutated concurrently (for example, if the last `Arc` + // is dropped, the data field will be dropped in-place). + Some(unsafe { + let ptr = self.ptr.as_ptr(); + WeakInner { strong: &(*ptr).strong, weak: &(*ptr).weak } + }) + } } /// Returns `true` if the two `Weak`s point to the same allocation (similar to diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index fad3095f8a3fc..c4c1d2824b098 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -849,11 +849,11 @@ impl RefCell { /// ``` /// use std::cell::RefCell; /// - /// let c = RefCell::new(5); + /// let c = RefCell::new("hello".to_owned()); /// - /// *c.borrow_mut() = 7; + /// *c.borrow_mut() = "bonjour".to_owned(); /// - /// assert_eq!(*c.borrow(), 7); + /// assert_eq!(&*c.borrow(), "bonjour"); /// ``` /// /// An example of panic: diff --git a/src/libcore/iter/traits/double_ended.rs b/src/libcore/iter/traits/double_ended.rs index cceb373d552a8..f6329c6c593ed 100644 --- a/src/libcore/iter/traits/double_ended.rs +++ b/src/libcore/iter/traits/double_ended.rs @@ -63,6 +63,32 @@ pub trait DoubleEndedIterator: Iterator { /// assert_eq!(None, iter.next()); /// assert_eq!(None, iter.next_back()); /// ``` + /// + /// # Remarks + /// + /// The elements yielded by `DoubleEndedIterator`'s methods may differ from + /// the ones yielded by `Iterator`'s methods: + /// + /// ``` + /// let vec = vec![(1, 'a'), (1, 'b'), (1, 'c'), (2, 'a'), (2, 'b')]; + /// let uniq_by_fst_comp = || { + /// let mut seen = std::collections::HashSet::new(); + /// vec.iter().copied().filter(move |x| seen.insert(x.0)) + /// }; + /// + /// assert_eq!(uniq_by_fst_comp().last(), Some((2, 'a'))); + /// assert_eq!(uniq_by_fst_comp().next_back(), Some((2, 'b'))); + /// + /// assert_eq!( + /// uniq_by_fst_comp().fold(vec![], |mut v, x| {v.push(x); v}), + /// vec![(1, 'a'), (2, 'a')] + /// ); + /// assert_eq!( + /// uniq_by_fst_comp().rfold(vec![], |mut v, x| {v.push(x); v}), + /// vec![(2, 'b'), (1, 'c')] + /// ); + /// ``` + /// #[stable(feature = "rust1", since = "1.0.0")] fn next_back(&mut self) -> Option; diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs index f05d018613852..660a63841bcef 100644 --- a/src/librustc_parse/parser/diagnostics.rs +++ b/src/librustc_parse/parser/diagnostics.rs @@ -935,6 +935,19 @@ impl<'a> Parser<'a> { return self.expect(&token::Semi).map(drop); } else if !sm.is_multiline(self.prev_token.span.until(self.token.span)) { // The current token is in the same line as the prior token, not recoverable. + } else if [token::Comma, token::Colon].contains(&self.token.kind) + && &self.prev_token.kind == &token::CloseDelim(token::Paren) + { + // Likely typo: The current token is on a new line and is expected to be + // `.`, `;`, `?`, or an operator after a close delimiter token. + // + // let a = std::process::Command::new("echo") + // .arg("1") + // ,arg("2") + // ^ + // https://github.com/rust-lang/rust/issues/72253 + self.expect(&token::Semi)?; + return Ok(()); } else if self.look_ahead(1, |t| { t == &token::CloseDelim(token::Brace) || t.can_begin_expr() && t.kind != token::Colon }) && [token::Comma, token::Colon].contains(&self.token.kind) diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css index b1e0ab9ca64fd..2cb3347135c1b 100644 --- a/src/librustdoc/html/static/rustdoc.css +++ b/src/librustdoc/html/static/rustdoc.css @@ -3,14 +3,12 @@ font-family: 'Fira Sans'; font-style: normal; font-weight: 400; - font-display: optional; src: local('Fira Sans'), url("FiraSans-Regular.woff") format('woff'); } @font-face { font-family: 'Fira Sans'; font-style: normal; font-weight: 500; - font-display: optional; src: local('Fira Sans Medium'), url("FiraSans-Medium.woff") format('woff'); } @@ -19,23 +17,18 @@ font-family: 'Source Serif Pro'; font-style: normal; font-weight: 400; - /* The difference for body text without this font is greater than other fonts, - * so the 0~100ms block of fallback is preferred over optional, for legibility. */ - font-display: fallback; src: local('Source Serif Pro'), url("SourceSerifPro-Regular.ttf.woff") format('woff'); } @font-face { font-family: 'Source Serif Pro'; font-style: italic; font-weight: 400; - font-display: optional; src: local('Source Serif Pro Italic'), url("SourceSerifPro-It.ttf.woff") format('woff'); } @font-face { font-family: 'Source Serif Pro'; font-style: normal; font-weight: 700; - font-display: optional; src: local('Source Serif Pro Bold'), url("SourceSerifPro-Bold.ttf.woff") format('woff'); } @@ -44,7 +37,6 @@ font-family: 'Source Code Pro'; font-style: normal; font-weight: 400; - font-display: optional; /* Avoid using locally installed font because bad versions are in circulation: * see https://github.com/rust-lang/rust/issues/24355 */ src: url("SourceCodePro-Regular.woff") format('woff'); @@ -53,7 +45,6 @@ font-family: 'Source Code Pro'; font-style: normal; font-weight: 600; - font-display: optional; src: url("SourceCodePro-Semibold.woff") format('woff'); } diff --git a/src/test/ui/issues/issue-50687-ice-on-borrow.rs b/src/test/ui/issues/issue-50687-ice-on-borrow.rs new file mode 100644 index 0000000000000..7a8a12c2a93af --- /dev/null +++ b/src/test/ui/issues/issue-50687-ice-on-borrow.rs @@ -0,0 +1,41 @@ +// This previously caused an ICE at: +// librustc/traits/structural_impls.rs:180: impossible case reached + +#![no_main] + +use std::borrow::Borrow; +use std::io; +use std::io::Write; + +trait Constraint {} + +struct Container { + t: T, +} + +struct Borrowed; +struct Owned; + +impl<'a, T> Write for &'a Container +where + T: Constraint, + &'a T: Write, +{ + fn write(&mut self, buf: &[u8]) -> io::Result { + Ok(buf.len()) + } + + fn flush(&mut self) -> io::Result<()> { + Ok(()) + } +} + +impl Borrow for Owned { + fn borrow(&self) -> &Borrowed { + &Borrowed + } +} + +fn func(owned: Owned) { + let _: () = Borrow::borrow(&owned); //~ ERROR mismatched types +} diff --git a/src/test/ui/issues/issue-50687-ice-on-borrow.stderr b/src/test/ui/issues/issue-50687-ice-on-borrow.stderr new file mode 100644 index 0000000000000..f6adfc87dad33 --- /dev/null +++ b/src/test/ui/issues/issue-50687-ice-on-borrow.stderr @@ -0,0 +1,16 @@ +error[E0308]: mismatched types + --> $DIR/issue-50687-ice-on-borrow.rs:40:17 + | +LL | let _: () = Borrow::borrow(&owned); + | -- ^^^^^^^^^^^^^^^^^^^^^^ + | | | + | | expected `()`, found reference + | | help: consider dereferencing the borrow: `*Borrow::borrow(&owned)` + | expected due to this + | + = note: expected unit type `()` + found reference `&_` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/issues/issue-72253.rs b/src/test/ui/issues/issue-72253.rs new file mode 100644 index 0000000000000..6f9af73b039e4 --- /dev/null +++ b/src/test/ui/issues/issue-72253.rs @@ -0,0 +1,6 @@ +fn main() { + let a = std::process::Command::new("echo") + .arg("1") + ,arg("2") //~ ERROR expected one of `.`, `;`, `?`, or an operator, found `,` + .output(); +} diff --git a/src/test/ui/issues/issue-72253.stderr b/src/test/ui/issues/issue-72253.stderr new file mode 100644 index 0000000000000..3819fd92a9e21 --- /dev/null +++ b/src/test/ui/issues/issue-72253.stderr @@ -0,0 +1,10 @@ +error: expected one of `.`, `;`, `?`, or an operator, found `,` + --> $DIR/issue-72253.rs:4:9 + | +LL | .arg("1") + | - expected one of `.`, `;`, `?`, or an operator +LL | ,arg("2") + | ^ unexpected token + +error: aborting due to previous error +