diff options
| author | 许杰友 Jieyou Xu (Joe) <jieyouxu@outlook.com> | 2023-05-28 01:18:51 +0000 |
|---|---|---|
| committer | 许杰友 Jieyou Xu (Joe) <jieyouxu@outlook.com> | 2023-05-28 16:55:21 +0800 |
| commit | 41f5a30690884578f697727c38139728131217ea (patch) | |
| tree | 6dfad2224f55f6be2ef042593be65a201bd95410 | |
| parent | b9c5fdc888e05be88269a47d40fd0d911ec2be0b (diff) | |
| download | rust-41f5a30690884578f697727c38139728131217ea.tar.gz rust-41f5a30690884578f697727c38139728131217ea.zip | |
Recover upon encountering mistyped `Const` in const param def
| -rw-r--r-- | compiler/rustc_parse/src/parser/generics.rs | 44 | ||||
| -rw-r--r-- | tests/ui/parser/typod-const-in-const-param-def.rs | 16 | ||||
| -rw-r--r-- | tests/ui/parser/typod-const-in-const-param-def.stderr | 46 |
3 files changed, 106 insertions, 0 deletions
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 @@ impl<'a> Parser<'a> { 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 @@ impl<'a> Parser<'a> { }) } + 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<ast::GenericParam>> { 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<Const N: u8>() {} +//~^ ERROR `const` keyword was mistyped as `Const` + +pub fn bar<Const>() {} +// OK + +pub fn baz<Const N: u8, T>() {} +//~^ ERROR `const` keyword was mistyped as `Const` + +pub fn qux<T, Const N: u8>() {} +//~^ ERROR `const` keyword was mistyped as `Const` + +pub fn quux<T, Const N: u8, U>() {} +//~^ 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<Const N: u8>() {} + | ^^^^^ + | +help: use the `const` keyword + | +LL | pub fn foo<const N: u8>() {} + | ~~~~~ + +error: `const` keyword was mistyped as `Const` + --> $DIR/typod-const-in-const-param-def.rs:7:12 + | +LL | pub fn baz<Const N: u8, T>() {} + | ^^^^^ + | +help: use the `const` keyword + | +LL | pub fn baz<const N: u8, T>() {} + | ~~~~~ + +error: `const` keyword was mistyped as `Const` + --> $DIR/typod-const-in-const-param-def.rs:10:15 + | +LL | pub fn qux<T, Const N: u8>() {} + | ^^^^^ + | +help: use the `const` keyword + | +LL | pub fn qux<T, const N: u8>() {} + | ~~~~~ + +error: `const` keyword was mistyped as `Const` + --> $DIR/typod-const-in-const-param-def.rs:13:16 + | +LL | pub fn quux<T, Const N: u8, U>() {} + | ^^^^^ + | +help: use the `const` keyword + | +LL | pub fn quux<T, const N: u8, U>() {} + | ~~~~~ + +error: aborting due to 4 previous errors + |
