about summary refs log tree commit diff
path: root/compiler/rustc_parse/src/parser
diff options
context:
space:
mode:
authorSNCPlay42 <SNCPlay42@gmail.com>2020-06-21 21:37:17 +0100
committerMark Rousskov <mark.simulacrum@gmail.com>2020-09-15 10:36:06 -0400
commit4de9a53d98533868dfa209bfb3604bba92d5e7b1 (patch)
tree0f19e96f09dbdbc43f9d1f7d00aa6aaf9a63c56d /compiler/rustc_parse/src/parser
parent90b1f5ae59291dd69d72fad41a22277df19dc953 (diff)
downloadrust-4de9a53d98533868dfa209bfb3604bba92d5e7b1.tar.gz
rust-4de9a53d98533868dfa209bfb3604bba92d5e7b1.zip
improve diagnostics for lifetime after `&mut`
Diffstat (limited to 'compiler/rustc_parse/src/parser')
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs28
1 files changed, 27 insertions, 1 deletions
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 259764a317d..fc4c62ccbd9 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -276,8 +276,34 @@ impl<'a> Parser<'a> {
     }
 
     fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
-        let opt_lifetime = if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
+        let and_span = self.prev_token.span;
+        let mut opt_lifetime =
+            if self.check_lifetime() { Some(self.expect_lifetime()) } else { None };
         let mutbl = self.parse_mutability();
+        if self.token.is_lifetime() && mutbl == Mutability::Mut && opt_lifetime.is_none() {
+            // A lifetime is invalid here: it would be part of a bare trait bound, which requires
+            // it to be followed by a plus, but we disallow plus in the pointee type.
+            // So we can handle this case as an error here, and suggest `'a mut`.
+            // If there *is* a plus next though, handling the error later provides better suggestions
+            // (like adding parentheses)
+            if !self.look_ahead(1, |t| t.is_like_plus()) {
+                let lifetime_span = self.token.span;
+                let span = and_span.to(lifetime_span);
+
+                let mut err = self.struct_span_err(span, "lifetime must precede `mut`");
+                if let Ok(lifetime_src) = self.span_to_snippet(lifetime_span) {
+                    err.span_suggestion(
+                        span,
+                        "place the lifetime before `mut`",
+                        format!("&{} mut", lifetime_src),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
+                err.emit();
+
+                opt_lifetime = Some(self.expect_lifetime());
+            }
+        }
         let ty = self.parse_ty_no_plus()?;
         Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }))
     }