Skip to content

Commit efd1bd0

Browse files
committed
add parser check for multi-reference self
1 parent 1ed3cd7 commit efd1bd0

File tree

3 files changed

+215
-4
lines changed

3 files changed

+215
-4
lines changed

compiler/rustc_parse/src/parser/diagnostics.rs

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@ use std::mem::take;
22
use std::ops::{Deref, DerefMut};
33

44
use ast::token::IdentIsRaw;
5-
use rustc_ast as ast;
65
use rustc_ast::token::{self, Lit, LitKind, Token, TokenKind};
76
use rustc_ast::util::parser::AssocOp;
87
use rustc_ast::{
9-
AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block,
10-
BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Param, Pat, PatKind,
11-
Path, PathSegment, QSelf, Recovered, Ty, TyKind,
8+
self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode,
9+
Block, BlockCheckMode, Expr, ExprKind, GenericArg, Generics, Item, ItemKind, Mutability, Param,
10+
Pat, PatKind, Path, PathSegment, QSelf, Recovered, Ty, TyKind,
1211
};
1312
use rustc_ast_pretty::pprust;
1413
use rustc_data_structures::fx::FxHashSet;
@@ -2305,6 +2304,62 @@ impl<'a> Parser<'a> {
23052304
pat.span.shrink_to_lo(),
23062305
)
23072306
}
2307+
PatKind::Ref(ref inner_pat, mutble) => {
2308+
let mut inner = inner_pat;
2309+
let mut span_vec = vec![pat.span];
2310+
let mut mut_vec = vec![mutble];
2311+
2312+
while let PatKind::Ref(ref inner_type, mutble) = inner.kind {
2313+
inner = inner_type;
2314+
span_vec.push(inner.span.shrink_to_lo());
2315+
mut_vec.push(mutble);
2316+
}
2317+
2318+
let mut refs_string = String::new();
2319+
for &mutability in &mut_vec {
2320+
match mutability {
2321+
Mutability::Not => refs_string.push('&'),
2322+
Mutability::Mut => refs_string.push_str("&mut "),
2323+
}
2324+
}
2325+
2326+
if span_vec.len() <= 1 {
2327+
if let Some(_) = pat.to_ty() {
2328+
err.span_suggestion_verbose(
2329+
pat.span.shrink_to_lo(),
2330+
"explicitly ignore the parameter name",
2331+
"_: ".to_string(),
2332+
Applicability::MachineApplicable,
2333+
);
2334+
maybe_emit_anon_params_note(self, err);
2335+
}
2336+
2337+
return None;
2338+
}
2339+
2340+
let span = if span_vec.len() == 2 {
2341+
span_vec[0].until(inner_pat.span.shrink_to_lo())
2342+
} else {
2343+
span_vec[0].until(span_vec[span_vec.len() - 2].shrink_to_lo())
2344+
};
2345+
2346+
err.span_suggestion_verbose(
2347+
span,
2348+
"`self` should be `self`, `&self` or `&mut self`, please remove extra references",
2349+
"".to_string(),
2350+
Applicability::MachineApplicable,
2351+
);
2352+
2353+
err.span_suggestion_verbose(
2354+
span_vec[0],
2355+
format!("or if you want exactly {refs_string}self, please write it like this"),
2356+
format!("self: {refs_string}Self"),
2357+
Applicability::MachineApplicable,
2358+
);
2359+
2360+
maybe_emit_anon_params_note(self, err);
2361+
return None;
2362+
}
23082363
_ => {
23092364
// Otherwise, try to get a type and emit a suggestion.
23102365
if let Some(_) = pat.to_ty() {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
struct A ;
2+
3+
impl A {
4+
fn a(&&self) {}
5+
//~^ ERROR expected one of
6+
//~| HELP `self` should be `self`, `&self` or `&mut self`, please remove extra references
7+
//~| HELP or if you want exactly
8+
fn b(&&&&&&self) {}
9+
//~^ ERROR expected one of
10+
//~| HELP `self` should be `self`, `&self` or `&mut self`, please remove extra references
11+
//~| HELP or if you want exactly
12+
fn c(&self) {}
13+
fn d(&mut &self) {}
14+
//~^ ERROR expected one of
15+
//~| HELP `self` should be `self`, `&self` or `&mut self`, please remove extra references
16+
//~| HELP or if you want exactly
17+
fn e(&mut &&&self) {}
18+
//~^ ERROR expected one of
19+
//~| HELP `self` should be `self`, `&self` or `&mut self`, please remove extra references
20+
//~| HELP or if you want exactly
21+
fn f(&mut &mut &mut self) {}
22+
//~^ ERROR expected one of
23+
//~| HELP `self` should be `self`, `&self` or `&mut self`, please remove extra references
24+
//~| HELP or if you want exactly
25+
fn g(&mut & &mut self) {}
26+
//~^ ERROR expected one of
27+
//~| HELP `self` should be `self`, `&self` or `&mut self`, please remove extra references
28+
//~| HELP or if you want exactly
29+
fn h(&mut & & & && & & self) {}
30+
//~^ ERROR expected one of
31+
//~| HELP `self` should be `self`, `&self` or `&mut self`, please remove extra references
32+
//~| HELP or if you want exactly
33+
}
34+
35+
fn main() {}
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
2+
--> $DIR/lot-of-references-self.rs:4:16
3+
|
4+
LL | fn a(&&self) {}
5+
| ^ expected one of 9 possible tokens
6+
|
7+
help: `self` should be `self`, `&self` or `&mut self`, please remove extra references
8+
|
9+
LL - fn a(&&self) {}
10+
LL + fn a(&self) {}
11+
|
12+
help: or if you want exactly &&self, please write it like this
13+
|
14+
LL - fn a(&&self) {}
15+
LL + fn a(self: &&Self) {}
16+
|
17+
18+
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
19+
--> $DIR/lot-of-references-self.rs:8:20
20+
|
21+
LL | fn b(&&&&&&self) {}
22+
| ^ expected one of 9 possible tokens
23+
|
24+
help: `self` should be `self`, `&self` or `&mut self`, please remove extra references
25+
|
26+
LL - fn b(&&&&&&self) {}
27+
LL + fn b(&self) {}
28+
|
29+
help: or if you want exactly &&&&&&self, please write it like this
30+
|
31+
LL - fn b(&&&&&&self) {}
32+
LL + fn b(self: &&&&&&Self) {}
33+
|
34+
35+
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
36+
--> $DIR/lot-of-references-self.rs:13:20
37+
|
38+
LL | fn d(&mut &self) {}
39+
| ^ expected one of 9 possible tokens
40+
|
41+
help: `self` should be `self`, `&self` or `&mut self`, please remove extra references
42+
|
43+
LL - fn d(&mut &self) {}
44+
LL + fn d(&self) {}
45+
|
46+
help: or if you want exactly &mut &self, please write it like this
47+
|
48+
LL - fn d(&mut &self) {}
49+
LL + fn d(self: &mut &Self) {}
50+
|
51+
52+
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
53+
--> $DIR/lot-of-references-self.rs:17:22
54+
|
55+
LL | fn e(&mut &&&self) {}
56+
| ^ expected one of 9 possible tokens
57+
|
58+
help: `self` should be `self`, `&self` or `&mut self`, please remove extra references
59+
|
60+
LL - fn e(&mut &&&self) {}
61+
LL + fn e(&self) {}
62+
|
63+
help: or if you want exactly &mut &&&self, please write it like this
64+
|
65+
LL - fn e(&mut &&&self) {}
66+
LL + fn e(self: &mut &&&Self) {}
67+
|
68+
69+
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
70+
--> $DIR/lot-of-references-self.rs:21:29
71+
|
72+
LL | fn f(&mut &mut &mut self) {}
73+
| ^ expected one of 9 possible tokens
74+
|
75+
help: `self` should be `self`, `&self` or `&mut self`, please remove extra references
76+
|
77+
LL - fn f(&mut &mut &mut self) {}
78+
LL + fn f(&mut self) {}
79+
|
80+
help: or if you want exactly &mut &mut &mut self, please write it like this
81+
|
82+
LL - fn f(&mut &mut &mut self) {}
83+
LL + fn f(self: &mut &mut &mut Self) {}
84+
|
85+
86+
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
87+
--> $DIR/lot-of-references-self.rs:25:26
88+
|
89+
LL | fn g(&mut & &mut self) {}
90+
| ^ expected one of 9 possible tokens
91+
|
92+
help: `self` should be `self`, `&self` or `&mut self`, please remove extra references
93+
|
94+
LL - fn g(&mut & &mut self) {}
95+
LL + fn g(&mut self) {}
96+
|
97+
help: or if you want exactly &mut &&mut self, please write it like this
98+
|
99+
LL - fn g(&mut & &mut self) {}
100+
LL + fn g(self: &mut &&mut Self) {}
101+
|
102+
103+
error: expected one of `!`, `(`, `...`, `..=`, `..`, `::`, `:`, `{`, or `|`, found `)`
104+
--> $DIR/lot-of-references-self.rs:29:39
105+
|
106+
LL | fn h(&mut & & & && & & self) {}
107+
| ^ expected one of 9 possible tokens
108+
|
109+
help: `self` should be `self`, `&self` or `&mut self`, please remove extra references
110+
|
111+
LL - fn h(&mut & & & && & & self) {}
112+
LL + fn h(& self) {}
113+
|
114+
help: or if you want exactly &mut &&&&&&&self, please write it like this
115+
|
116+
LL - fn h(&mut & & & && & & self) {}
117+
LL + fn h(self: &mut &&&&&&&Self) {}
118+
|
119+
120+
error: aborting due to 7 previous errors
121+

0 commit comments

Comments
 (0)