From 5082fd8b1ee31284be473fe4e8691677ff61c708 Mon Sep 17 00:00:00 2001 From: Tyrone Wu Date: Sun, 17 Nov 2024 21:02:05 +0000 Subject: [PATCH] Trim extra whitespace in fn ptr suggestion span Trim extra whitespace when suggesting removal of invalid qualifiers when parsing function pointer type. Fixes: #133083 Signed-off-by: Tyrone Wu --- compiler/rustc_parse/src/errors.rs | 6 ++- compiler/rustc_parse/src/parser/ty.rs | 50 +++++++++++++++++-- tests/ui/parser/bad-fn-ptr-qualifier.fixed | 28 +++++------ tests/ui/parser/bad-fn-ptr-qualifier.stderr | 32 ++++++------ .../recover/recover-const-async-fn-ptr.stderr | 32 ++++++------ 5 files changed, 96 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index f78d9dc2bfc28..3d07166274d5a 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2830,9 +2830,10 @@ pub(crate) struct DynAfterMut { pub(crate) struct FnPointerCannotBeConst { #[primary_span] pub span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] #[label] pub qualifier: Span, + #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] + pub suggestion: Span, } #[derive(Diagnostic)] @@ -2840,9 +2841,10 @@ pub(crate) struct FnPointerCannotBeConst { pub(crate) struct FnPointerCannotBeAsync { #[primary_span] pub span: Span, - #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] #[label] pub qualifier: Span, + #[suggestion(code = "", applicability = "maybe-incorrect", style = "verbose")] + pub suggestion: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 6497d19a173ca..dc5919b3630ce 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -609,16 +609,58 @@ impl<'a> Parser<'a> { 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(); 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); - if let ast::Const::Yes(span) = constness { - self.dcx().emit_err(FnPointerCannotBeConst { span: whole_span, qualifier: 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, .. }) = coroutine_kind { - self.dcx().emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: 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); diff --git a/tests/ui/parser/bad-fn-ptr-qualifier.fixed b/tests/ui/parser/bad-fn-ptr-qualifier.fixed index e2a2f9486b785..8a97a2f09ccab 100644 --- a/tests/ui/parser/bad-fn-ptr-qualifier.fixed +++ b/tests/ui/parser/bad-fn-ptr-qualifier.fixed @@ -2,24 +2,24 @@ //@ edition:2018 // Most of items are taken from ./recover-const-async-fn-ptr.rs but this is able to apply rustfix. -pub type T0 = fn(); //~ ERROR an `fn` pointer type cannot be `const` -pub type T1 = extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` -pub type T2 = unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` -pub type T3 = fn(); //~ ERROR an `fn` pointer type cannot be `async` -pub type T4 = extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` -pub type T5 = unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` -pub type T6 = unsafe extern "C" fn(); +pub type T0 = fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type T1 = extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type T2 = unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type T3 = fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type T4 = extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type T5 = unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type T6 = unsafe extern "C" fn(); //~^ ERROR an `fn` pointer type cannot be `const` //~| ERROR an `fn` pointer type cannot be `async` -pub type FTT0 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `const` -pub type FTT1 = for<'a> extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` -pub type FTT2 = for<'a> unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` -pub type FTT3 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `async` -pub type FTT4 = for<'a> extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` -pub type FTT5 = for<'a> unsafe extern "C" fn(); +pub type FTT0 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type FTT1 = for<'a> extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type FTT2 = for<'a> unsafe extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `const` +pub type FTT3 = for<'a> fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type FTT4 = for<'a> extern "C" fn(); //~ ERROR an `fn` pointer type cannot be `async` +pub type FTT5 = for<'a> unsafe extern "C" fn(); //~^ ERROR an `fn` pointer type cannot be `async` -pub type FTT6 = for<'a> unsafe extern "C" fn(); +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` diff --git a/tests/ui/parser/bad-fn-ptr-qualifier.stderr b/tests/ui/parser/bad-fn-ptr-qualifier.stderr index ddc8bac678cfb..b9d2625d9f4be 100644 --- a/tests/ui/parser/bad-fn-ptr-qualifier.stderr +++ b/tests/ui/parser/bad-fn-ptr-qualifier.stderr @@ -9,7 +9,7 @@ LL | pub type T0 = const fn(); help: remove the `const` qualifier | LL - pub type T0 = const fn(); -LL + pub type T0 = fn(); +LL + pub type T0 = fn(); | error: an `fn` pointer type cannot be `const` @@ -23,7 +23,7 @@ LL | pub type T1 = const extern "C" fn(); help: remove the `const` qualifier | LL - pub type T1 = const extern "C" fn(); -LL + pub type T1 = extern "C" fn(); +LL + pub type T1 = extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -37,7 +37,7 @@ LL | pub type T2 = const unsafe extern "C" fn(); help: remove the `const` qualifier | LL - pub type T2 = const unsafe extern "C" fn(); -LL + pub type T2 = unsafe extern "C" fn(); +LL + pub type T2 = unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -51,7 +51,7 @@ LL | pub type T3 = async fn(); help: remove the `async` qualifier | LL - pub type T3 = async fn(); -LL + pub type T3 = fn(); +LL + pub type T3 = fn(); | error: an `fn` pointer type cannot be `async` @@ -65,7 +65,7 @@ LL | pub type T4 = async extern "C" fn(); help: remove the `async` qualifier | LL - pub type T4 = async extern "C" fn(); -LL + pub type T4 = extern "C" fn(); +LL + pub type T4 = extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -79,7 +79,7 @@ LL | pub type T5 = async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - pub type T5 = async unsafe extern "C" fn(); -LL + pub type T5 = unsafe extern "C" fn(); +LL + pub type T5 = unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -93,7 +93,7 @@ LL | pub type T6 = const async unsafe extern "C" fn(); help: remove the `const` qualifier | LL - pub type T6 = const async unsafe extern "C" fn(); -LL + pub type T6 = async unsafe extern "C" fn(); +LL + pub type T6 = async unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -107,7 +107,7 @@ LL | pub type T6 = const async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - pub type T6 = const async unsafe extern "C" fn(); -LL + pub type T6 = const unsafe extern "C" fn(); +LL + pub type T6 = const unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -121,7 +121,7 @@ LL | pub type FTT0 = for<'a> const fn(); help: remove the `const` qualifier | LL - pub type FTT0 = for<'a> const fn(); -LL + pub type FTT0 = for<'a> fn(); +LL + pub type FTT0 = for<'a> fn(); | error: an `fn` pointer type cannot be `const` @@ -135,7 +135,7 @@ LL | pub type FTT1 = for<'a> const extern "C" fn(); help: remove the `const` qualifier | LL - pub type FTT1 = for<'a> const extern "C" fn(); -LL + pub type FTT1 = for<'a> extern "C" fn(); +LL + pub type FTT1 = for<'a> extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -149,7 +149,7 @@ LL | pub type FTT2 = for<'a> const unsafe extern "C" fn(); help: remove the `const` qualifier | LL - pub type FTT2 = for<'a> const unsafe extern "C" fn(); -LL + pub type FTT2 = for<'a> unsafe extern "C" fn(); +LL + pub type FTT2 = for<'a> unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -163,7 +163,7 @@ LL | pub type FTT3 = for<'a> async fn(); help: remove the `async` qualifier | LL - pub type FTT3 = for<'a> async fn(); -LL + pub type FTT3 = for<'a> fn(); +LL + pub type FTT3 = for<'a> fn(); | error: an `fn` pointer type cannot be `async` @@ -177,7 +177,7 @@ LL | pub type FTT4 = for<'a> async extern "C" fn(); help: remove the `async` qualifier | LL - pub type FTT4 = for<'a> async extern "C" fn(); -LL + pub type FTT4 = for<'a> extern "C" fn(); +LL + pub type FTT4 = for<'a> extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -191,7 +191,7 @@ LL | pub type FTT5 = for<'a> async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - pub type FTT5 = for<'a> async unsafe extern "C" fn(); -LL + pub type FTT5 = for<'a> unsafe extern "C" fn(); +LL + pub type FTT5 = for<'a> unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -205,7 +205,7 @@ LL | pub type FTT6 = for<'a> const async unsafe extern "C" fn(); help: remove the `const` qualifier | LL - pub type FTT6 = for<'a> const async unsafe extern "C" fn(); -LL + pub type FTT6 = for<'a> async unsafe extern "C" fn(); +LL + pub type FTT6 = for<'a> async unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -219,7 +219,7 @@ LL | pub type FTT6 = for<'a> const async unsafe extern "C" fn(); 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(); +LL + pub type FTT6 = for<'a> const unsafe extern "C" fn(); | error: aborting due to 16 previous errors 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 9112a0e135a50..4e5927914ccb5 100644 --- a/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr +++ b/tests/ui/parser/recover/recover-const-async-fn-ptr.stderr @@ -9,7 +9,7 @@ LL | type T0 = const fn(); help: remove the `const` qualifier | LL - type T0 = const fn(); -LL + type T0 = fn(); +LL + type T0 = fn(); | error: an `fn` pointer type cannot be `const` @@ -23,7 +23,7 @@ LL | type T1 = const extern "C" fn(); help: remove the `const` qualifier | LL - type T1 = const extern "C" fn(); -LL + type T1 = extern "C" fn(); +LL + type T1 = extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -37,7 +37,7 @@ LL | type T2 = const unsafe extern "C" fn(); help: remove the `const` qualifier | LL - type T2 = const unsafe extern "C" fn(); -LL + type T2 = unsafe extern "C" fn(); +LL + type T2 = unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -51,7 +51,7 @@ LL | type T3 = async fn(); help: remove the `async` qualifier | LL - type T3 = async fn(); -LL + type T3 = fn(); +LL + type T3 = fn(); | error: an `fn` pointer type cannot be `async` @@ -65,7 +65,7 @@ LL | type T4 = async extern "C" fn(); help: remove the `async` qualifier | LL - type T4 = async extern "C" fn(); -LL + type T4 = extern "C" fn(); +LL + type T4 = extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -79,7 +79,7 @@ LL | type T5 = async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - type T5 = async unsafe extern "C" fn(); -LL + type T5 = unsafe extern "C" fn(); +LL + type T5 = unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -93,7 +93,7 @@ LL | type T6 = const async unsafe extern "C" fn(); help: remove the `const` qualifier | LL - type T6 = const async unsafe extern "C" fn(); -LL + type T6 = async unsafe extern "C" fn(); +LL + type T6 = async unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -107,7 +107,7 @@ LL | type T6 = const async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - type T6 = const async unsafe extern "C" fn(); -LL + type T6 = const unsafe extern "C" fn(); +LL + type T6 = const unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -121,7 +121,7 @@ LL | type FT0 = for<'a> const fn(); help: remove the `const` qualifier | LL - type FT0 = for<'a> const fn(); -LL + type FT0 = for<'a> fn(); +LL + type FT0 = for<'a> fn(); | error: an `fn` pointer type cannot be `const` @@ -135,7 +135,7 @@ LL | type FT1 = for<'a> const extern "C" fn(); help: remove the `const` qualifier | LL - type FT1 = for<'a> const extern "C" fn(); -LL + type FT1 = for<'a> extern "C" fn(); +LL + type FT1 = for<'a> extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -149,7 +149,7 @@ LL | type FT2 = for<'a> const unsafe extern "C" fn(); help: remove the `const` qualifier | LL - type FT2 = for<'a> const unsafe extern "C" fn(); -LL + type FT2 = for<'a> unsafe extern "C" fn(); +LL + type FT2 = for<'a> unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -163,7 +163,7 @@ LL | type FT3 = for<'a> async fn(); help: remove the `async` qualifier | LL - type FT3 = for<'a> async fn(); -LL + type FT3 = for<'a> fn(); +LL + type FT3 = for<'a> fn(); | error: an `fn` pointer type cannot be `async` @@ -177,7 +177,7 @@ LL | type FT4 = for<'a> async extern "C" fn(); help: remove the `async` qualifier | LL - type FT4 = for<'a> async extern "C" fn(); -LL + type FT4 = for<'a> extern "C" fn(); +LL + type FT4 = for<'a> extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -191,7 +191,7 @@ LL | type FT5 = for<'a> async unsafe extern "C" fn(); help: remove the `async` qualifier | LL - type FT5 = for<'a> async unsafe extern "C" fn(); -LL + type FT5 = for<'a> unsafe extern "C" fn(); +LL + type FT5 = for<'a> unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `const` @@ -205,7 +205,7 @@ LL | type FT6 = for<'a> const async unsafe extern "C" fn(); help: remove the `const` qualifier | LL - type FT6 = for<'a> const async unsafe extern "C" fn(); -LL + type FT6 = for<'a> async unsafe extern "C" fn(); +LL + type FT6 = for<'a> async unsafe extern "C" fn(); | error: an `fn` pointer type cannot be `async` @@ -219,7 +219,7 @@ LL | type FT6 = for<'a> const async unsafe extern "C" fn(); 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(); +LL + type FT6 = for<'a> const unsafe extern "C" fn(); | error[E0308]: mismatched types