From 41f5a30690884578f697727c38139728131217ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Sun, 28 May 2023 01:18:51 +0000 Subject: [PATCH] Recover upon encountering mistyped `Const` in const param def --- compiler/rustc_parse/src/parser/generics.rs | 44 ++++++++++++++++++ .../parser/typod-const-in-const-param-def.rs | 16 +++++++ .../typod-const-in-const-param-def.stderr | 46 +++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 tests/ui/parser/typod-const-in-const-param-def.rs create mode 100644 tests/ui/parser/typod-const-in-const-param-def.stderr diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index cd779b0b43e..8ab38c4fb8b 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -43,6 +43,15 @@ fn parse_lt_param_bounds(&mut self) -> GenericBounds { fn parse_ty_param(&mut self, preceding_attrs: AttrVec) -> PResult<'a, GenericParam> { let ident = self.parse_ident()?; + // We might have a typo'd `Const` that was parsed as a type parameter. + if self.may_recover() + && ident.name.as_str().to_ascii_lowercase() == kw::Const.as_str() + && self.check_ident() + // `Const` followed by IDENT + { + return Ok(self.recover_const_param_with_mistyped_const(preceding_attrs, ident)?); + } + // Parse optional colon and param bounds. let mut colon_span = None; let bounds = if self.eat(&token::Colon) { @@ -120,6 +129,41 @@ pub(crate) fn parse_const_param( }) } + pub(crate) fn recover_const_param_with_mistyped_const( + &mut self, + preceding_attrs: AttrVec, + mistyped_const_ident: Ident, + ) -> PResult<'a, GenericParam> { + let ident = self.parse_ident()?; + self.expect(&token::Colon)?; + let ty = self.parse_ty()?; + + // Parse optional const generics default value. + let default = if self.eat(&token::Eq) { Some(self.parse_const_arg()?) } else { None }; + + let mut err = self.struct_span_err( + mistyped_const_ident.span, + format!("`const` keyword was mistyped as `{}`", mistyped_const_ident.as_str()), + ); + err.span_suggestion_verbose( + mistyped_const_ident.span, + "use the `const` keyword", + kw::Const.as_str(), + Applicability::MachineApplicable, + ); + err.emit(); + + Ok(GenericParam { + ident, + id: ast::DUMMY_NODE_ID, + attrs: preceding_attrs, + bounds: Vec::new(), + kind: GenericParamKind::Const { ty, kw_span: mistyped_const_ident.span, default }, + is_placeholder: false, + colon_span: None, + }) + } + /// Parses a (possibly empty) list of lifetime and type parameters, possibly including /// a trailing comma and erroneous trailing attributes. pub(super) fn parse_generic_params(&mut self) -> PResult<'a, ThinVec> { diff --git a/tests/ui/parser/typod-const-in-const-param-def.rs b/tests/ui/parser/typod-const-in-const-param-def.rs new file mode 100644 index 00000000000..85d3ebba57a --- /dev/null +++ b/tests/ui/parser/typod-const-in-const-param-def.rs @@ -0,0 +1,16 @@ +pub fn foo() {} +//~^ ERROR `const` keyword was mistyped as `Const` + +pub fn bar() {} +// OK + +pub fn baz() {} +//~^ ERROR `const` keyword was mistyped as `Const` + +pub fn qux() {} +//~^ ERROR `const` keyword was mistyped as `Const` + +pub fn quux() {} +//~^ ERROR `const` keyword was mistyped as `Const` + +fn main() {} diff --git a/tests/ui/parser/typod-const-in-const-param-def.stderr b/tests/ui/parser/typod-const-in-const-param-def.stderr new file mode 100644 index 00000000000..75d73c6ea87 --- /dev/null +++ b/tests/ui/parser/typod-const-in-const-param-def.stderr @@ -0,0 +1,46 @@ +error: `const` keyword was mistyped as `Const` + --> $DIR/typod-const-in-const-param-def.rs:1:12 + | +LL | pub fn foo() {} + | ^^^^^ + | +help: use the `const` keyword + | +LL | pub fn foo() {} + | ~~~~~ + +error: `const` keyword was mistyped as `Const` + --> $DIR/typod-const-in-const-param-def.rs:7:12 + | +LL | pub fn baz() {} + | ^^^^^ + | +help: use the `const` keyword + | +LL | pub fn baz() {} + | ~~~~~ + +error: `const` keyword was mistyped as `Const` + --> $DIR/typod-const-in-const-param-def.rs:10:15 + | +LL | pub fn qux() {} + | ^^^^^ + | +help: use the `const` keyword + | +LL | pub fn qux() {} + | ~~~~~ + +error: `const` keyword was mistyped as `Const` + --> $DIR/typod-const-in-const-param-def.rs:13:16 + | +LL | pub fn quux() {} + | ^^^^^ + | +help: use the `const` keyword + | +LL | pub fn quux() {} + | ~~~~~ + +error: aborting due to 4 previous errors +