about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/dataflow/impls/borrows.rs18
-rw-r--r--src/librustc_typeck/check/method/suggest.rs5
-rw-r--r--src/librustdoc/html/static/main.js26
-rw-r--r--src/librustdoc/html/static/rustdoc.css27
-rw-r--r--src/librustdoc/html/static/styles/main.css7
-rw-r--r--src/libstd/io/mod.rs5
-rw-r--r--src/libsyntax/ast.rs81
-rw-r--r--src/libsyntax/parse/parser.rs62
-rw-r--r--src/test/ui/did_you_mean/bad-assoc-expr.rs6
-rw-r--r--src/test/ui/did_you_mean/bad-assoc-expr.stderr14
-rw-r--r--src/test/ui/did_you_mean/bad-assoc-pat.rs5
-rw-r--r--src/test/ui/did_you_mean/bad-assoc-pat.stderr14
-rw-r--r--src/test/ui/did_you_mean/bad-assoc-ty.rs15
-rw-r--r--src/test/ui/did_you_mean/bad-assoc-ty.stderr38
-rw-r--r--src/test/ui/span/issue-37767.stderr12
-rw-r--r--src/test/ui/span/issue-7575.stderr12
16 files changed, 248 insertions, 99 deletions
diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs
index 25e4b30da80..8083c1debb8 100644
--- a/src/librustc_mir/dataflow/impls/borrows.rs
+++ b/src/librustc_mir/dataflow/impls/borrows.rs
@@ -361,7 +361,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
                 }
             }
 
-            mir::StatementKind::Assign(_, ref rhs) => {
+            mir::StatementKind::Assign(ref lhs, ref rhs) => {
                 // NOTE: if/when the Assign case is revised to inspect
                 // the assigned_place here, make sure to also
                 // re-consider the current implementations of the
@@ -382,6 +382,22 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> {
                         panic!("could not find BorrowIndexs for region {:?}", region);
                     }).contains(&index));
                     sets.gen(&ReserveOrActivateIndex::reserved(*index));
+
+                    if is_activations {
+                        // Issue #46746: Two-phase borrows handles
+                        // stmts of form `Tmp = &mut Borrow` ...
+                        match lhs {
+                            Place::Local(..) => {} // okay
+                            Place::Static(..) => unreachable!(), // (filtered by is_unsafe_place)
+                            Place::Projection(..) => {
+                                // ... can assign into projections,
+                                // e.g. `box (&mut _)`. Current
+                                // conservative solution: force
+                                // immediate activation here.
+                                sets.gen(&ReserveOrActivateIndex::active(*index));
+                            }
+                        }
+                    }
                 }
             }
 
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index b3a7c32140b..f29009c1973 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -122,7 +122,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                impl_ty);
                         if let Some(note_span) = note_span {
                             // We have a span pointing to the method. Show note with snippet.
-                            err.span_note(note_span, &note_str);
+                            err.span_note(self.tcx.sess.codemap().def_span(note_span), &note_str);
                         } else {
                             err.note(&note_str);
                         }
@@ -131,7 +131,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         let item = self
                             .associated_item(trait_did, item_name, Namespace::Value)
                             .unwrap();
