parse: recover on const fn()
/ async fn()
.
This commit is contained in:
parent
a5fb9ae5b2
commit
af1146bd23
@ -1494,7 +1494,7 @@ impl<'a> Parser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Is the current token the start of an `FnHeader` / not a valid parse?
|
/// 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.
|
// We use an over-approximation here.
|
||||||
// `const const`, `fn const` won't parse, but we're not stepping over other syntax either.
|
// `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];
|
const QUALS: [Symbol; 4] = [kw::Const, kw::Async, kw::Unsafe, kw::Extern];
|
||||||
@ -1521,7 +1521,7 @@ impl<'a> Parser<'a> {
|
|||||||
/// FnQual = "const"? "async"? "unsafe"? Extern? ;
|
/// FnQual = "const"? "async"? "unsafe"? Extern? ;
|
||||||
/// FnFrontMatter = FnQual? "fn" ;
|
/// 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 constness = self.parse_constness();
|
||||||
let asyncness = self.parse_asyncness();
|
let asyncness = self.parse_asyncness();
|
||||||
let unsafety = self.parse_unsafety();
|
let unsafety = self.parse_unsafety();
|
||||||
|
@ -127,16 +127,16 @@ impl<'a> Parser<'a> {
|
|||||||
} else if self.eat_keyword(kw::Underscore) {
|
} else if self.eat_keyword(kw::Underscore) {
|
||||||
// A type to be inferred `_`
|
// A type to be inferred `_`
|
||||||
TyKind::Infer
|
TyKind::Infer
|
||||||
} else if self.token_is_bare_fn_keyword() {
|
} else if self.check_fn_front_matter() {
|
||||||
// Function pointer type
|
// 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) {
|
} else if self.check_keyword(kw::For) {
|
||||||
// Function pointer type or bound list (trait object type) starting with a poly-trait.
|
// 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> [unsafe] [extern "ABI"] fn (&'lt S) -> T`
|
||||||
// `for<'lt> Trait1<'lt> + Trait2 + 'a`
|
// `for<'lt> Trait1<'lt> + Trait2 + 'a`
|
||||||
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
|
let lifetime_defs = self.parse_late_bound_lifetime_defs()?;
|
||||||
if self.token_is_bare_fn_keyword() {
|
if self.check_fn_front_matter() {
|
||||||
self.parse_ty_bare_fn(lifetime_defs)?
|
self.parse_ty_bare_fn(lo, lifetime_defs)?
|
||||||
} else {
|
} else {
|
||||||
let path = self.parse_path(PathStyle::Type)?;
|
let path = self.parse_path(PathStyle::Type)?;
|
||||||
let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
|
let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus();
|
||||||
@ -291,13 +291,6 @@ impl<'a> Parser<'a> {
|
|||||||
Ok(TyKind::Typeof(expr))
|
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`).
|
/// Parses a function pointer type (`TyKind::BareFn`).
|
||||||
/// ```
|
/// ```
|
||||||
/// [unsafe] [extern "ABI"] fn (S) -> T
|
/// [unsafe] [extern "ABI"] fn (S) -> T
|
||||||
@ -306,12 +299,31 @@ impl<'a> Parser<'a> {
|
|||||||
/// | | | Return type
|
/// | | | Return type
|
||||||
/// Function Style ABI Parameter types
|
/// Function Style ABI Parameter types
|
||||||
/// ```
|
/// ```
|
||||||
fn parse_ty_bare_fn(&mut self, generic_params: Vec<GenericParam>) -> PResult<'a, TyKind> {
|
/// We actually parse `FnHeader FnDecl`, but we error on `const` and `async` qualifiers.
|
||||||
let unsafety = self.parse_unsafety();
|
fn parse_ty_bare_fn(&mut self, lo: Span, params: Vec<GenericParam>) -> PResult<'a, TyKind> {
|
||||||
let ext = self.parse_extern()?;
|
let ast::FnHeader { ext, unsafety, constness, asyncness } = self.parse_fn_front_matter()?;
|
||||||
self.expect_keyword(kw::Fn)?;
|
|
||||||
let decl = self.parse_fn_decl(|_| false, AllowPlus::No)?;
|
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.
|
/// 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() {}
|
fn main() {}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
error: expected `fn`, found `::`
|
error: expected type, found keyword `extern`
|
||||||
--> $DIR/keyword-extern-as-identifier-type.rs:1:16
|
--> $DIR/keyword-extern-as-identifier-type.rs:1:10
|
||||||
|
|
|
|
||||||
LL | type A = extern::foo::bar;
|
LL | type A = extern::foo::bar;
|
||||||
| ^^ expected `fn`
|
| ^^^^^^ expected type
|
||||||
|
|
||||||
error: aborting due to previous error
|
error: aborting due to previous error
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `;`
|
|||||||
LL | impl W <s(f;Y(;]
|
LL | impl W <s(f;Y(;]
|
||||||
| ^ expected one of 7 possible tokens
|
| ^ 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
|
--> $DIR/issue-63116.rs:3:15
|
||||||
|
|
|
|
||||||
LL | impl W <s(f;Y(;]
|
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…
x
Reference in New Issue
Block a user