Auto merge of #79668 - coolreader18:recover-const-impl, r=petrochenkov
Recover on `const impl<> X for Y` `@leonardo-m` mentioned that `const impl Foo for Bar` could be recovered from in #79287. I'm not sure about the error strings as they are, I think it should probably be something like the error that `expected_one_of_not_found` makes + the suggestion to flip the keywords, but I'm not sure how exactly to do that. Also, I decided not to try to handle `const unsafe impl` or `unsafe const impl` cause I figured that `unsafe impl const` would be pretty rare anyway (if it's even valid?), and it wouldn't be worth making the code more messy.
This commit is contained in:
commit
057937bdda
5 changed files with 99 additions and 3 deletions
|
@ -247,9 +247,14 @@ impl<'a> Parser<'a> {
|
|||
(ident, ItemKind::Static(ty, m, expr))
|
||||
} else if let Const::Yes(const_span) = self.parse_constness() {
|
||||
// CONST ITEM
|
||||
self.recover_const_mut(const_span);
|
||||
let (ident, ty, expr) = self.parse_item_global(None)?;
|
||||
(ident, ItemKind::Const(def(), ty, expr))
|
||||
if self.token.is_keyword(kw::Impl) {
|
||||
// recover from `const impl`, suggest `impl const`
|
||||
self.recover_const_impl(const_span, attrs, def())?
|
||||
} else {
|
||||
self.recover_const_mut(const_span);
|
||||
let (ident, ty, expr) = self.parse_item_global(None)?;
|
||||
(ident, ItemKind::Const(def(), ty, expr))
|
||||
}
|
||||
} else if self.check_keyword(kw::Trait) || self.check_auto_or_unsafe_trait_item() {
|
||||
// TRAIT ITEM
|
||||
self.parse_item_trait(attrs, lo)?
|
||||
|
@ -988,6 +993,36 @@ impl<'a> Parser<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Recover on `const impl` with `const` already eaten.
|
||||
fn recover_const_impl(
|
||||
&mut self,
|
||||
const_span: Span,
|
||||
attrs: &mut Vec<Attribute>,
|
||||
defaultness: Defaultness,
|
||||
) -> PResult<'a, ItemInfo> {
|
||||
let impl_span = self.token.span;
|
||||
let mut err = self.expected_ident_found();
|
||||
let mut impl_info = self.parse_item_impl(attrs, defaultness)?;
|
||||
match impl_info.1 {
|
||||
// only try to recover if this is implementing a trait for a type
|
||||
ItemKind::Impl { of_trait: Some(ref trai), ref mut constness, .. } => {
|
||||
*constness = Const::Yes(const_span);
|
||||
|
||||
let before_trait = trai.path.span.shrink_to_lo();
|
||||
let const_up_to_impl = const_span.with_hi(impl_span.lo());
|
||||
err.multipart_suggestion(
|
||||
"you might have meant to write a const trait impl",
|
||||
vec![(const_up_to_impl, "".to_owned()), (before_trait, "const ".to_owned())],
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
ItemKind::Impl { .. } => return Err(err),
|
||||
_ => unreachable!(),
|
||||
}
|
||||
Ok(impl_info)
|
||||
}
|
||||
|
||||
/// Parse `["const" | ("static" "mut"?)] $ident ":" $ty (= $expr)?` with
|
||||
/// `["const" | ("static" "mut"?)]` already parsed and stored in `m`.
|
||||
///
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue