diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 1f221b4bf78c2..f6e0b08b14046 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -299,10 +299,12 @@ parse_float_literal_unsupported_base = {$base} float literal is not supported
parse_fn_pointer_cannot_be_async = an `fn` pointer type cannot be `async`
.label = `async` because of this
.suggestion = remove the `async` qualifier
+ .note = allowed qualifiers are: `unsafe` and `extern`
parse_fn_pointer_cannot_be_const = an `fn` pointer type cannot be `const`
.label = `const` because of this
.suggestion = remove the `const` qualifier
+ .note = allowed qualifiers are: `unsafe` and `extern`
parse_fn_ptr_with_generics = function pointer types may not have generic parameters
.suggestion = consider moving the lifetime {$arity ->
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 2dba568a258a2..0f0c5434800a5 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2938,22 +2938,22 @@ pub(crate) struct DynAfterMut {
#[derive(Diagnostic)]
#[diag(parse_fn_pointer_cannot_be_const)]
+#[note]
pub(crate) struct FnPointerCannotBeConst {
#[primary_span]
- pub span: Span,
#[label]
- pub qualifier: Span,
+ pub span: Span,
#[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")]
pub suggestion: Span,
}
#[derive(Diagnostic)]
#[diag(parse_fn_pointer_cannot_be_async)]
+#[note]
pub(crate) struct FnPointerCannotBeAsync {
#[primary_span]
- pub span: Span,
#[label]
- pub qualifier: Span,
+ pub span: Span,
#[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")]
pub suggestion: Span,
}
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index a325c2a57ab8e..658ed4bd41c40 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -23,7 +23,7 @@ use super::{
AttrWrapper, ExpKeywordPair, ExpTokenPair, FollowedByType, ForceCollect, Parser, PathStyle,
Recovered, Trailing, UsePreAttrPos,
};
-use crate::errors::{self, MacroExpandsToAdtField};
+use crate::errors::{self, FnPointerCannotBeAsync, FnPointerCannotBeConst, MacroExpandsToAdtField};
use crate::{exp, fluent_generated as fluent};
impl<'a> Parser<'a> {
@@ -2402,7 +2402,7 @@ impl<'a> Parser<'a> {
case: Case,
) -> PResult<'a, (Ident, FnSig, Generics, Option
>, Option
>)> {
let fn_span = self.token.span;
- let header = self.parse_fn_front_matter(vis, case)?; // `const ... fn`
+ let header = self.parse_fn_front_matter(vis, case, FrontMatterParsingMode::Function)?; // `const ... fn`
let ident = self.parse_ident()?; // `foo`
let mut generics = self.parse_generics()?; // `<'a, T, ...>`
let decl = match self.parse_fn_decl(
@@ -2658,16 +2658,37 @@ impl<'a> Parser<'a> {
///
/// `vis` represents the visibility that was already parsed, if any. Use
/// `Visibility::Inherited` when no visibility is known.
+ ///
+ /// If `parsing_mode` is `FrontMatterParsingMode::FunctionPtrType`, we error on `const` and `async` qualifiers,
+ /// which are not allowed in function pointer types.
pub(super) fn parse_fn_front_matter(
&mut self,
orig_vis: &Visibility,
case: Case,
+ parsing_mode: FrontMatterParsingMode,
) -> PResult<'a, FnHeader> {
let sp_start = self.token.span;
let constness = self.parse_constness(case);
+ if parsing_mode == FrontMatterParsingMode::FunctionPtrType
+ && let Const::Yes(const_span) = constness
+ {
+ self.dcx().emit_err(FnPointerCannotBeConst {
+ span: const_span,
+ suggestion: const_span.until(self.token.span),
+ });
+ }
let async_start_sp = self.token.span;
let coroutine_kind = self.parse_coroutine_kind(case);
+ if parsing_mode == FrontMatterParsingMode::FunctionPtrType
+ && let Some(ast::CoroutineKind::Async { span: async_span, .. }) = coroutine_kind
+ {
+ self.dcx().emit_err(FnPointerCannotBeAsync {
+ span: async_span,
+ suggestion: async_span.until(self.token.span),
+ });
+ }
+ // FIXME(gen_blocks): emit a similar error for `gen fn()`
let unsafe_start_sp = self.token.span;
let safety = self.parse_safety(case);
@@ -2703,6 +2724,11 @@ impl<'a> Parser<'a> {
enum WrongKw {
Duplicated(Span),
Misplaced(Span),
+ /// `MisplacedDisallowedQualifier` is only used instead of `Misplaced`,
+ /// when the misplaced keyword is disallowed by the current `FrontMatterParsingMode`.
+ /// In this case, we avoid generating the suggestion to swap around the keywords,
+ /// as we already generated a suggestion to remove the keyword earlier.
+ MisplacedDisallowedQualifier,
}
// We may be able to recover
@@ -2716,7 +2742,21 @@ impl<'a> Parser<'a> {
Const::Yes(sp) => Some(WrongKw::Duplicated(sp)),
Const::No => {
recover_constness = Const::Yes(self.token.span);
- Some(WrongKw::Misplaced(async_start_sp))
+ match parsing_mode {
+ FrontMatterParsingMode::Function => {
+ Some(WrongKw::Misplaced(async_start_sp))
+ }
+ FrontMatterParsingMode::FunctionPtrType => {
+ self.dcx().emit_err(FnPointerCannotBeConst {
+ span: self.token.span,
+ suggestion: self
+ .token
+ .span
+ .with_lo(self.prev_token.span.hi()),
+ });
+ Some(WrongKw::MisplacedDisallowedQualifier)
+ }
+ }
}
}
} else if self.check_keyword(exp!(Async)) {
@@ -2742,7 +2782,21 @@ impl<'a> Parser<'a> {
closure_id: DUMMY_NODE_ID,
return_impl_trait_id: DUMMY_NODE_ID,
});
- Some(WrongKw::Misplaced(unsafe_start_sp))
+ match parsing_mode {
+ FrontMatterParsingMode::Function => {
+ Some(WrongKw::Misplaced(async_start_sp))
+ }
+ FrontMatterParsingMode::FunctionPtrType => {
+ self.dcx().emit_err(FnPointerCannotBeAsync {
+ span: self.token.span,
+ suggestion: self
+ .token
+ .span
+ .with_lo(self.prev_token.span.hi()),
+ });
+ Some(WrongKw::MisplacedDisallowedQualifier)
+ }
+ }
}
}
} else if self.check_keyword(exp!(Unsafe)) {
@@ -2840,14 +2894,20 @@ impl<'a> Parser<'a> {
// FIXME(gen_blocks): add keyword recovery logic for genness
- if wrong_kw.is_some()
+ if let Some(wrong_kw) = wrong_kw
&& self.may_recover()
&& self.look_ahead(1, |tok| tok.is_keyword_case(kw::Fn, case))
{
// Advance past the misplaced keyword and `fn`
self.bump();
self.bump();
- err.emit();
+ // When we recover from a `MisplacedDisallowedQualifier`, we already emitted an error for the disallowed qualifier
+ // So we don't emit another error that the qualifier is unexpected.
+ if matches!(wrong_kw, WrongKw::MisplacedDisallowedQualifier) {
+ err.cancel();
+ } else {
+ err.emit();
+ }
return Ok(FnHeader {
constness: recover_constness,
safety: recover_safety,
@@ -3194,3 +3254,12 @@ enum IsMacroRulesItem {
Yes { has_bang: bool },
No,
}
+
+#[derive(Copy, Clone, PartialEq, Eq)]
+pub(super) enum FrontMatterParsingMode {
+ /// Parse the front matter of a function declaration
+ Function,
+ /// Parse the front matter of a function pointet type.
+ /// For function pointer types, the `const` and `async` keywords are not permitted.
+ FunctionPtrType,
+}
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 9ddfc179e9b84..620a34044d12e 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -15,10 +15,11 @@ use thin_vec::{ThinVec, thin_vec};
use super::{Parser, PathStyle, SeqSep, TokenType, Trailing};
use crate::errors::{
self, DynAfterMut, ExpectedFnPathFoundFnKeyword, ExpectedMutOrConstInRawPointerType,
- FnPointerCannotBeAsync, FnPointerCannotBeConst, FnPtrWithGenerics, FnPtrWithGenericsSugg,
- HelpUseLatestEdition, InvalidDynKeyword, LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime,
- NestedCVariadicType, ReturnTypesUseThinArrow,
+ FnPtrWithGenerics, FnPtrWithGenericsSugg, HelpUseLatestEdition, InvalidDynKeyword,
+ LifetimeAfterMut, NeedPlusAfterTraitObjectLifetime, NestedCVariadicType,
+ ReturnTypesUseThinArrow,
};
+use crate::parser::item::FrontMatterParsingMode;
use crate::{exp, maybe_recover_from_interpolated_ty_qpath};
/// Signals whether parsing a type should allow `+`.
@@ -669,62 +670,16 @@ impl<'a> Parser<'a> {
tokens: None,
};
let span_start = self.token.span;
- let ast::FnHeader { ext, safety, constness, coroutine_kind } =
- self.parse_fn_front_matter(&inherited_vis, Case::Sensitive)?;
- let fn_start_lo = self.prev_token.span.lo();
+ let ast::FnHeader { ext, safety, .. } = self.parse_fn_front_matter(
+ &inherited_vis,
+ Case::Sensitive,
+ FrontMatterParsingMode::FunctionPtrType,
+ )?;
if self.may_recover() && self.token == TokenKind::Lt {
self.recover_fn_ptr_with_generics(lo, &mut params, param_insertion_point)?;
}
let decl = self.parse_fn_decl(|_| false, AllowPlus::No, recover_return_sign)?;
- let whole_span = lo.to(self.prev_token.span);
-
- // Order/parsing of "front matter" follows:
- // ` fn()`
- // ^ ^ ^ ^ ^
- // | | | | fn_start_lo
- // | | | ext_sp.lo
- // | | safety_sp.lo
- // | coroutine_sp.lo
- // const_sp.lo
- if let ast::Const::Yes(const_span) = constness {
- let next_token_lo = if let Some(
- ast::CoroutineKind::Async { span, .. }
- | ast::CoroutineKind::Gen { span, .. }
- | ast::CoroutineKind::AsyncGen { span, .. },
- ) = coroutine_kind
- {
- span.lo()
- } else if let ast::Safety::Unsafe(span) | ast::Safety::Safe(span) = safety {
- span.lo()
- } else if let ast::Extern::Implicit(span) | ast::Extern::Explicit(_, span) = ext {
- span.lo()
- } else {
- fn_start_lo
- };
- let sugg_span = const_span.with_hi(next_token_lo);
- self.dcx().emit_err(FnPointerCannotBeConst {
- span: whole_span,
- qualifier: const_span,
- suggestion: sugg_span,
- });
- }
- if let Some(ast::CoroutineKind::Async { span: async_span, .. }) = coroutine_kind {
- let next_token_lo = if let ast::Safety::Unsafe(span) | ast::Safety::Safe(span) = safety
- {
- span.lo()
- } else if let ast::Extern::Implicit(span) | ast::Extern::Explicit(_, span) = ext {
- span.lo()
- } else {
- fn_start_lo
- };
- let sugg_span = async_span.with_hi(next_token_lo);
- self.dcx().emit_err(FnPointerCannotBeAsync {
- span: whole_span,
- qualifier: async_span,
- suggestion: sugg_span,
- });
- }
- // FIXME(gen_blocks): emit a similar error for `gen fn()`
+
let decl_span = span_start.to(self.prev_token.span);
Ok(TyKind::BareFn(P(BareFnTy { ext, safety, generic_params: params, decl, decl_span })))
}
diff --git a/tests/ui/parser/bad-fn-ptr-qualifier.fixed b/tests/ui/parser/bad-fn-ptr-qualifier.fixed
index 8a97a2f09ccab..e9b87a72aab41 100644
--- a/tests/ui/parser/bad-fn-ptr-qualifier.fixed
+++ b/tests/ui/parser/bad-fn-ptr-qualifier.fixed
@@ -23,4 +23,12 @@ pub type FTT6 = for<'a> unsafe extern "C" fn();
//~^ ERROR an `fn` pointer type cannot be `const`
//~| ERROR an `fn` pointer type cannot be `async`
+// Tests with qualifiers in the wrong order
+pub type W1 = unsafe fn();
+//~^ ERROR an `fn` pointer type cannot be `const`
+pub type W2 = unsafe fn();
+//~^ ERROR an `fn` pointer type cannot be `async`
+pub type W3 = for<'a> unsafe fn();
+//~^ ERROR an `fn` pointer type cannot be `const`
+
fn main() {}
diff --git a/tests/ui/parser/bad-fn-ptr-qualifier.rs b/tests/ui/parser/bad-fn-ptr-qualifier.rs
index f2611c93b1763..f110375509c66 100644
--- a/tests/ui/parser/bad-fn-ptr-qualifier.rs
+++ b/tests/ui/parser/bad-fn-ptr-qualifier.rs
@@ -23,4 +23,12 @@ pub type FTT6 = for<'a> const async unsafe extern "C" fn();
//~^ ERROR an `fn` pointer type cannot be `const`
//~| ERROR an `fn` pointer type cannot be `async`
+// Tests with qualifiers in the wrong order
+pub type W1 = unsafe const fn();
+//~^ ERROR an `fn` pointer type cannot be `const`
+pub type W2 = unsafe async fn();
+//~^ ERROR an `fn` pointer type cannot be `async`
+pub type W3 = for<'a> unsafe const fn();
+//~^ ERROR an `fn` pointer type cannot be `const`
+
fn main() {}
diff --git a/tests/ui/parser/bad-fn-ptr-qualifier.stderr b/tests/ui/parser/bad-fn-ptr-qualifier.stderr
index b9d2625d9f4be..f3fbbf67159d1 100644
--- a/tests/ui/parser/bad-fn-ptr-qualifier.stderr
+++ b/tests/ui/parser/bad-fn-ptr-qualifier.stderr
@@ -2,10 +2,9 @@ error: an `fn` pointer type cannot be `const`
--> $DIR/bad-fn-ptr-qualifier.rs:5:15
|
LL | pub type T0 = const fn();
- | -----^^^^^
- | |
- | `const` because of this
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - pub type T0 = const fn();
@@ -16,10 +15,9 @@ error: an `fn` pointer type cannot be `const`
--> $DIR/bad-fn-ptr-qualifier.rs:6:15
|
LL | pub type T1 = const extern "C" fn();
- | -----^^^^^^^^^^^^^^^^
- | |
- | `const` because of this
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - pub type T1 = const extern "C" fn();
@@ -30,10 +28,9 @@ error: an `fn` pointer type cannot be `const`
--> $DIR/bad-fn-ptr-qualifier.rs:7:15
|
LL | pub type T2 = const unsafe extern "C" fn();
- | -----^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `const` because of this
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - pub type T2 = const unsafe extern "C" fn();
@@ -44,10 +41,9 @@ error: an `fn` pointer type cannot be `async`
--> $DIR/bad-fn-ptr-qualifier.rs:8:15
|
LL | pub type T3 = async fn();
- | -----^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - pub type T3 = async fn();
@@ -58,10 +54,9 @@ error: an `fn` pointer type cannot be `async`
--> $DIR/bad-fn-ptr-qualifier.rs:9:15
|
LL | pub type T4 = async extern "C" fn();
- | -----^^^^^^^^^^^^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - pub type T4 = async extern "C" fn();
@@ -72,10 +67,9 @@ error: an `fn` pointer type cannot be `async`
--> $DIR/bad-fn-ptr-qualifier.rs:10:15
|
LL | pub type T5 = async unsafe extern "C" fn();
- | -----^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - pub type T5 = async unsafe extern "C" fn();
@@ -86,10 +80,9 @@ error: an `fn` pointer type cannot be `const`
--> $DIR/bad-fn-ptr-qualifier.rs:11:15
|
LL | pub type T6 = const async unsafe extern "C" fn();
- | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `const` because of this
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - pub type T6 = const async unsafe extern "C" fn();
@@ -97,13 +90,12 @@ LL + pub type T6 = async unsafe extern "C" fn();
|
error: an `fn` pointer type cannot be `async`
- --> $DIR/bad-fn-ptr-qualifier.rs:11:15
+ --> $DIR/bad-fn-ptr-qualifier.rs:11:21
|
LL | pub type T6 = const async unsafe extern "C" fn();
- | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - pub type T6 = const async unsafe extern "C" fn();
@@ -111,13 +103,12 @@ LL + pub type T6 = const unsafe extern "C" fn();
|
error: an `fn` pointer type cannot be `const`
- --> $DIR/bad-fn-ptr-qualifier.rs:15:17
+ --> $DIR/bad-fn-ptr-qualifier.rs:15:25
|
LL | pub type FTT0 = for<'a> const fn();
- | ^^^^^^^^-----^^^^^
- | |
- | `const` because of this
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - pub type FTT0 = for<'a> const fn();
@@ -125,13 +116,12 @@ LL + pub type FTT0 = for<'a> fn();
|
error: an `fn` pointer type cannot be `const`
- --> $DIR/bad-fn-ptr-qualifier.rs:16:17
+ --> $DIR/bad-fn-ptr-qualifier.rs:16:25
|
LL | pub type FTT1 = for<'a> const extern "C" fn();
- | ^^^^^^^^-----^^^^^^^^^^^^^^^^
- | |
- | `const` because of this
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - pub type FTT1 = for<'a> const extern "C" fn();
@@ -139,13 +129,12 @@ LL + pub type FTT1 = for<'a> extern "C" fn();
|
error: an `fn` pointer type cannot be `const`
- --> $DIR/bad-fn-ptr-qualifier.rs:17:17
+ --> $DIR/bad-fn-ptr-qualifier.rs:17:25
|
LL | pub type FTT2 = for<'a> const unsafe extern "C" fn();
- | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `const` because of this
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - pub type FTT2 = for<'a> const unsafe extern "C" fn();
@@ -153,13 +142,12 @@ LL + pub type FTT2 = for<'a> unsafe extern "C" fn();
|
error: an `fn` pointer type cannot be `async`
- --> $DIR/bad-fn-ptr-qualifier.rs:18:17
+ --> $DIR/bad-fn-ptr-qualifier.rs:18:25
|
LL | pub type FTT3 = for<'a> async fn();
- | ^^^^^^^^-----^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - pub type FTT3 = for<'a> async fn();
@@ -167,13 +155,12 @@ LL + pub type FTT3 = for<'a> fn();
|
error: an `fn` pointer type cannot be `async`
- --> $DIR/bad-fn-ptr-qualifier.rs:19:17
+ --> $DIR/bad-fn-ptr-qualifier.rs:19:25
|
LL | pub type FTT4 = for<'a> async extern "C" fn();
- | ^^^^^^^^-----^^^^^^^^^^^^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - pub type FTT4 = for<'a> async extern "C" fn();
@@ -181,13 +168,12 @@ LL + pub type FTT4 = for<'a> extern "C" fn();
|
error: an `fn` pointer type cannot be `async`
- --> $DIR/bad-fn-ptr-qualifier.rs:20:17
+ --> $DIR/bad-fn-ptr-qualifier.rs:20:25
|
LL | pub type FTT5 = for<'a> async unsafe extern "C" fn();
- | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - pub type FTT5 = for<'a> async unsafe extern "C" fn();
@@ -195,13 +181,12 @@ LL + pub type FTT5 = for<'a> unsafe extern "C" fn();
|
error: an `fn` pointer type cannot be `const`
- --> $DIR/bad-fn-ptr-qualifier.rs:22:17
+ --> $DIR/bad-fn-ptr-qualifier.rs:22:25
|
LL | pub type FTT6 = for<'a> const async unsafe extern "C" fn();
- | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `const` because of this
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - pub type FTT6 = for<'a> const async unsafe extern "C" fn();
@@ -209,18 +194,56 @@ LL + pub type FTT6 = for<'a> async unsafe extern "C" fn();
|
error: an `fn` pointer type cannot be `async`
- --> $DIR/bad-fn-ptr-qualifier.rs:22:17
+ --> $DIR/bad-fn-ptr-qualifier.rs:22:31
|
LL | pub type FTT6 = for<'a> const async unsafe extern "C" fn();
- | ^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - pub type FTT6 = for<'a> const async unsafe extern "C" fn();
LL + pub type FTT6 = for<'a> const unsafe extern "C" fn();
|
-error: aborting due to 16 previous errors
+error: an `fn` pointer type cannot be `const`
+ --> $DIR/bad-fn-ptr-qualifier.rs:27:22
+ |
+LL | pub type W1 = unsafe const fn();
+ | ^^^^^ `const` because of this
+ |
+ = note: allowed qualifiers are: `unsafe` and `extern`
+help: remove the `const` qualifier
+ |
+LL - pub type W1 = unsafe const fn();
+LL + pub type W1 = unsafe fn();
+ |
+
+error: an `fn` pointer type cannot be `async`
+ --> $DIR/bad-fn-ptr-qualifier.rs:29:22
+ |
+LL | pub type W2 = unsafe async fn();
+ | ^^^^^ `async` because of this
+ |
+ = note: allowed qualifiers are: `unsafe` and `extern`
+help: remove the `async` qualifier
+ |
+LL - pub type W2 = unsafe async fn();
+LL + pub type W2 = unsafe fn();
+ |
+
+error: an `fn` pointer type cannot be `const`
+ --> $DIR/bad-fn-ptr-qualifier.rs:31:30
+ |
+LL | pub type W3 = for<'a> unsafe const fn();
+ | ^^^^^ `const` because of this
+ |
+ = note: allowed qualifiers are: `unsafe` and `extern`
+help: remove the `const` qualifier
+ |
+LL - pub type W3 = for<'a> unsafe const fn();
+LL + pub type W3 = for<'a> unsafe fn();
+ |
+
+error: aborting due to 19 previous errors
diff --git a/tests/ui/parser/recover/recover-const-async-fn-ptr.rs b/tests/ui/parser/recover/recover-const-async-fn-ptr.rs
index 45d753495999b..a74b618c282cd 100644
--- a/tests/ui/parser/recover/recover-const-async-fn-ptr.rs
+++ b/tests/ui/parser/recover/recover-const-async-fn-ptr.rs
@@ -20,6 +20,14 @@ 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`
+// Tests with qualifiers in the wrong order
+type W1 = unsafe const fn();
+//~^ ERROR an `fn` pointer type cannot be `const`
+type W2 = unsafe async fn();
+//~^ ERROR an `fn` pointer type cannot be `async`
+type W3 = for<'a> unsafe const fn();
+//~^ ERROR an `fn` pointer type cannot be `const`
+
fn main() {
let _recovery_witness: () = 0; //~ ERROR mismatched types
}
diff --git a/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr b/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr
index 4e5927914ccb5..3700bee6e1544 100644
--- a/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr
+++ b/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr
@@ -2,10 +2,9 @@ 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
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - type T0 = const fn();
@@ -16,10 +15,9 @@ 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
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - type T1 = const extern "C" fn();
@@ -30,10 +28,9 @@ error: an `fn` pointer type cannot be `const`
--> $DIR/recover-const-async-fn-ptr.rs:5:11
|
LL | type T2 = const unsafe extern "C" fn();
- | -----^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `const` because of this
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - type T2 = const unsafe extern "C" fn();
@@ -44,10 +41,9 @@ 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
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - type T3 = async fn();
@@ -58,10 +54,9 @@ error: an `fn` pointer type cannot be `async`
--> $DIR/recover-const-async-fn-ptr.rs:7:11
|
LL | type T4 = async extern "C" fn();
- | -----^^^^^^^^^^^^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - type T4 = async extern "C" fn();
@@ -72,10 +67,9 @@ 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
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - type T5 = async unsafe extern "C" fn();
@@ -86,10 +80,9 @@ 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
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - type T6 = const async unsafe extern "C" fn();
@@ -97,13 +90,12 @@ LL + type T6 = async unsafe extern "C" fn();
|
error: an `fn` pointer type cannot be `async`
- --> $DIR/recover-const-async-fn-ptr.rs:9:11
+ --> $DIR/recover-const-async-fn-ptr.rs:9:17
|
LL | type T6 = const async unsafe extern "C" fn();
- | ^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - type T6 = const async unsafe extern "C" fn();
@@ -111,13 +103,12 @@ LL + type T6 = const unsafe extern "C" fn();
|
error: an `fn` pointer type cannot be `const`
- --> $DIR/recover-const-async-fn-ptr.rs:13:12
+ --> $DIR/recover-const-async-fn-ptr.rs:13:20
|
LL | type FT0 = for<'a> const fn();
- | ^^^^^^^^-----^^^^^
- | |
- | `const` because of this
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - type FT0 = for<'a> const fn();
@@ -125,13 +116,12 @@ LL + type FT0 = for<'a> fn();
|
error: an `fn` pointer type cannot be `const`
- --> $DIR/recover-const-async-fn-ptr.rs:14:12
+ --> $DIR/recover-const-async-fn-ptr.rs:14:20
|
LL | type FT1 = for<'a> const extern "C" fn();
- | ^^^^^^^^-----^^^^^^^^^^^^^^^^
- | |
- | `const` because of this
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - type FT1 = for<'a> const extern "C" fn();
@@ -139,13 +129,12 @@ LL + type FT1 = for<'a> extern "C" fn();
|
error: an `fn` pointer type cannot be `const`
- --> $DIR/recover-const-async-fn-ptr.rs:15:12
+ --> $DIR/recover-const-async-fn-ptr.rs:15:20
|
LL | type FT2 = for<'a> const unsafe extern "C" fn();
- | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `const` because of this
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - type FT2 = for<'a> const unsafe extern "C" fn();
@@ -153,13 +142,12 @@ LL + type FT2 = for<'a> unsafe extern "C" fn();
|
error: an `fn` pointer type cannot be `async`
- --> $DIR/recover-const-async-fn-ptr.rs:16:12
+ --> $DIR/recover-const-async-fn-ptr.rs:16:20
|
LL | type FT3 = for<'a> async fn();
- | ^^^^^^^^-----^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - type FT3 = for<'a> async fn();
@@ -167,13 +155,12 @@ LL + type FT3 = for<'a> fn();
|
error: an `fn` pointer type cannot be `async`
- --> $DIR/recover-const-async-fn-ptr.rs:17:12
+ --> $DIR/recover-const-async-fn-ptr.rs:17:20
|
LL | type FT4 = for<'a> async extern "C" fn();
- | ^^^^^^^^-----^^^^^^^^^^^^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - type FT4 = for<'a> async extern "C" fn();
@@ -181,13 +168,12 @@ LL + type FT4 = for<'a> extern "C" fn();
|
error: an `fn` pointer type cannot be `async`
- --> $DIR/recover-const-async-fn-ptr.rs:18:12
+ --> $DIR/recover-const-async-fn-ptr.rs:18:20
|
LL | type FT5 = for<'a> async unsafe extern "C" fn();
- | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - type FT5 = for<'a> async unsafe extern "C" fn();
@@ -195,13 +181,12 @@ LL + type FT5 = for<'a> unsafe extern "C" fn();
|
error: an `fn` pointer type cannot be `const`
- --> $DIR/recover-const-async-fn-ptr.rs:19:12
+ --> $DIR/recover-const-async-fn-ptr.rs:19:20
|
LL | type FT6 = for<'a> const async unsafe extern "C" fn();
- | ^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `const` because of this
+ | ^^^^^ `const` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `const` qualifier
|
LL - type FT6 = for<'a> const async unsafe extern "C" fn();
@@ -209,27 +194,65 @@ LL + type FT6 = for<'a> async unsafe extern "C" fn();
|
error: an `fn` pointer type cannot be `async`
- --> $DIR/recover-const-async-fn-ptr.rs:19:12
+ --> $DIR/recover-const-async-fn-ptr.rs:19:26
|
LL | type FT6 = for<'a> const async unsafe extern "C" fn();
- | ^^^^^^^^^^^^^^-----^^^^^^^^^^^^^^^^^^^^^^^
- | |
- | `async` because of this
+ | ^^^^^ `async` because of this
|
+ = note: allowed qualifiers are: `unsafe` and `extern`
help: remove the `async` qualifier
|
LL - type FT6 = for<'a> const async unsafe extern "C" fn();
LL + type FT6 = for<'a> const unsafe extern "C" fn();
|
+error: an `fn` pointer type cannot be `const`
+ --> $DIR/recover-const-async-fn-ptr.rs:24:18
+ |
+LL | type W1 = unsafe const fn();
+ | ^^^^^ `const` because of this
+ |
+ = note: allowed qualifiers are: `unsafe` and `extern`
+help: remove the `const` qualifier
+ |
+LL - type W1 = unsafe const fn();
+LL + type W1 = unsafe fn();
+ |
+
+error: an `fn` pointer type cannot be `async`
+ --> $DIR/recover-const-async-fn-ptr.rs:26:18
+ |
+LL | type W2 = unsafe async fn();
+ | ^^^^^ `async` because of this
+ |
+ = note: allowed qualifiers are: `unsafe` and `extern`
+help: remove the `async` qualifier
+ |
+LL - type W2 = unsafe async fn();
+LL + type W2 = unsafe fn();
+ |
+
+error: an `fn` pointer type cannot be `const`
+ --> $DIR/recover-const-async-fn-ptr.rs:28:26
+ |
+LL | type W3 = for<'a> unsafe const fn();
+ | ^^^^^ `const` because of this
+ |
+ = note: allowed qualifiers are: `unsafe` and `extern`
+help: remove the `const` qualifier
+ |
+LL - type W3 = for<'a> unsafe const fn();
+LL + type W3 = for<'a> unsafe fn();
+ |
+
error[E0308]: mismatched types
- --> $DIR/recover-const-async-fn-ptr.rs:24:33
+ --> $DIR/recover-const-async-fn-ptr.rs:32:33
|
LL | let _recovery_witness: () = 0;
| -- ^ expected `()`, found integer
| |
| expected due to this
-error: aborting due to 17 previous errors
+error: aborting due to 20 previous errors
For more information about this error, try `rustc --explain E0308`.