(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)?
}
}
+ /// 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`.
///
--- /dev/null
+error: expected identifier, found keyword `impl`
+ --> $DIR/const-impl-recovery.rs:6:7
+ |
+LL | const impl Foo for i32 {}
+ | ^^^^ expected identifier, found keyword
+ |
+help: you might have meant to write a const trait impl
+ |
+LL | impl const Foo for i32 {}
+ |-- ^^^^^
+
+error: expected identifier, found keyword `impl`
+ --> $DIR/const-impl-recovery.rs:10:7
+ |
+LL | const impl<T: Foo> Bar for T {}
+ | ^^^^ expected identifier, found keyword
+ |
+help: you might have meant to write a const trait impl
+ |
+LL | impl<T: Foo> const Bar for T {}
+ |-- ^^^^^
+
+error: aborting due to 2 previous errors
+