Fix suggestion when shorthand self has erroneous type
This commit is contained in:
parent
96e51d9482
commit
05c34cc5ed
6 changed files with 127 additions and 1 deletions
|
@ -2566,6 +2566,18 @@ pub enum SelfKind {
|
||||||
Explicit(P<Ty>, Mutability),
|
Explicit(P<Ty>, Mutability),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl SelfKind {
|
||||||
|
pub fn to_ref_suggestion(&self) -> String {
|
||||||
|
match self {
|
||||||
|
SelfKind::Region(None, mutbl) => mutbl.ref_prefix_str().to_string(),
|
||||||
|
SelfKind::Region(Some(lt), mutbl) => format!("&{lt} {}", mutbl.prefix_str()),
|
||||||
|
SelfKind::Value(_) | SelfKind::Explicit(_, _) => {
|
||||||
|
unreachable!("if we had an explicit self, we wouldn't be here")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub type ExplicitSelf = Spanned<SelfKind>;
|
pub type ExplicitSelf = Spanned<SelfKind>;
|
||||||
|
|
||||||
impl Param {
|
impl Param {
|
||||||
|
|
|
@ -343,6 +343,9 @@ parse_incorrect_semicolon =
|
||||||
.suggestion = remove this semicolon
|
.suggestion = remove this semicolon
|
||||||
.help = {$name} declarations are not followed by a semicolon
|
.help = {$name} declarations are not followed by a semicolon
|
||||||
|
|
||||||
|
parse_incorrect_type_on_self = type not allowed for shorthand `self` parameter
|
||||||
|
.suggestion = move the modifiers on `self` to the type
|
||||||
|
|
||||||
parse_incorrect_use_of_await = incorrect use of `await`
|
parse_incorrect_use_of_await = incorrect use of `await`
|
||||||
.parentheses_suggestion = `await` is not a method call, remove the parentheses
|
.parentheses_suggestion = `await` is not a method call, remove the parentheses
|
||||||
|
|
||||||
|
|
|
@ -3409,3 +3409,22 @@ pub(crate) struct PolarityAndModifiers {
|
||||||
pub polarity: &'static str,
|
pub polarity: &'static str,
|
||||||
pub modifiers_concatenated: String,
|
pub modifiers_concatenated: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(parse_incorrect_type_on_self)]
|
||||||
|
pub(crate) struct IncorrectTypeOnSelf {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub move_self_modifier: MoveSelfModifier,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
|
||||||
|
pub(crate) struct MoveSelfModifier {
|
||||||
|
#[suggestion_part(code = "")]
|
||||||
|
pub removal_span: Span,
|
||||||
|
#[suggestion_part(code = "{modifier}")]
|
||||||
|
pub insertion_span: Span,
|
||||||
|
pub modifier: String,
|
||||||
|
}
|
||||||
|
|
|
@ -2941,6 +2941,32 @@ impl<'a> Parser<'a> {
|
||||||
};
|
};
|
||||||
Ok((eself, eself_ident, eself_hi))
|
Ok((eself, eself_ident, eself_hi))
|
||||||
};
|
};
|
||||||
|
let expect_self_ident_not_typed =
|
||||||
|
|this: &mut Self, modifier: &SelfKind, modifier_span: Span| {
|
||||||
|
let eself_ident = expect_self_ident(this);
|
||||||
|
|
||||||
|
// Recover `: Type` after a qualified self
|
||||||
|
if this.may_recover() && this.eat_noexpect(&token::Colon) {
|
||||||
|
let snap = this.create_snapshot_for_diagnostic();
|
||||||
|
match this.parse_ty() {
|
||||||
|
Ok(ty) => {
|
||||||
|
this.dcx().emit_err(errors::IncorrectTypeOnSelf {
|
||||||
|
span: ty.span,
|
||||||
|
move_self_modifier: errors::MoveSelfModifier {
|
||||||
|
removal_span: modifier_span,
|
||||||
|
insertion_span: ty.span.shrink_to_lo(),
|
||||||
|
modifier: modifier.to_ref_suggestion(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Err(diag) => {
|
||||||
|
diag.cancel();
|
||||||
|
this.restore_snapshot(snap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eself_ident
|
||||||
|
};
|
||||||
// Recover for the grammar `*self`, `*const self`, and `*mut self`.
|
// Recover for the grammar `*self`, `*const self`, and `*mut self`.
|
||||||
let recover_self_ptr = |this: &mut Self| {
|
let recover_self_ptr = |this: &mut Self| {
|
||||||
this.dcx().emit_err(errors::SelfArgumentPointer { span: this.token.span });
|
this.dcx().emit_err(errors::SelfArgumentPointer { span: this.token.span });
|
||||||
|
@ -2978,7 +3004,9 @@ impl<'a> Parser<'a> {
|
||||||
// `¬_self`
|
// `¬_self`
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
(eself, expect_self_ident(self), self.prev_token.span)
|
let hi = self.token.span;
|
||||||
|
let self_ident = expect_self_ident_not_typed(self, &eself, eself_lo.until(hi));
|
||||||
|
(eself, self_ident, hi)
|
||||||
}
|
}
|
||||||
// `*self`
|
// `*self`
|
||||||
token::BinOp(token::Star) if is_isolated_self(self, 1) => {
|
token::BinOp(token::Star) if is_isolated_self(self, 1) => {
|
||||||
|
|
14
tests/ui/parser/typed-self-param.rs
Normal file
14
tests/ui/parser/typed-self-param.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
struct S;
|
||||||
|
|
||||||
|
impl S {
|
||||||
|
fn a(&self: Self) {}
|
||||||
|
//~^ ERROR type not allowed for shorthand `self` parameter
|
||||||
|
fn b(&mut self: Self) {}
|
||||||
|
//~^ ERROR type not allowed for shorthand `self` parameter
|
||||||
|
fn c<'c>(&'c mut self: Self) {}
|
||||||
|
//~^ ERROR type not allowed for shorthand `self` parameter
|
||||||
|
fn d<'d>(&'d self: Self) {}
|
||||||
|
//~^ ERROR type not allowed for shorthand `self` parameter
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {}
|
50
tests/ui/parser/typed-self-param.stderr
Normal file
50
tests/ui/parser/typed-self-param.stderr
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
error: type not allowed for shorthand `self` parameter
|
||||||
|
--> $DIR/typed-self-param.rs:4:17
|
||||||
|
|
|
||||||
|
LL | fn a(&self: Self) {}
|
||||||
|
| ^^^^
|
||||||
|
|
|
||||||
|
help: move the modifiers on `self` to the type
|
||||||
|
|
|
||||||
|
LL - fn a(&self: Self) {}
|
||||||
|
LL + fn a(self: &Self) {}
|
||||||
|
|
|
||||||
|
|
||||||
|
error: type not allowed for shorthand `self` parameter
|
||||||
|
--> $DIR/typed-self-param.rs:6:21
|
||||||
|
|
|
||||||
|
LL | fn b(&mut self: Self) {}
|
||||||
|
| ^^^^
|
||||||
|
|
|
||||||
|
help: move the modifiers on `self` to the type
|
||||||
|
|
|
||||||
|
LL - fn b(&mut self: Self) {}
|
||||||
|
LL + fn b(self: &mut Self) {}
|
||||||
|
|
|
||||||
|
|
||||||
|
error: type not allowed for shorthand `self` parameter
|
||||||
|
--> $DIR/typed-self-param.rs:8:28
|
||||||
|
|
|
||||||
|
LL | fn c<'c>(&'c mut self: Self) {}
|
||||||
|
| ^^^^
|
||||||
|
|
|
||||||
|
help: move the modifiers on `self` to the type
|
||||||
|
|
|
||||||
|
LL - fn c<'c>(&'c mut self: Self) {}
|
||||||
|
LL + fn c<'c>(self: &'c mut Self) {}
|
||||||
|
|
|
||||||
|
|
||||||
|
error: type not allowed for shorthand `self` parameter
|
||||||
|
--> $DIR/typed-self-param.rs:10:24
|
||||||
|
|
|
||||||
|
LL | fn d<'d>(&'d self: Self) {}
|
||||||
|
| ^^^^
|
||||||
|
|
|
||||||
|
help: move the modifiers on `self` to the type
|
||||||
|
|
|
||||||
|
LL - fn d<'d>(&'d self: Self) {}
|
||||||
|
LL + fn d<'d>(self: &'d Self) {}
|
||||||
|
|
|
||||||
|
|
||||||
|
error: aborting due to 4 previous errors
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue