diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 6168647183fdb..3ceabbd7e3c61 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -311,6 +311,10 @@ impl<'a> Parser<'a> { } else if self.eat(exp!(Bang)) { // Never type `!` TyKind::Never + } else if (self.token.is_keyword(kw::Const) || self.token.is_keyword(kw::Mut)) + && self.look_ahead(1, |t| *t == token::Star) + { + self.parse_ty_c_style_pointer()? } else if self.eat(exp!(Star)) { self.parse_ty_ptr()? } else if self.eat(exp!(OpenBracket)) { @@ -579,6 +583,42 @@ impl<'a> Parser<'a> { Ok(TyKind::TraitObject(bounds, TraitObjectSyntax::None)) } + /// Parses a raw pointer with a C-style typo + fn parse_ty_c_style_pointer(&mut self) -> PResult<'a, TyKind> { + let kw_span = self.token.span; + let mutbl = self.parse_const_or_mut(); + + if let Some(mutbl) = mutbl + && self.eat(exp!(Star)) + { + let star_span = self.prev_token.span; + + let mutability = match mutbl { + Mutability::Not => "const", + Mutability::Mut => "mut", + }; + + let ty = self.parse_ty_no_question_mark_recover()?; + + let _guar = self + .dcx() + .struct_span_err( + kw_span, + format!("raw pointer types must be written as `*{mutability} T`"), + ) + .with_multipart_suggestion( + format!("put the `*` before `{mutability}`"), + vec![(star_span, String::new()), (kw_span.shrink_to_lo(), "*".to_string())], + Applicability::MachineApplicable, + ) + .emit(); + + return Ok(TyKind::Ptr(MutTy { ty, mutbl })); + } + // This is unreachable because we always get into if above and return from it + unreachable!("this should never happen happen") + } + /// Parses a raw pointer type: `*[const | mut] $type`. fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> { let mutbl = self.parse_const_or_mut().unwrap_or_else(|| { diff --git a/tests/ui/did_you_mean/c-style-pointer-types.fixed b/tests/ui/did_you_mean/c-style-pointer-types.fixed new file mode 100644 index 0000000000000..2517c8f1954d9 --- /dev/null +++ b/tests/ui/did_you_mean/c-style-pointer-types.fixed @@ -0,0 +1,113 @@ +//@ run-rustfix + +#![allow(unused)] + +pub const P1: *const u8 = 0 as _; +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +pub const P2: *mut u8 = 1 as _; +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +pub const P3: *const i32 = std::ptr::null(); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +pub const P4: *const i32 = std::ptr::null(); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +pub const P5: *mut i32 = std::ptr::null_mut(); +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +pub const P6: *mut i32 = std::ptr::null_mut(); +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +pub const P7: *const Vec = std::ptr::null(); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +pub const P8: *const std::collections::HashMap = std::ptr::null(); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +fn func1(p: *const u8) {} +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +fn func2(p: *mut u8) {} +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +fn func3() -> *const u8 { std::ptr::null() } +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +fn func4() -> *mut u8 { std::ptr::null_mut() } +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +struct S1 { + field: *const u8, + //~^ ERROR: raw pointer types must be written as `*const T` + //~| HELP: put the `*` before `const` +} + +struct S2 { + field: *mut u8, + //~^ ERROR: raw pointer types must be written as `*mut T` + //~| HELP: put the `*` before `mut` +} + +type Tuple1 = (*const u8, i32); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +type Tuple2 = (*mut u8, i32); +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +type Array1 = [*const u8; 10]; +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +type Array2 = [*mut u8; 10]; +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +type Alias1 = *const u8; +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +type Alias2 = *mut u8; +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +pub const P9: *const u8 = std::ptr::null(); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +pub const P10: *const u8 = std::ptr::null(); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +impl S1 { + fn method(self, size: *const u32) {} + //~^ ERROR: raw pointer types must be written as `*const T` + //~| HELP: put the `*` before `const` +} + +trait Trait1 { + fn method(p: *const u8); + //~^ ERROR: raw pointer types must be written as `*const T` + //~| HELP: put the `*` before `const` +} + +fn generic_func() -> *const T { std::ptr::null() } +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +fn main() {} diff --git a/tests/ui/did_you_mean/c-style-pointer-types.rs b/tests/ui/did_you_mean/c-style-pointer-types.rs new file mode 100644 index 0000000000000..562d85fb75fb8 --- /dev/null +++ b/tests/ui/did_you_mean/c-style-pointer-types.rs @@ -0,0 +1,113 @@ +//@ run-rustfix + +#![allow(unused)] + +pub const P1: const* u8 = 0 as _; +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +pub const P2: mut* u8 = 1 as _; +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +pub const P3: const* i32 = std::ptr::null(); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +pub const P4: const* i32 = std::ptr::null(); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +pub const P5: mut* i32 = std::ptr::null_mut(); +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +pub const P6: mut* i32 = std::ptr::null_mut(); +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +pub const P7: const* Vec = std::ptr::null(); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +pub const P8: const* std::collections::HashMap = std::ptr::null(); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +fn func1(p: const* u8) {} +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +fn func2(p: mut* u8) {} +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +fn func3() -> const* u8 { std::ptr::null() } +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +fn func4() -> mut* u8 { std::ptr::null_mut() } +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +struct S1 { + field: const* u8, + //~^ ERROR: raw pointer types must be written as `*const T` + //~| HELP: put the `*` before `const` +} + +struct S2 { + field: mut* u8, + //~^ ERROR: raw pointer types must be written as `*mut T` + //~| HELP: put the `*` before `mut` +} + +type Tuple1 = (const* u8, i32); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +type Tuple2 = (mut* u8, i32); +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +type Array1 = [const* u8; 10]; +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +type Array2 = [mut* u8; 10]; +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +type Alias1 = const* u8; +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +type Alias2 = mut* u8; +//~^ ERROR: raw pointer types must be written as `*mut T` +//~| HELP: put the `*` before `mut` + +pub const P9: const *u8 = std::ptr::null(); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +pub const P10: const * u8 = std::ptr::null(); +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +impl S1 { + fn method(self, size: const* u32) {} + //~^ ERROR: raw pointer types must be written as `*const T` + //~| HELP: put the `*` before `const` +} + +trait Trait1 { + fn method(p: const* u8); + //~^ ERROR: raw pointer types must be written as `*const T` + //~| HELP: put the `*` before `const` +} + +fn generic_func() -> const* T { std::ptr::null() } +//~^ ERROR: raw pointer types must be written as `*const T` +//~| HELP: put the `*` before `const` + +fn main() {} diff --git a/tests/ui/did_you_mean/c-style-pointer-types.stderr b/tests/ui/did_you_mean/c-style-pointer-types.stderr new file mode 100644 index 0000000000000..bbab72c016629 --- /dev/null +++ b/tests/ui/did_you_mean/c-style-pointer-types.stderr @@ -0,0 +1,302 @@ +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:5:15 + | +LL | pub const P1: const* u8 = 0 as _; + | ^^^^^ + | +help: put the `*` before `const` + | +LL - pub const P1: const* u8 = 0 as _; +LL + pub const P1: *const u8 = 0 as _; + | + +error: raw pointer types must be written as `*mut T` + --> $DIR/c-style-pointer-types.rs:9:15 + | +LL | pub const P2: mut* u8 = 1 as _; + | ^^^ + | +help: put the `*` before `mut` + | +LL - pub const P2: mut* u8 = 1 as _; +LL + pub const P2: *mut u8 = 1 as _; + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:13:15 + | +LL | pub const P3: const* i32 = std::ptr::null(); + | ^^^^^ + | +help: put the `*` before `const` + | +LL - pub const P3: const* i32 = std::ptr::null(); +LL + pub const P3: *const i32 = std::ptr::null(); + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:17:15 + | +LL | pub const P4: const* i32 = std::ptr::null(); + | ^^^^^ + | +help: put the `*` before `const` + | +LL - pub const P4: const* i32 = std::ptr::null(); +LL + pub const P4: *const i32 = std::ptr::null(); + | + +error: raw pointer types must be written as `*mut T` + --> $DIR/c-style-pointer-types.rs:21:15 + | +LL | pub const P5: mut* i32 = std::ptr::null_mut(); + | ^^^ + | +help: put the `*` before `mut` + | +LL - pub const P5: mut* i32 = std::ptr::null_mut(); +LL + pub const P5: *mut i32 = std::ptr::null_mut(); + | + +error: raw pointer types must be written as `*mut T` + --> $DIR/c-style-pointer-types.rs:25:15 + | +LL | pub const P6: mut* i32 = std::ptr::null_mut(); + | ^^^ + | +help: put the `*` before `mut` + | +LL - pub const P6: mut* i32 = std::ptr::null_mut(); +LL + pub const P6: *mut i32 = std::ptr::null_mut(); + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:29:15 + | +LL | pub const P7: const* Vec = std::ptr::null(); + | ^^^^^ + | +help: put the `*` before `const` + | +LL - pub const P7: const* Vec = std::ptr::null(); +LL + pub const P7: *const Vec = std::ptr::null(); + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:33:15 + | +LL | pub const P8: const* std::collections::HashMap = std::ptr::null(); + | ^^^^^ + | +help: put the `*` before `const` + | +LL - pub const P8: const* std::collections::HashMap = std::ptr::null(); +LL + pub const P8: *const std::collections::HashMap = std::ptr::null(); + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:37:13 + | +LL | fn func1(p: const* u8) {} + | ^^^^^ + | +help: put the `*` before `const` + | +LL - fn func1(p: const* u8) {} +LL + fn func1(p: *const u8) {} + | + +error: raw pointer types must be written as `*mut T` + --> $DIR/c-style-pointer-types.rs:41:13 + | +LL | fn func2(p: mut* u8) {} + | ^^^ + | +help: put the `*` before `mut` + | +LL - fn func2(p: mut* u8) {} +LL + fn func2(p: *mut u8) {} + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:45:15 + | +LL | fn func3() -> const* u8 { std::ptr::null() } + | ^^^^^ + | +help: put the `*` before `const` + | +LL - fn func3() -> const* u8 { std::ptr::null() } +LL + fn func3() -> *const u8 { std::ptr::null() } + | + +error: raw pointer types must be written as `*mut T` + --> $DIR/c-style-pointer-types.rs:49:15 + | +LL | fn func4() -> mut* u8 { std::ptr::null_mut() } + | ^^^ + | +help: put the `*` before `mut` + | +LL - fn func4() -> mut* u8 { std::ptr::null_mut() } +LL + fn func4() -> *mut u8 { std::ptr::null_mut() } + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:54:12 + | +LL | field: const* u8, + | ^^^^^ + | +help: put the `*` before `const` + | +LL - field: const* u8, +LL + field: *const u8, + | + +error: raw pointer types must be written as `*mut T` + --> $DIR/c-style-pointer-types.rs:60:12 + | +LL | field: mut* u8, + | ^^^ + | +help: put the `*` before `mut` + | +LL - field: mut* u8, +LL + field: *mut u8, + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:65:16 + | +LL | type Tuple1 = (const* u8, i32); + | ^^^^^ + | +help: put the `*` before `const` + | +LL - type Tuple1 = (const* u8, i32); +LL + type Tuple1 = (*const u8, i32); + | + +error: raw pointer types must be written as `*mut T` + --> $DIR/c-style-pointer-types.rs:69:16 + | +LL | type Tuple2 = (mut* u8, i32); + | ^^^ + | +help: put the `*` before `mut` + | +LL - type Tuple2 = (mut* u8, i32); +LL + type Tuple2 = (*mut u8, i32); + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:73:16 + | +LL | type Array1 = [const* u8; 10]; + | ^^^^^ + | +help: put the `*` before `const` + | +LL - type Array1 = [const* u8; 10]; +LL + type Array1 = [*const u8; 10]; + | + +error: raw pointer types must be written as `*mut T` + --> $DIR/c-style-pointer-types.rs:77:16 + | +LL | type Array2 = [mut* u8; 10]; + | ^^^ + | +help: put the `*` before `mut` + | +LL - type Array2 = [mut* u8; 10]; +LL + type Array2 = [*mut u8; 10]; + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:81:15 + | +LL | type Alias1 = const* u8; + | ^^^^^ + | +help: put the `*` before `const` + | +LL - type Alias1 = const* u8; +LL + type Alias1 = *const u8; + | + +error: raw pointer types must be written as `*mut T` + --> $DIR/c-style-pointer-types.rs:85:15 + | +LL | type Alias2 = mut* u8; + | ^^^ + | +help: put the `*` before `mut` + | +LL - type Alias2 = mut* u8; +LL + type Alias2 = *mut u8; + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:89:15 + | +LL | pub const P9: const *u8 = std::ptr::null(); + | ^^^^^ + | +help: put the `*` before `const` + | +LL - pub const P9: const *u8 = std::ptr::null(); +LL + pub const P9: *const u8 = std::ptr::null(); + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:93:16 + | +LL | pub const P10: const * u8 = std::ptr::null(); + | ^^^^^ + | +help: put the `*` before `const` + | +LL - pub const P10: const * u8 = std::ptr::null(); +LL + pub const P10: *const u8 = std::ptr::null(); + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:98:27 + | +LL | fn method(self, size: const* u32) {} + | ^^^^^ + | +help: put the `*` before `const` + | +LL - fn method(self, size: const* u32) {} +LL + fn method(self, size: *const u32) {} + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:104:18 + | +LL | fn method(p: const* u8); + | ^^^^^ + | +help: put the `*` before `const` + | +LL - fn method(p: const* u8); +LL + fn method(p: *const u8); + | + +error: raw pointer types must be written as `*const T` + --> $DIR/c-style-pointer-types.rs:109:25 + | +LL | fn generic_func() -> const* T { std::ptr::null() } + | ^^^^^ + | +help: put the `*` before `const` + | +LL - fn generic_func() -> const* T { std::ptr::null() } +LL + fn generic_func() -> *const T { std::ptr::null() } + | + +error: aborting due to 25 previous errors +