Rollup merge of #70421 - Centril:recover-const-async-fn-ptr, r=estebank
parse: recover on `const fn()` / `async fn()` Recover on `const fn()` and `async fn()` function pointers, suggesting to remove the qualifier. For example: ``` error: an `fn` pointer type cannot be `async` --> $DIR/recover-const-async-fn-ptr.rs:6:11 | LL | type T3 = async fn(); | -----^^^^^ | | | `async` because of this | help: remove the `async` qualifier ``` r? @estebank
This commit is contained in:
commit
03591e8a78
@ -1496,7 +1496,7 @@ fn parse_fn_body(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, Option<P<
|
||||
}
|
||||
|
||||
/// Is the current token the start of an `FnHeader` / not a valid parse?
|
||||
fn check_fn_front_matter(&mut self) -> bool {
|
||||
pub(super) fn check_fn_front_matter(&mut self) -> bool {
|
||||
// We use an over-approximation here.
|
||||
// `const const`, `fn const` won't parse, but we're not stepping over other syntax either.
|
||||
const QUALS: [Symbol; 4] = [kw::Const, kw::Async, kw::Unsafe, kw::Extern];
|
||||
@ -1523,7 +1523,7 @@ fn check_fn_front_matter(&mut self) -> bool {
|
||||
/// FnQual = "const"? "async"? "unsafe"? Extern? ;
|
||||
/// FnFrontMatter = FnQual? "fn" ;
|
||||
/// ```
|
||||
fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
|
||||
pub(super) fn parse_fn_front_matter(&mut self) -> PResult<'a, FnHeader> {
|
||||
let constness = self.parse_constness();
|
||||
let asyncness = self.parse_asyncness();
|
||||
let unsafety = self.parse_unsafety();
|
||||
|
@ -127,16 +127,16 @@ fn parse_ty_common(
|
||||
} else if self.eat_keyword(kw::Underscore) {
|
||||
// A type to be inferred `_`
|
||||
TyKind::Infer
|
||||
} else if self.token_is_bare_fn_keyword() {
|
||||
} else if self.check_fn_front_matter() {
|
||||
// Function pointer type
|
||||
self.parse_ty_bare_fn(Vec::new())?
|
||||
self.parse_ty_bare_fn(lo, Vec::new())?
|
||||
} else if self.check_keyword(kw::For) {
|
||||
// Function pointer type or bound list (trait object type) starting with a poly-trait.
|
||||
// `for<'lt> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
|
||||
// `for<'lt> Trait1<'lt> + Trait2 + 'a`
|
||||
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
|
||||
if self.token_is_bare_fn_keyword() {
|
||||
self.parse_ty_bare_fn(lifetime_defs)?
|
||||
if self.check_fn_front_matter() {
|
||||
self.parse_ty_bare_fn(lo, lifetime_defs)?
|
||||
} else {
|
||||
let path = self.parse_path(PathStyle::Type)?;
|
||||
let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
|
||||
@ -291,13 +291,6 @@ fn parse_typeof_ty(&mut self) -> PResult<'a, TyKind> {
|
||||
Ok(TyKind::Typeof(expr))
|
||||
}
|
||||
|
||||
/// Is the current token one of the keywords that signals a bare function type?
|
||||
fn token_is_bare_fn_keyword(&mut self) -> bool {
|
||||
self.check_keyword(kw::Fn)
|
||||
|| self.check_keyword(kw::Unsafe)
|
||||
|| self.check_keyword(kw::Extern)
|
||||
}
|
||||
|
||||
/// Parses a function pointer type (`TyKind::BareFn`).
|
||||
/// ```
|
||||
/// [unsafe] [extern "ABI"] fn (S) -> T
|
||||
@ -306,12 +299,31 @@ fn token_is_bare_fn_keyword(&mut self) -> bool {
|
||||
/// | | | Return type
|
||||
/// Function Style ABI Parameter types
|
||||
/// ```
|
||||
fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> {
|
||||
let unsafety = self.parse_unsafety();
|
||||
let ext = self.parse_extern()?;
|
||||
self.expect_keyword(kw::Fn)?;
|
||||
/// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers.
|
||||
fn parse_ty_bare_fn(&mut self, lo: Span, params: Vec<GenericParam>) -> PResult<'a, TyKind> {
|
||||
let ast::FnHeader { ext, unsafety, constness, asyncness } = self.parse_fn_front_matter()?;
|
||||
let decl = self.parse_fn_decl(|_| false, AllowPlus::No)?;
|
||||
Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params, decl })))
|
||||
let whole_span = lo.to(self.prev_token.span);
|
||||
if let ast::Const::Yes(span) = constness {
|
||||
self.error_fn_ptr_bad_qualifier(whole_span, span, "const");
|
||||
}
|
||||
if let ast::Async::Yes { span, .. } = asyncness {
|
||||
self.error_fn_ptr_bad_qualifier(whole_span, span, "async");
|
||||
}
|
||||
Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl })))
|
||||
}
|
||||
|
||||
/// Emit an error for the given bad function pointer qualifier.
|
||||
fn error_fn_ptr_bad_qualifier(&self, span: Span, qual_span: Span, qual: &str) {
|
||||
self.struct_span_err(span, &format!("an `fn` pointer type cannot be `{}`", qual))
|
||||
.span_label(qual_span, format!("`{}` because of this", qual))
|
||||
.span_suggestion_short(
|
||||
qual_span,
|
||||
&format!("remove the `{}` qualifier", qual),
|
||||
String::new(),
|
||||
Applicability::MaybeIncorrect,
|
||||
)
|
||||
.emit();
|
||||
}
|
||||
|
||||
/// Parses an `impl B0 + ... + Bn` type.
|
||||
|
@ -1,3 +1,3 @@
|
||||
type A = extern::foo::bar; //~ ERROR expected `fn`, found `::`
|
||||
type A = extern::foo::bar; //~ ERROR expected type, found keyword `extern`
|
||||
|
||||
fn main() {}
|
||||
|
@ -1,8 +1,8 @@
|
||||
error: expected `fn`, found `::`
|
||||
--> $DIR/keyword-extern-as-identifier-type.rs:1:16
|
||||
error: expected type, found keyword `extern`
|
||||
--> $DIR/keyword-extern-as-identifier-type.rs:1:10
|
||||
|
|
||||
LL | type A = extern::foo::bar;
|
||||
| ^^ expected `fn`
|
||||
| ^^^^^^ expected type
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -12,7 +12,7 @@ error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `;`
|
||||
LL | impl W <s(f;Y(;]
|
||||
| ^ expected one of 7 possible tokens
|
||||
|
||||
error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `<`, `>`, `?`, `[`, `_`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, lifetime, or path, found `;`
|
||||
error: expected one of `!`, `&&`, `&`, `(`, `)`, `*`, `+`, `,`, `->`, `...`, `::`, `<`, `>`, `?`, `[`, `_`, `async`, `const`, `dyn`, `extern`, `fn`, `for`, `impl`, `unsafe`, lifetime, or path, found `;`
|
||||
--> $DIR/issue-63116.rs:3:15
|
||||
|
|
||||
LL | impl W <s(f;Y(;]
|
||||
|
25
src/test/ui/parser/recover-const-async-fn-ptr.rs
Normal file
25
src/test/ui/parser/recover-const-async-fn-ptr.rs
Normal file
@ -0,0 +1,25 @@
|
||||
// edition:2018
|
||||
|
||||
type T0 = const fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type T1 = const extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type T2 = const unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type T3 = async fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type T4 = async extern fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type T5 = async unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type T6 = const async unsafe extern "C" fn();
|
||||
//~^ ERROR an `fn` pointer type cannot be `const`
|
||||
//~| ERROR an `fn` pointer type cannot be `async`
|
||||
|
||||
type FT0 = for<'a> const fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type FT1 = for<'a> const extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type FT2 = for<'a> const unsafe extern fn(); //~ ERROR an `fn` pointer type cannot be `const`
|
||||
type FT3 = for<'a> async fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type FT4 = for<'a> async extern fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type FT5 = for<'a> async unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async`
|
||||
type FT6 = for<'a> const async unsafe extern "C" fn();
|
||||
//~^ ERROR an `fn` pointer type cannot be `const`
|
||||
//~| ERROR an `fn` pointer type cannot be `async`
|
||||
|
||||
fn main() {
|
||||
let _recovery_witness: () = 0; //~ ERROR mismatched types
|
||||
}
|
155
src/test/ui/parser/recover-const-async-fn-ptr.stderr
Normal file
155
src/test/ui/parser/recover-const-async-fn-ptr.stderr
Normal file
@ -0,0 +1,155 @@
|
||||
error: an `fn` pointer type cannot be `const`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:3:11
|
||||
|
|
||||
LL | type T0 = const fn();
|
||||
| -----^^^^^
|
||||
| |
|
||||
| `const` because of this
|
||||
| help: remove the `const` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `const`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:4:11
|
||||
|
|
||||
LL | type T1 = const extern "C" fn();
|
||||
| -----^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `const` because of this
|
||||
| help: remove the `const` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `const`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:5:11
|
||||
|
|
||||
LL | type T2 = const unsafe extern fn();
|
||||
| -----^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `const` because of this
|
||||
| help: remove the `const` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:6:11
|
||||
|
|
||||
LL | type T3 = async fn();
|
||||
| -----^^^^^
|
||||
| |
|
||||
| `async` because of this
|
||||
| help: remove the `async` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:7:11
|
||||
|
|
||||
LL | type T4 = async extern fn();
|
||||
| -----^^^^^^^^^^^^
|
||||
| |
|
||||
| `async` because of this
|
||||
| help: remove the `async` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:8:11
|
||||
|
|
||||
LL | type T5 = async unsafe extern "C" fn();
|
||||
| -----^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `async` because of this
|
||||
| help: remove the `async` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `const`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:9:11
|
||||
|
|
||||
LL | type T6 = const async unsafe extern "C" fn();
|
||||
| -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `const` because of this
|
||||
| help: remove the `const` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:9:11
|
||||
|
|
||||
LL | type T6 = const async unsafe extern "C" fn();
|
||||
| ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `async` because of this
|
||||
| help: remove the `async` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `const`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:13:12
|
||||
|
|
||||
LL | type FT0 = for<'a> const fn();
|
||||
| ^^^^^^^^-----^^^^^
|
||||
| |
|
||||
| `const` because of this
|
||||
| help: remove the `const` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `const`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:14:12
|
||||
|
|
||||
LL | type FT1 = for<'a> const extern "C" fn();
|
||||
| ^^^^^^^^-----^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `const` because of this
|
||||
| help: remove the `const` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `const`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:15:12
|
||||
|
|
||||
LL | type FT2 = for<'a> const unsafe extern fn();
|
||||
| ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `const` because of this
|
||||
| help: remove the `const` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:16:12
|
||||
|
|
||||
LL | type FT3 = for<'a> async fn();
|
||||
| ^^^^^^^^-----^^^^^
|
||||
| |
|
||||
| `async` because of this
|
||||
| help: remove the `async` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:17:12
|
||||
|
|
||||
LL | type FT4 = for<'a> async extern fn();
|
||||
| ^^^^^^^^-----^^^^^^^^^^^^
|
||||
| |
|
||||
| `async` because of this
|
||||
| help: remove the `async` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:18:12
|
||||
|
|
||||
LL | type FT5 = for<'a> async unsafe extern "C" fn();
|
||||
| ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `async` because of this
|
||||
| help: remove the `async` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `const`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:19:12
|
||||
|
|
||||
LL | type FT6 = for<'a> const async unsafe extern "C" fn();
|
||||
| ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `const` because of this
|
||||
| help: remove the `const` qualifier
|
||||
|
||||
error: an `fn` pointer type cannot be `async`
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:19:12
|
||||
|
|
||||
LL | type FT6 = for<'a> const async unsafe extern "C" fn();
|
||||
| ^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| `async` because of this
|
||||
| help: remove the `async` qualifier
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/recover-const-async-fn-ptr.rs:24:33
|
||||
|
|
||||
LL | let _recovery_witness: () = 0;
|
||||
| -- ^ expected `()`, found integer
|
||||
| |
|
||||
| expected due to this
|
||||
|
||||
error: aborting due to 17 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Reference in New Issue
Block a user