about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/liballoc/sync.rs35
-rw-r--r--src/libcore/cell.rs6
-rw-r--r--src/libcore/iter/traits/double_ended.rs26
-rw-r--r--src/librustc_parse/parser/diagnostics.rs13
-rw-r--r--src/librustdoc/html/static/rustdoc.css9
-rw-r--r--src/test/ui/issues/issue-50687-ice-on-borrow.rs41
-rw-r--r--src/test/ui/issues/issue-50687-ice-on-borrow.stderr16
-rw-r--r--src/test/ui/issues/issue-72253.rs6
-rw-r--r--src/test/ui/issues/issue-72253.stderr10
9 files changed, 141 insertions, 21 deletions
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index b7be8042ea4..8a45715e89c 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -867,12 +867,10 @@ impl<T: ?Sized> Arc<T> {
     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<T: Clone> Arc<T> {
 
         // 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<T: ?Sized> Arc<T> {
     #[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<T> Weak<T> {
     }
 }
 
+/// 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<T: ?Sized> Weak<T> {
     /// Attempts to upgrade the `Weak` pointer to an [`Arc`], delaying
     /// dropping of the inner value if successful.
@@ -1678,8 +1685,18 @@ impl<T: ?Sized> Weak<T> {
     /// 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<T>> {
-        if is_dangling(self.ptr) { None } else { Some(unsafe { self.ptr.as_ref() }) }
+    fn inner(&self) -> Option<WeakInner<'_>> {
+        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 fad3095f8a3..c4c1d2824b0 100644
--- a/src/libcore/cell.rs
+++ b/src/libcore/cell.rs
@@ -849,11 +849,11 @@ impl<T: ?Sized> RefCell<T> {
     /// ```
     /// 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 cceb373d552..f6329c6c593 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<Self::Item>;
 
diff --git a/src/librustc_parse/parser/diagnostics.rs b/src/librustc_parse/parser/diagnostics.rs
index f05d0186138..660a63841bc 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 b1e0ab9ca64..2cb3347135c 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 00000000000..7a8a12c2a93
--- /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: T,
+}
+
+struct Borrowed;
+struct Owned;
+
+impl<'a, T> Write for &'a Container<T>
+where
+    T: Constraint,
+    &'a T: Write,
+{
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        Ok(buf.len())
+    }
+
+    fn flush(&mut self) -> io::Result<()> {
+        Ok(())
+    }
+}
+
+impl Borrow<Borrowed> 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 00000000000..f6adfc87dad
--- /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 00000000000..6f9af73b039
--- /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 00000000000..3819fd92a9e
--- /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
+