1
Fork 0

Fix suggestion when shorthand self has erroneous type

This commit is contained in:
Michael Goulet 2024-03-08 00:02:11 +00:00
parent 96e51d9482
commit 05c34cc5ed
6 changed files with 127 additions and 1 deletions

View file

@ -343,6 +343,9 @@ parse_incorrect_semicolon =
.suggestion = remove this 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`
.parentheses_suggestion = `await` is not a method call, remove the parentheses

View file

@ -3409,3 +3409,22 @@ pub(crate) struct PolarityAndModifiers {
pub polarity: &'static str,
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,
}

View file

@ -2941,6 +2941,32 @@ impl<'a> Parser<'a> {
};
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`.
let recover_self_ptr = |this: &mut Self| {
this.dcx().emit_err(errors::SelfArgumentPointer { span: this.token.span });
@ -2978,7 +3004,9 @@ impl<'a> Parser<'a> {
// `&not_self`
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`
token::BinOp(token::Star) if is_isolated_self(self, 1) => {