-                        let item_span = self.tcx.def_span(item.def_id);
+                        let item_span = self.tcx.sess.codemap()
+                            .def_span(self.tcx.def_span(item.def_id));
                         span_note!(err,
                                    item_span,
                                    "candidate #{} is defined in the trait `{}`",
diff --git a/src/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index e6cf27b2008..559f8494fc3 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -109,24 +109,32 @@
     function showSidebar() {
         var elems = document.getElementsByClassName("sidebar-elems")[0];
         if (elems) {
-            elems.style.display = "block";
+            addClass(elems, "show-it");
         }
         var sidebar = document.getElementsByClassName('sidebar')[0];
-        sidebar.style.position = 'fixed';
-        sidebar.style.width = '100%';
-        sidebar.style.marginLeft = '0';
+        if (sidebar) {
+            addClass(sidebar, 'mobile');
+            var filler = document.getElementById("sidebar-filler");
+            if (!filler) {
+                var div = document.createElement("div");
+                div.id = "sidebar-filler";
+                sidebar.appendChild(div);
+            }
+        }
         document.getElementsByTagName("body")[0].style.marginTop = '45px';
     }
 
     function hideSidebar() {
         var elems = document.getElementsByClassName("sidebar-elems")[0];
         if (elems) {
-            elems.style.display = "";
+            removeClass(elems, "show-it");
         }
         var sidebar = document.getElementsByClassName('sidebar')[0];
-        sidebar.style.position = '';
-        sidebar.style.width = '';
-        sidebar.style.marginLeft = '';
+        removeClass(sidebar, 'mobile');
+        var filler = document.getElementById("sidebar-filler");
+        if (filler) {
+            filler.remove();
+        }
         document.getElementsByTagName("body")[0].style.marginTop = '';
     }
 
@@ -1859,7 +1867,7 @@
     if (sidebar_menu) {
         sidebar_menu.onclick = function() {
             var sidebar = document.getElementsByClassName('sidebar')[0];
-            if (sidebar.style.position === "fixed") {
+            if (hasClass(sidebar, "mobile") === true) {
                 hideSidebar();
             } else {
                 showSidebar();
diff --git a/src/librustdoc/html/static/rustdoc.css b/src/librustdoc/html/static/rustdoc.css
index e620abea277..b41874a56b8 100644
--- a/src/librustdoc/html/static/rustdoc.css
+++ b/src/librustdoc/html/static/rustdoc.css
@@ -1020,6 +1020,33 @@ h4 > .important-traits {
 	#titles {
 		height: 50px;
 	}
+
+	.sidebar.mobile {
+		position: fixed;
+		width: 100%;
+		margin-left: 0;
+		background-color: rgba(0,0,0,0);
+		height: 100%;
+	}
+
+	.show-it {
+		display: block;
+	}
+
+	/* Because of ios, we need to actually have a full height sidebar title so the
+	 * actual sidebar can show up. But then we need to make it transparent so we don't
+	 * hide content. The filler just allows to create the background for the sidebar
+	 * title. But because of the absolute position, I had to lower the z-index.
+	 */
+	#sidebar-filler {
+		position: fixed;
+		left: 45px;
+		width: calc(100% - 45px);
+		top: 0;
+		height: 45px;
+		z-index: -1;
+		border-bottom: 1px solid;
+	}
 }
 
 
diff --git a/src/librustdoc/html/static/styles/main.css b/src/librustdoc/html/static/styles/main.css
index c31808cfc0f..c79413c0852 100644
--- a/src/librustdoc/html/static/styles/main.css
+++ b/src/librustdoc/html/static/styles/main.css
@@ -191,7 +191,7 @@ a.test-arrow {
 
 #help > div {
 	background: #e9e9e9;
-	border-color: #bfbfbf;;
+	border-color: #bfbfbf;
 }
 
 #help dt {
@@ -342,4 +342,9 @@ pre.ignore:hover, .information:hover + pre.ignore {
 		background-color: #F1F1F1;
 		border-right-color: #000;
 	}
+
+	#sidebar-filler {
+		background-color: #F1F1F1;
+		border-bottom-color: #e0e0e0;
+	}
 }
diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs
index 9c401d7663f..e9b707c57eb 100644
--- a/src/libstd/io/mod.rs
+++ b/src/libstd/io/mod.rs
@@ -441,7 +441,7 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
 /// # }
 /// ```
 ///
-/// Read from `&str` because [`&[u8]`] implements `Read`:
+/// Read from [`&str`] because [`&[u8]`][slice] implements `Read`:
 ///
 /// ```
 /// # use std::io;
@@ -464,7 +464,8 @@ fn read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize>
 /// [`File`]: ../fs/struct.File.html
 /// [`BufRead`]: trait.BufRead.html
 /// [`BufReader`]: struct.BufReader.html
-/// [`&[u8]`]: primitive.slice.html
+/// [`&str`]: ../../std/primitive.str.html
+/// [slice]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(spotlight)]
 pub trait Read {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 461cb0480d2..1d399f159c8 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -20,7 +20,6 @@ use syntax_pos::{Span, DUMMY_SP};
 use codemap::{respan, Spanned};
 use abi::Abi;
 use ext::hygiene::{Mark, SyntaxContext};
-use parse::parser::{RecoverQPath, PathStyle};
 use print::pprust;
 use ptr::P;
 use rustc_data_structures::indexed_vec;
@@ -485,6 +484,30 @@ impl fmt::Debug for Pat {
 }
 
 impl Pat {
+    pub(super) fn to_ty(&self) -> Option<P<Ty>> {
+        let node = match &self.node {
+            PatKind::Wild => TyKind::Infer,
+            PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) =>
+                TyKind::Path(None, Path::from_ident(ident.span, ident.node)),
+            PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
+            PatKind::Mac(mac) => TyKind::Mac(mac.clone()),
+            PatKind::Ref(pat, mutbl) =>
+                pat.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?,
+            PatKind::Slice(pats, None, _) if pats.len() == 1 =>
+                pats[0].to_ty().map(TyKind::Slice)?,
+            PatKind::Tuple(pats, None) => {
+                let mut tys = Vec::new();
+                for pat in pats {
+                    tys.push(pat.to_ty()?);
+                }
+                TyKind::Tup(tys)
+            }
+            _ => return None,
+        };
+
+        Some(P(Ty { node, id: self.id, span: self.span }))
+    }
+
     pub fn walk<F>(&self, it: &mut F) -> bool
         where F: FnMut(&Pat) -> bool
     {
@@ -520,38 +543,6 @@ impl Pat {
     }
 }
 
-impl RecoverQPath for Pat {
-    fn to_ty(&self) -> Option<P<Ty>> {
-        let node = match &self.node {
-            PatKind::Wild => TyKind::Infer,
-            PatKind::Ident(BindingMode::ByValue(Mutability::Immutable), ident, None) =>
-                TyKind::Path(None, Path::from_ident(ident.span, ident.node)),
-            PatKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
-            PatKind::Mac(mac) => TyKind::Mac(mac.clone()),
-            PatKind::Ref(pat, mutbl) =>
-                pat.to_ty().map(|ty| TyKind::Rptr(None, MutTy { ty, mutbl: *mutbl }))?,
-            PatKind::Slice(pats, None, _) if pats.len() == 1 =>
-                pats[0].to_ty().map(TyKind::Slice)?,
-            PatKind::Tuple(pats, None) => {
-                let mut tys = Vec::new();
-                for pat in pats {
-                    tys.push(pat.to_ty()?);
-                }
-                TyKind::Tup(tys)
-            }
-            _ => return None,
-        };
-
-        Some(P(Ty { node, id: self.id, span: self.span }))
-    }
-    fn to_recovered(&self, qself: Option<QSelf>, path: Path) -> Self {
-        Self { span: path.span, node: PatKind::Path(qself, path), id: self.id }
-    }
-    fn to_string(&self) -> String {
-        pprust::pat_to_string(self)
-    }
-}
-
 /// A single field in a struct pattern
 ///
 /// Patterns like the fields of Foo `{ x, ref y, ref mut z }`
@@ -919,10 +910,8 @@ impl Expr {
             _ => None,
         }
     }
-}
 
-impl RecoverQPath for Expr {
-    fn to_ty(&self) -> Option<P<Ty>> {
+    pub(super) fn to_ty(&self) -> Option<P<Ty>> {
         let node = match &self.node {
             ExprKind::Path(qself, path) => TyKind::Path(qself.clone(), path.clone()),
             ExprKind::Mac(mac) => TyKind::Mac(mac.clone()),
@@ -951,13 +940,6 @@ impl RecoverQPath for Expr {
 
         Some(P(Ty { node, id: self.id, span: self.span }))
     }
-    fn to_recovered(&self, qself: Option<QSelf>, path: Path) -> Self {
-        Self { span: path.span, node: ExprKind::Path(qself, path),
-               id: self.id, attrs: self.attrs.clone() }
-    }
-    fn to_string(&self) -> String {
-        pprust::expr_to_string(self)
-    }
 }
 
 impl fmt::Debug for Expr {
@@ -1469,19 +1451,6 @@ pub struct Ty {
     pub span: Span,
 }
 
-impl RecoverQPath for Ty {
-    fn to_ty(&self) -> Option<P<Ty>> {
-        Some(P(self.clone()))
-    }
-    fn to_recovered(&self, qself: Option<QSelf>, path: Path) -> Self {
-        Self { span: path.span, node: TyKind::Path(qself, path), id: self.id }
-    }
-    fn to_string(&self) -> String {
-        pprust::ty_to_string(self)
-    }
-    const PATH_STYLE: PathStyle = PathStyle::Type;
-}
-
 impl fmt::Debug for Ty {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "type({})", pprust::ty_to_string(self))
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 2aac7ef39f2..d9434539246 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -169,11 +169,49 @@ enum PrevTokenKind {
     Other,
 }
 
-pub(crate) trait RecoverQPath: Sized {
+trait RecoverQPath: Sized {
+    const PATH_STYLE: PathStyle = PathStyle::Expr;
     fn to_ty(&self) -> Option<P<Ty>>;
     fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self;
     fn to_string(&self) -> String;
-    const PATH_STYLE: PathStyle = PathStyle::Expr;
+}
+
+impl RecoverQPath for Ty {
+    const PATH_STYLE: PathStyle = PathStyle::Type;
+    fn to_ty(&self) -> Option<P<Ty>> {
+        Some(P(self.clone()))
+    }
+    fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self {
+        Self { span: path.span, node: TyKind::Path(qself, path), id: self.id }
+    }
+    fn to_string(&self) -> String {
+        pprust::ty_to_string(self)
+    }
+}
+
+impl RecoverQPath for Pat {
+    fn to_ty(&self) -> Option<P<Ty>> {
+        self.to_ty()
+    }
+    fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self {
+        Self { span: path.span, node: PatKind::Path(qself, path), id: self.id }
+    }
+    fn to_string(&self) -> String {
+        pprust::pat_to_string(self)
+    }
+}
+
+impl RecoverQPath for Expr {
+    fn to_ty(&self) -> Option<P<Ty>> {
+        self.to_ty()
+    }
+    fn to_recovered(&self, qself: Option<QSelf>, path: ast::Path) -> Self {
+        Self { span: path.span, node: ExprKind::Path(qself, path),
+               id: self.id, attrs: self.attrs.clone() }
+    }
+    fn to_string(&self) -> String {
+        pprust::expr_to_string(self)
+    }
 }
 
 /* ident is handled by common.rs */
@@ -1432,7 +1470,7 @@ impl<'a> Parser<'a> {
 
     // Parse a type
     pub fn parse_ty(&mut self) -> PResult<'a, P<Ty>> {
-        self.parse_ty_common(true)
+        self.parse_ty_common(true, true)
     }
 
     /// Parse a type in restricted contexts where `+` is not permitted.
@@ -1441,10 +1479,11 @@ impl<'a> Parser<'a> {
     /// Example 2: `value1 as TYPE + value2`
     ///     `+` is prohibited to avoid interactions with expression grammar.
     fn parse_ty_no_plus(&mut self) -> PResult<'a, P<Ty>> {
-        self.parse_ty_common(false)
+        self.parse_ty_common(false, true)
     }
 
-    fn parse_ty_common(&mut self, allow_plus: bool) -> PResult<'a, P<Ty>> {
+    fn parse_ty_common(&mut self, allow_plus: bool, allow_qpath_recovery: bool)
+                       -> PResult<'a, P<Ty>> {
         maybe_whole!(self, NtTy, |x| x);
 
         let lo = self.span;
@@ -1577,7 +1616,7 @@ impl<'a> Parser<'a> {
 
         // Try to recover from use of `+` with incorrect priority.
         self.maybe_recover_from_bad_type_plus(allow_plus, &ty)?;
-        let ty = self.maybe_recover_from_bad_qpath(ty)?;
+        let ty = self.maybe_recover_from_bad_qpath(ty, allow_qpath_recovery)?;
 
         Ok(P(ty))
     }
@@ -1633,9 +1672,10 @@ impl<'a> Parser<'a> {
     }
 
     // Try to recover from associated item paths like `[T]::AssocItem`/`(T, U)::AssocItem`.
-    fn maybe_recover_from_bad_qpath<T: RecoverQPath>(&mut self, base: T) -> PResult<'a, T> {
+    fn maybe_recover_from_bad_qpath<T: RecoverQPath>(&mut self, base: T, allow_recovery: bool)
+                                                     -> PResult<'a, T> {
         // Do not add `::` to expected tokens.
-        if self.token != token::ModSep {
+        if !allow_recovery || self.token != token::ModSep {
             return Ok(base);
         }
         let ty = match base.to_ty() {
@@ -1969,7 +2009,7 @@ impl<'a> Parser<'a> {
                     |p| p.parse_ty())?;
                 self.bump(); // `)`
                 let output = if self.eat(&token::RArrow) {
-                    Some(self.parse_ty_no_plus()?)
+                    Some(self.parse_ty_common(false, false)?)
                 } else {
                     None
                 };
@@ -2376,7 +2416,7 @@ impl<'a> Parser<'a> {
         }
 
         let expr = Expr { node: ex, span: lo.to(hi), id: ast::DUMMY_NODE_ID, attrs };
-        let expr = self.maybe_recover_from_bad_qpath(expr)?;
+        let expr = self.maybe_recover_from_bad_qpath(expr, true)?;
 
         return Ok(P(expr));
     }
@@ -3743,7 +3783,7 @@ impl<'a> Parser<'a> {
         }
 
         let pat = Pat { node: pat, span: lo.to(self.prev_span), id: ast::DUMMY_NODE_ID };
-        let pat = self.maybe_recover_from_bad_qpath(pat)?;
+        let pat = self.maybe_recover_from_bad_qpath(pat, true)?;
 
         Ok(P(pat))
     }
diff --git a/src/test/ui/did_you_mean/bad-assoc-expr.rs b/src/test/ui/did_you_mean/bad-assoc-expr.rs
index 72b616ddd69..779aa952c81 100644
--- a/src/test/ui/did_you_mean/bad-assoc-expr.rs
+++ b/src/test/ui/did_you_mean/bad-assoc-expr.rs
@@ -21,4 +21,10 @@ fn main() {
 
     (u8, u8)::clone(&(0, 0));
     //~^ ERROR missing angle brackets in associated item path
+
+    &(u8)::clone(&0);
+    //~^ ERROR missing angle brackets in associated item path
+
+    10 + (u8)::clone(&0);
+    //~^ ERROR missing angle brackets in associated item path
 }
diff --git a/src/test/ui/did_you_mean/bad-assoc-expr.stderr b/src/test/ui/did_you_mean/bad-assoc-expr.stderr
index 1f8fc118f78..1affdc5fda2 100644
--- a/src/test/ui/did_you_mean/bad-assoc-expr.stderr
+++ b/src/test/ui/did_you_mean/bad-assoc-expr.stderr
@@ -22,5 +22,17 @@ error: missing angle brackets in associated item path
 22 |     (u8, u8)::clone(&(0, 0));
    |     ^^^^^^^^^^^^^^^ help: try: `<(u8, u8)>::clone`
 
-error: aborting due to 4 previous errors
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-expr.rs:25:6
+   |
+25 |     &(u8)::clone(&0);
+   |      ^^^^^^^^^^^ help: try: `<(u8)>::clone`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-expr.rs:28:10
+   |
+28 |     10 + (u8)::clone(&0);
+   |          ^^^^^^^^^^^ help: try: `<(u8)>::clone`
+
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/did_you_mean/bad-assoc-pat.rs b/src/test/ui/did_you_mean/bad-assoc-pat.rs
index e6b7127f100..bf6be0ee985 100644
--- a/src/test/ui/did_you_mean/bad-assoc-pat.rs
+++ b/src/test/ui/did_you_mean/bad-assoc-pat.rs
@@ -20,4 +20,9 @@ fn main() {
         //~^ ERROR missing angle brackets in associated item path
         //~| ERROR no associated item named `AssocItem` found for type `_` in the current scope
     }
+    match &0u8 {
+        &(u8,)::AssocItem => {}
+        //~^ ERROR missing angle brackets in associated item path
+        //~| ERROR no associated item named `AssocItem` found for type `(u8,)` in the current scope
+    }
 }
diff --git a/src/test/ui/did_you_mean/bad-assoc-pat.stderr b/src/test/ui/did_you_mean/bad-assoc-pat.stderr
index 20f9b96dbaa..1ca4576d88f 100644
--- a/src/test/ui/did_you_mean/bad-assoc-pat.stderr
+++ b/src/test/ui/did_you_mean/bad-assoc-pat.stderr
@@ -16,6 +16,12 @@ error: missing angle brackets in associated item path
 19 |         _::AssocItem => {}
    |         ^^^^^^^^^^^^ help: try: `<_>::AssocItem`
 
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-pat.rs:24:10
+   |
+24 |         &(u8,)::AssocItem => {}
+   |          ^^^^^^^^^^^^^^^^ help: try: `<(u8,)>::AssocItem`
+
 error[E0599]: no associated item named `AssocItem` found for type `[u8]` in the current scope
   --> $DIR/bad-assoc-pat.rs:13:9
    |
@@ -34,5 +40,11 @@ error[E0599]: no associated item named `AssocItem` found for type `_` in the cur
 19 |         _::AssocItem => {}
    |         ^^^^^^^^^^^^ associated item not found in `_`
 
-error: aborting due to 6 previous errors
+error[E0599]: no associated item named `AssocItem` found for type `(u8,)` in the current scope
+  --> $DIR/bad-assoc-pat.rs:24:10
+   |
+24 |         &(u8,)::AssocItem => {}
+   |          ^^^^^^^^^^^^^^^^ associated item not found in `(u8,)`
+
+error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.rs b/src/test/ui/did_you_mean/bad-assoc-ty.rs
index 45a52936738..b4a59904ee4 100644
--- a/src/test/ui/did_you_mean/bad-assoc-ty.rs
+++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs
@@ -28,4 +28,19 @@ type E = _::AssocTy;
 //~^ ERROR missing angle brackets in associated item path
 //~| ERROR the type placeholder `_` is not allowed within types on item signatures
 
+type F = &'static (u8)::AssocTy;
+//~^ ERROR missing angle brackets in associated item path
+//~| ERROR ambiguous associated type
+
+// Qualified paths cannot appear in bounds, so the recovery
+// should apply to the whole sum and not `(Send)`.
+type G = 'static + (Send)::AssocTy;
+//~^ ERROR missing angle brackets in associated item path
+//~| ERROR ambiguous associated type
+
+// This is actually a legal path with fn-like generic arguments in the middle!
+// Recovery should not apply in this context.
+type H = Fn(u8) -> (u8)::Output;
+//~^ ERROR ambiguous associated type
+
 fn main() {}
diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr
index 617339a7d92..c44dc5a0468 100644
--- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr
+++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr
@@ -28,6 +28,18 @@ error: missing angle brackets in associated item path
 27 | type E = _::AssocTy;
    |          ^^^^^^^^^^ help: try: `<_>::AssocTy`
 
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:31:19
+   |
+31 | type F = &'static (u8)::AssocTy;
+   |                   ^^^^^^^^^^^^^ help: try: `<(u8)>::AssocTy`
+
+error: missing angle brackets in associated item path
+  --> $DIR/bad-assoc-ty.rs:37:10
+   |
+37 | type G = 'static + (Send)::AssocTy;
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `<'static + Send>::AssocTy`
+
 error[E0223]: ambiguous associated type
   --> $DIR/bad-assoc-ty.rs:11:10
    |
@@ -66,5 +78,29 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa
 27 | type E = _::AssocTy;
    |          ^ not allowed in type signatures
 
-error: aborting due to 10 previous errors
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:31:19
+   |
+31 | type F = &'static (u8)::AssocTy;
+   |                   ^^^^^^^^^^^^^ ambiguous associated type
+   |
+   = note: specify the type using the syntax `<u8 as Trait>::AssocTy`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:37:10
+   |
+37 | type G = 'static + (Send)::AssocTy;
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type
+   |
+   = note: specify the type using the syntax `<std::marker::Send + 'static as Trait>::AssocTy`
+
+error[E0223]: ambiguous associated type
+  --> $DIR/bad-assoc-ty.rs:43:10
+   |
+43 | type H = Fn(u8) -> (u8)::Output;
+   |          ^^^^^^^^^^^^^^^^^^^^^^ ambiguous associated type
+   |
+   = note: specify the type using the syntax `<std::ops::Fn(u8) -> u8 + 'static as Trait>::Output`
+
+error: aborting due to 15 previous errors
 
diff --git a/src/test/ui/span/issue-37767.stderr b/src/test/ui/span/issue-37767.stderr
index 8babcc74ed5..e9a1fe82f14 100644
--- a/src/test/ui/span/issue-37767.stderr
+++ b/src/test/ui/span/issue-37767.stderr
@@ -8,13 +8,13 @@ note: candidate #1 is defined in the trait `A`
   --> $DIR/issue-37767.rs:12:5
    |
 12 |     fn foo(&mut self) {}
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^
    = help: to disambiguate the method call, write `A::foo(&a)` instead
 note: candidate #2 is defined in the trait `B`
   --> $DIR/issue-37767.rs:16:5
    |
 16 |     fn foo(&mut self) {}
-   |     ^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^
    = help: to disambiguate the method call, write `B::foo(&a)` instead
 
 error[E0034]: multiple applicable items in scope
@@ -27,13 +27,13 @@ note: candidate #1 is defined in the trait `C`
   --> $DIR/issue-37767.rs:24:5
    |
 24 |     fn foo(&self) {}
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^
    = help: to disambiguate the method call, write `C::foo(&a)` instead
 note: candidate #2 is defined in the trait `D`
   --> $DIR/issue-37767.rs:28:5
    |
 28 |     fn foo(&self) {}
-   |     ^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^
    = help: to disambiguate the method call, write `D::foo(&a)` instead
 
 error[E0034]: multiple applicable items in scope
@@ -46,13 +46,13 @@ note: candidate #1 is defined in the trait `E`
   --> $DIR/issue-37767.rs:36:5
    |
 36 |     fn foo(self) {}
-   |     ^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^
    = help: to disambiguate the method call, write `E::foo(a)` instead
 note: candidate #2 is defined in the trait `F`
   --> $DIR/issue-37767.rs:40:5
    |
 40 |     fn foo(self) {}
-   |     ^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^
    = help: to disambiguate the method call, write `F::foo(a)` instead
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/span/issue-7575.stderr b/src/test/ui/span/issue-7575.stderr
index 57c4d25b7d0..aeb98e4cabc 100644
--- a/src/test/ui/span/issue-7575.stderr
+++ b/src/test/ui/span/issue-7575.stderr
@@ -44,10 +44,8 @@ error[E0599]: no method named `fff` found for type `Myisize` in the current scop
 note: candidate #1 is defined in an impl for the type `Myisize`
   --> $DIR/issue-7575.rs:51:5
    |
-51 | /     fn fff(i: isize) -> isize {
-52 | |         i
-53 | |     }
-   | |_____^
+51 |     fn fff(i: isize) -> isize {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0599]: no method named `is_str` found for type `T` in the current scope
   --> $DIR/issue-7575.rs:82:7
@@ -60,10 +58,8 @@ error[E0599]: no method named `is_str` found for type `T` in the current scope
 note: candidate #1 is defined in the trait `ManyImplTrait`
   --> $DIR/issue-7575.rs:57:5
    |
-57 | /     fn is_str() -> bool {
-58 | |         false
-59 | |     }
-   | |_____^
+57 |     fn is_str() -> bool {
+   |     ^^^^^^^^^^^^^^^^^^^
    = help: to disambiguate the method call, write `ManyImplTrait::is_str(t)` instead
    = help: items from traits can only be used if the trait is implemented and in scope
    = note: the following trait defines an item `is_str`, perhaps you need to implement it: