improve diagnostics for lifetime after &mut
This commit is contained in:
parent
90b1f5ae59
commit
4de9a53d98
@ -276,8 +276,34 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse_borrowed_pointee(&mut self) -> PResult<'a, TyKind> {
|
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();
|
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()?;
|
let ty = self.parse_ty_no_plus()?;
|
||||||
Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }))
|
Ok(TyKind::Rptr(opt_lifetime, MutTy { ty, mutbl }))
|
||||||
}
|
}
|
||||||
|
21
src/test/ui/parser/issue-73568-lifetime-after-mut.rs
Normal file
21
src/test/ui/parser/issue-73568-lifetime-after-mut.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#![crate_type="lib"]
|
||||||
|
fn x<'a>(x: &mut 'a i32){} //~ ERROR lifetime must precede `mut`
|
||||||
|
|
||||||
|
macro_rules! mac {
|
||||||
|
($lt:lifetime) => {
|
||||||
|
fn w<$lt>(w: &mut $lt i32) {}
|
||||||
|
//~^ ERROR lifetime must precede `mut`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mac!('a);
|
||||||
|
|
||||||
|
// avoid false positives
|
||||||
|
fn y<'a>(y: &mut 'a + Send) {
|
||||||
|
//~^ ERROR expected a path on the left-hand side of `+`, not `&mut 'a`
|
||||||
|
//~| WARNING trait objects without an explicit `dyn` are deprecated
|
||||||
|
//~| ERROR at least one trait is required for an object type
|
||||||
|
let z = y as &mut 'a + Send;
|
||||||
|
//~^ ERROR expected value, found trait `Send`
|
||||||
|
//~| WARNING trait objects without an explicit `dyn` are deprecated
|
||||||
|
}
|
53
src/test/ui/parser/issue-73568-lifetime-after-mut.stderr
Normal file
53
src/test/ui/parser/issue-73568-lifetime-after-mut.stderr
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
error: lifetime must precede `mut`
|
||||||
|
--> $DIR/issue-73568-lifetime-after-mut.rs:2:13
|
||||||
|
|
|
||||||
|
LL | fn x<'a>(x: &mut 'a i32){}
|
||||||
|
| ^^^^^^^ help: place the lifetime before `mut`: `&'a mut`
|
||||||
|
|
||||||
|
error[E0178]: expected a path on the left-hand side of `+`, not `&mut 'a`
|
||||||
|
--> $DIR/issue-73568-lifetime-after-mut.rs:14:13
|
||||||
|
|
|
||||||
|
LL | fn y<'a>(y: &mut 'a + Send) {
|
||||||
|
| ^^^^^^^^^^^^^^ help: try adding parentheses: `&mut ('a + Send)`
|
||||||
|
|
||||||
|
error: lifetime must precede `mut`
|
||||||
|
--> $DIR/issue-73568-lifetime-after-mut.rs:6:22
|
||||||
|
|
|
||||||
|
LL | fn w<$lt>(w: &mut $lt i32) {}
|
||||||
|
| ^^^^^^^^ help: place the lifetime before `mut`: `&$lt mut`
|
||||||
|
...
|
||||||
|
LL | mac!('a);
|
||||||
|
| --------- in this macro invocation
|
||||||
|
|
|
||||||
|
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||||
|
|
||||||
|
error[E0423]: expected value, found trait `Send`
|
||||||
|
--> $DIR/issue-73568-lifetime-after-mut.rs:18:28
|
||||||
|
|
|
||||||
|
LL | let z = y as &mut 'a + Send;
|
||||||
|
| ^^^^ not a value
|
||||||
|
|
||||||
|
warning: trait objects without an explicit `dyn` are deprecated
|
||||||
|
--> $DIR/issue-73568-lifetime-after-mut.rs:14:18
|
||||||
|
|
|
||||||
|
LL | fn y<'a>(y: &mut 'a + Send) {
|
||||||
|
| ^^ help: use `dyn`: `dyn 'a`
|
||||||
|
|
|
||||||
|
= note: `#[warn(bare_trait_objects)]` on by default
|
||||||
|
|
||||||
|
warning: trait objects without an explicit `dyn` are deprecated
|
||||||
|
--> $DIR/issue-73568-lifetime-after-mut.rs:18:23
|
||||||
|
|
|
||||||
|
LL | let z = y as &mut 'a + Send;
|
||||||
|
| ^^ help: use `dyn`: `dyn 'a`
|
||||||
|
|
||||||
|
error[E0224]: at least one trait is required for an object type
|
||||||
|
--> $DIR/issue-73568-lifetime-after-mut.rs:14:18
|
||||||
|
|
|
||||||
|
LL | fn y<'a>(y: &mut 'a + Send) {
|
||||||
|
| ^^
|
||||||
|
|
||||||
|
error: aborting due to 5 previous errors; 2 warnings emitted
|
||||||
|
|
||||||
|
Some errors have detailed explanations: E0178, E0224, E0423.
|
||||||
|
For more information about an error, try `rustc --explain E0178`.
|
Loading…
Reference in New Issue
Block a user