add parser check for multi-reference self
This commit is contained in:
parent
1ed3cd7030
commit
7298174cd5
4 changed files with 158 additions and 4 deletions
|
|
@ -715,6 +715,15 @@ impl Pat {
|
|||
}
|
||||
}
|
||||
|
||||
/// Strip off all reference patterns (`&`, `&mut`) and return the inner pattern.
|
||||
pub fn peel_refs(&self) -> &Pat {
|
||||
let mut current = self;
|
||||
while let PatKind::Ref(inner, _) = ¤t.kind {
|
||||
current = inner;
|
||||
}
|
||||
current
|
||||
}
|
||||
|
||||
/// Is this a `..` pattern?
|
||||
pub fn is_rest(&self) -> bool {
|
||||
matches!(self.kind, PatKind::Rest)
|
||||
|
|
|
|||
|
|
@ -2,13 +2,12 @@ use std::mem::take;
|
|||
use std::ops::{Deref, DerefMut};
|
||||
|
||||
use ast::token::IdentIsRaw;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::token::{self, Lit, LitKind, Token, TokenKind};
|
||||
use rustc_ast::util::parser::AssocOp;
|
||||
use rustc_ast::{
|
||||
AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block,
|
||||
BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat, PatKind,
|
||||
Path, PathSegment, QSelf, Recovered, Ty, TyKind,
|
||||
self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode,
|
||||
Block, BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat,
|
||||
PatKind, Path, PathSegment, QSelf, Recovered, Ty, TyKind,
|
||||
};
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
|
|
@ -2290,6 +2289,38 @@ impl<'a> Parser<'a> {
|
|||
pat.span.shrink_to_hi(),
|
||||
pat.span.shrink_to_lo(),
|
||||
),
|
||||
PatKind::Ref(ref inner_pat, _)
|
||||
// Fix suggestions for multi-reference `self` parameters (e.g. `&&&self`)
|
||||
// cc: https://github.com/rust-lang/rust/pull/146305
|
||||
if let PatKind::Ref(_, _) = &inner_pat.kind
|
||||
&& let PatKind::Path(_, path) = &pat.peel_refs().kind
|
||||
&& let [a, ..] = path.segments.as_slice()
|
||||
&& a.ident.name == kw::SelfLower =>
|
||||
{
|
||||
let mut inner = inner_pat;
|
||||
let mut span_vec = vec![pat.span];
|
||||
|
||||
while let PatKind::Ref(ref inner_type, _) = inner.kind {
|
||||
inner = inner_type;
|
||||
span_vec.push(inner.span.shrink_to_lo());
|
||||
}
|
||||
|
||||
let span = match span_vec.len() {
|
||||
// Should be unreachable: match guard ensures at least 2 references
|
||||
0 | 1 => unreachable!(),
|
||||
2 => span_vec[0].until(inner_pat.span.shrink_to_lo()),
|
||||
_ => span_vec[0].until(span_vec[span_vec.len() - 2].shrink_to_lo()),
|
||||
};
|
||||
|
||||
err.span_suggestion_verbose(
|
||||
span,
|
||||
"`self` should be `self`, `&self` or `&mut self`, consider removing extra references",
|
||||
"".to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
|
||||
return None;
|
||||
}
|
||||
// Also catches `fn foo(&a)`.
|
||||
PatKind::Ref(ref inner_pat, mutab)
|
||||
if let PatKind::Ident(_, ident, _) = inner_pat.clone().kind =>
|
||||
|
|
|
|||
28
tests/ui/self/lot-of-references-self.rs
Normal file
28
tests/ui/self/lot-of-references-self.rs
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
struct A ;
|
||||
|
||||
impl A {
|
||||
fn a(&&self) {}
|
||||
//~^ ERROR expected one of
|
||||
//~| HELP `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
fn b(&&&&&&self) {}
|
||||
//~^ ERROR expected one of
|
||||
//~| HELP `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
fn c(&self) {}
|
||||
fn d(&mut &self) {}
|
||||
//~^ ERROR expected one of
|
||||
//~| HELP `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
fn e(&mut &&&self) {}
|
||||
//~^ ERROR expected one of
|
||||
//~| HELP `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
fn f(&mut &mut &mut self) {}
|
||||
//~^ ERROR expected one of
|
||||
//~| HELP `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
fn g(&mut & &mut self) {}
|
||||
//~^ ERROR expected one of
|
||||
//~| HELP `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
fn h(&mut & & & && & & self) {}
|
||||
//~^ ERROR expected one of
|
||||
//~| HELP `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
86
tests/ui/self/lot-of-references-self.stderr
Normal file
86
tests/ui/self/lot-of-references-self.stderr
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
|
||||
--> $DIR/lot-of-references-self.rs:4:16
|
||||
|
|
||||
LL | fn a(&&self) {}
|
||||
| ^ expected one of 9 possible tokens
|
||||
|
|
||||
help: `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
|
|
||||
LL - fn a(&&self) {}
|
||||
LL + fn a(&self) {}
|
||||
|
|
||||
|
||||
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
|
||||
--> $DIR/lot-of-references-self.rs:7:20
|
||||
|
|
||||
LL | fn b(&&&&&&self) {}
|
||||
| ^ expected one of 9 possible tokens
|
||||
|
|
||||
help: `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
|
|
||||
LL - fn b(&&&&&&self) {}
|
||||
LL + fn b(&self) {}
|
||||
|
|
||||
|
||||
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
|
||||
--> $DIR/lot-of-references-self.rs:11:20
|
||||
|
|
||||
LL | fn d(&mut &self) {}
|
||||
| ^ expected one of 9 possible tokens
|
||||
|
|
||||
help: `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
|
|
||||
LL - fn d(&mut &self) {}
|
||||
LL + fn d(&self) {}
|
||||
|
|
||||
|
||||
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
|
||||
--> $DIR/lot-of-references-self.rs:14:22
|
||||
|
|
||||
LL | fn e(&mut &&&self) {}
|
||||
| ^ expected one of 9 possible tokens
|
||||
|
|
||||
help: `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
|
|
||||
LL - fn e(&mut &&&self) {}
|
||||
LL + fn e(&self) {}
|
||||
|
|
||||
|
||||
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
|
||||
--> $DIR/lot-of-references-self.rs:17:29
|
||||
|
|
||||
LL | fn f(&mut &mut &mut self) {}
|
||||
| ^ expected one of 9 possible tokens
|
||||
|
|
||||
help: `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
|
|
||||
LL - fn f(&mut &mut &mut self) {}
|
||||
LL + fn f(&mut self) {}
|
||||
|
|
||||
|
||||
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
|
||||
--> $DIR/lot-of-references-self.rs:20:26
|
||||
|
|
||||
LL | fn g(&mut & &mut self) {}
|
||||
| ^ expected one of 9 possible tokens
|
||||
|
|
||||
help: `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
|
|
||||
LL - fn g(&mut & &mut self) {}
|
||||
LL + fn g(&mut self) {}
|
||||
|
|
||||
|
||||
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
|
||||
--> $DIR/lot-of-references-self.rs:23:39
|
||||
|
|
||||
LL | fn h(&mut & & & && & & self) {}
|
||||
| ^ expected one of 9 possible tokens
|
||||
|
|
||||
help: `self` should be `self`, `&self` or `&mut self`, consider removing extra references
|
||||
|
|
||||
LL - fn h(&mut & & & && & & self) {}
|
||||
LL + fn h(& self) {}
|
||||
|
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue