Auto merge of #87235 - poliorcetics:issue-87217-fn-quali-order, r=nagisa
Improve diagnostics for wrongly ordered keywords in function declaration Fix #87217 `@rustbot` label A-diagnostics T-compiler
This commit is contained in:
commit
74a11c63f8
13 changed files with 184 additions and 4 deletions
|
@ -1768,8 +1768,14 @@ impl<'a> Parser<'a> {
|
||||||
pub(super) fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
|
pub(super) fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
|
||||||
let sp_start = self.token.span;
|
let sp_start = self.token.span;
|
||||||
let constness = self.parse_constness();
|
let constness = self.parse_constness();
|
||||||
|
|
||||||
|
let async_start_sp = self.token.span;
|
||||||
let asyncness = self.parse_asyncness();
|
let asyncness = self.parse_asyncness();
|
||||||
|
|
||||||
|
let unsafe_start_sp = self.token.span;
|
||||||
let unsafety = self.parse_unsafety();
|
let unsafety = self.parse_unsafety();
|
||||||
|
|
||||||
|
let ext_start_sp = self.token.span;
|
||||||
let ext = self.parse_extern();
|
let ext = self.parse_extern();
|
||||||
|
|
||||||
if let Async::Yes { span, .. } = asyncness {
|
if let Async::Yes { span, .. } = asyncness {
|
||||||
|
@ -1784,8 +1790,35 @@ impl<'a> Parser<'a> {
|
||||||
Ok(true) => {}
|
Ok(true) => {}
|
||||||
Ok(false) => unreachable!(),
|
Ok(false) => unreachable!(),
|
||||||
Err(mut err) => {
|
Err(mut err) => {
|
||||||
|
// Qualifier keywords ordering check
|
||||||
|
|
||||||
|
// This will allow the machine fix to directly place the keyword in the correct place
|
||||||
|
let current_qual_sp = if self.check_keyword(kw::Const) {
|
||||||
|
Some(async_start_sp)
|
||||||
|
} else if self.check_keyword(kw::Async) {
|
||||||
|
Some(unsafe_start_sp)
|
||||||
|
} else if self.check_keyword(kw::Unsafe) {
|
||||||
|
Some(ext_start_sp)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(current_qual_sp) = current_qual_sp {
|
||||||
|
let current_qual_sp = current_qual_sp.to(self.prev_token.span);
|
||||||
|
if let Ok(current_qual) = self.span_to_snippet(current_qual_sp) {
|
||||||
|
let invalid_qual_sp = self.token.uninterpolated_span();
|
||||||
|
let invalid_qual = self.span_to_snippet(invalid_qual_sp).unwrap();
|
||||||
|
|
||||||
|
err.span_suggestion(
|
||||||
|
current_qual_sp.to(invalid_qual_sp),
|
||||||
|
&format!("`{}` must come before `{}`", invalid_qual, current_qual),
|
||||||
|
format!("{} {}", invalid_qual, current_qual),
|
||||||
|
Applicability::MachineApplicable,
|
||||||
|
).note("keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`");
|
||||||
|
}
|
||||||
|
}
|
||||||
// Recover incorrect visibility order such as `async pub`.
|
// Recover incorrect visibility order such as `async pub`.
|
||||||
if self.check_keyword(kw::Pub) {
|
else if self.check_keyword(kw::Pub) {
|
||||||
let sp = sp_start.to(self.prev_token.span);
|
let sp = sp_start.to(self.prev_token.span);
|
||||||
if let Ok(snippet) = self.span_to_snippet(sp) {
|
if let Ok(snippet) = self.span_to_snippet(sp) {
|
||||||
let vis = match self.parse_visibility(FollowedByType::No) {
|
let vis = match self.parse_visibility(FollowedByType::No) {
|
||||||
|
|
|
@ -2,7 +2,12 @@ error: expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
|
||||||
--> $DIR/no-async-const.rs:4:11
|
--> $DIR/no-async-const.rs:4:11
|
||||||
|
|
|
|
||||||
LL | pub async const fn x() {}
|
LL | pub async const fn x() {}
|
||||||
| ^^^^^ expected one of `extern`, `fn`, or `unsafe`
|
| ------^^^^^
|
||||||
|
| | |
|
||||||
|
| | expected one of `extern`, `fn`, or `unsafe`
|
||||||
|
| help: `const` must come before `async`: `const async`
|
||||||
|
|
|
||||||
|
= note: keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
|
|
@ -5,15 +5,25 @@ LL | impl S {
|
||||||
| - while parsing this item list starting here
|
| - while parsing this item list starting here
|
||||||
LL | #[cfg(FALSE)]
|
LL | #[cfg(FALSE)]
|
||||||
LL | unsafe async fn g() {}
|
LL | unsafe async fn g() {}
|
||||||
| ^^^^^ expected one of `extern` or `fn`
|
| -------^^^^^
|
||||||
|
| | |
|
||||||
|
| | expected one of `extern` or `fn`
|
||||||
|
| help: `async` must come before `unsafe`: `async unsafe`
|
||||||
LL | }
|
LL | }
|
||||||
| - the item list ends here
|
| - the item list ends here
|
||||||
|
|
|
||||||
|
= note: keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
|
||||||
|
|
||||||
error: expected one of `extern` or `fn`, found keyword `async`
|
error: expected one of `extern` or `fn`, found keyword `async`
|
||||||
--> $DIR/no-unsafe-async.rs:11:8
|
--> $DIR/no-unsafe-async.rs:11:8
|
||||||
|
|
|
|
||||||
LL | unsafe async fn f() {}
|
LL | unsafe async fn f() {}
|
||||||
| ^^^^^ expected one of `extern` or `fn`
|
| -------^^^^^
|
||||||
|
| | |
|
||||||
|
| | expected one of `extern` or `fn`
|
||||||
|
| help: `async` must come before `unsafe`: `async unsafe`
|
||||||
|
|
|
||||||
|
= note: keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
// Test that even when `const` is already present, the proposed fix is `const const async`,
|
||||||
|
// like for `pub pub`.
|
||||||
|
|
||||||
|
const async const fn test() {}
|
||||||
|
//~^ ERROR expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
|
||||||
|
//~| NOTE expected one of `extern`, `fn`, or `unsafe`
|
||||||
|
//~| HELP `const` must come before `async`
|
||||||
|
//~| SUGGESTION const async
|
||||||
|
//~| NOTE keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
|
|
@ -0,0 +1,13 @@
|
||||||
|
error: expected one of `extern`, `fn`, or `unsafe`, found keyword `const`
|
||||||
|
--> $DIR/const-async-const.rs:6:13
|
||||||
|
|
|
||||||
|
LL | const async const fn test() {}
|
||||||
|
| ------^^^^^
|
||||||
|
| | |
|
||||||
|
| | expected one of `extern`, `fn`, or `unsafe`
|
||||||
|
| help: `const` must come before `async`: `const async`
|
||||||
|
|
|
||||||
|
= note: keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
// There is an order to respect for keywords before a function:
|
||||||
|
// `<visibility>, const, async, unsafe, extern, "<ABI>"`
|
||||||
|
//
|
||||||
|
// This test ensures the compiler is helpful about them being misplaced.
|
||||||
|
// Visibilities are tested elsewhere.
|
||||||
|
|
||||||
|
async unsafe const fn test() {}
|
||||||
|
//~^ ERROR expected one of `extern` or `fn`, found keyword `const`
|
||||||
|
//~| NOTE expected one of `extern` or `fn`
|
||||||
|
//~| HELP `const` must come before `async unsafe`
|
||||||
|
//~| SUGGESTION const async unsafe
|
||||||
|
//~| NOTE keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
|
|
@ -0,0 +1,13 @@
|
||||||
|
error: expected one of `extern` or `fn`, found keyword `const`
|
||||||
|
--> $DIR/several-kw-jump.rs:9:14
|
||||||
|
|
|
||||||
|
LL | async unsafe const fn test() {}
|
||||||
|
| -------------^^^^^
|
||||||
|
| | |
|
||||||
|
| | expected one of `extern` or `fn`
|
||||||
|
| help: `const` must come before `async unsafe`: `const async unsafe`
|
||||||
|
|
|
||||||
|
= note: keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
14
src/test/ui/parser/issue-87217-keyword-order/wrong-async.rs
Normal file
14
src/test/ui/parser/issue-87217-keyword-order/wrong-async.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
// There is an order to respect for keywords before a function:
|
||||||
|
// `<visibility>, const, async, unsafe, extern, "<ABI>"`
|
||||||
|
//
|
||||||
|
// This test ensures the compiler is helpful about them being misplaced.
|
||||||
|
// Visibilities are tested elsewhere.
|
||||||
|
|
||||||
|
unsafe async fn test() {}
|
||||||
|
//~^ ERROR expected one of `extern` or `fn`, found keyword `async`
|
||||||
|
//~| NOTE expected one of `extern` or `fn`
|
||||||
|
//~| HELP `async` must come before `unsafe`
|
||||||
|
//~| SUGGESTION async unsafe
|
||||||
|
//~| NOTE keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
|
|
@ -0,0 +1,13 @@
|
||||||
|
error: expected one of `extern` or `fn`, found keyword `async`
|
||||||
|
--> $DIR/wrong-async.rs:9:8
|
||||||
|
|
|
||||||
|
LL | unsafe async fn test() {}
|
||||||
|
| -------^^^^^
|
||||||
|
| | |
|
||||||
|
| | expected one of `extern` or `fn`
|
||||||
|
| help: `async` must come before `unsafe`: `async unsafe`
|
||||||
|
|
|
||||||
|
= note: keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
14
src/test/ui/parser/issue-87217-keyword-order/wrong-const.rs
Normal file
14
src/test/ui/parser/issue-87217-keyword-order/wrong-const.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
// There is an order to respect for keywords before a function:
|
||||||
|
// `<visibility>, const, async, unsafe, extern, "<ABI>"`
|
||||||
|
//
|
||||||
|
// This test ensures the compiler is helpful about them being misplaced.
|
||||||
|
// Visibilities are tested elsewhere.
|
||||||
|
|
||||||
|
unsafe const fn test() {}
|
||||||
|
//~^ ERROR expected one of `extern` or `fn`, found keyword `const`
|
||||||
|
//~| NOTE expected one of `extern` or `fn`
|
||||||
|
//~| HELP `const` must come before `unsafe`
|
||||||
|
//~| SUGGESTION const unsafe
|
||||||
|
//~| NOTE keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
|
|
@ -0,0 +1,13 @@
|
||||||
|
error: expected one of `extern` or `fn`, found keyword `const`
|
||||||
|
--> $DIR/wrong-const.rs:9:8
|
||||||
|
|
|
||||||
|
LL | unsafe const fn test() {}
|
||||||
|
| -------^^^^^
|
||||||
|
| | |
|
||||||
|
| | expected one of `extern` or `fn`
|
||||||
|
| help: `const` must come before `unsafe`: `const unsafe`
|
||||||
|
|
|
||||||
|
= note: keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
14
src/test/ui/parser/issue-87217-keyword-order/wrong-unsafe.rs
Normal file
14
src/test/ui/parser/issue-87217-keyword-order/wrong-unsafe.rs
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// edition:2018
|
||||||
|
|
||||||
|
// There is an order to respect for keywords before a function:
|
||||||
|
// `<visibility>, const, async, unsafe, extern, "<ABI>"`
|
||||||
|
//
|
||||||
|
// This test ensures the compiler is helpful about them being misplaced.
|
||||||
|
// Visibilities are tested elsewhere.
|
||||||
|
|
||||||
|
extern unsafe fn test() {}
|
||||||
|
//~^ ERROR expected `fn`, found keyword `unsafe`
|
||||||
|
//~| NOTE expected `fn`
|
||||||
|
//~| HELP `unsafe` must come before `extern`
|
||||||
|
//~| SUGGESTION unsafe extern
|
||||||
|
//~| NOTE keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
|
|
@ -0,0 +1,13 @@
|
||||||
|
error: expected `fn`, found keyword `unsafe`
|
||||||
|
--> $DIR/wrong-unsafe.rs:9:8
|
||||||
|
|
|
||||||
|
LL | extern unsafe fn test() {}
|
||||||
|
| -------^^^^^^
|
||||||
|
| | |
|
||||||
|
| | expected `fn`
|
||||||
|
| help: `unsafe` must come before `extern`: `unsafe extern`
|
||||||
|
|
|
||||||
|
= note: keyword order for functions declaration is `default`, `pub`, `const`, `async`, `unsafe`, `extern`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue