about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTyrone Wu <wudevelops@gmail.com>2024-11-17 21:02:05 +0000
committerTyrone Wu <wudevelops@gmail.com>2025-01-27 17:17:22 +0000
commit5082fd8b1ee31284be473fe4e8691677ff61c708 (patch)
treeb9035a7d6a70c9e9c330e3ed6bc395c71ae27496
parentf753850659bdf5788332525f3fe395685929c682 (diff)
downloadrust-5082fd8b1ee31284be473fe4e8691677ff61c708.tar.gz
rust-5082fd8b1ee31284be473fe4e8691677ff61c708.zip
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 <wudevelops@gmail.com>
-rw-r--r--compiler/rustc_parse/src/errors.rs6
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs50
-rw-r--r--tests/ui/parser/bad-fn-ptr-qualifier.fixed28
-rw-r--r--tests/ui/parser/bad-fn-ptr-qualifier.stderr32
-rw-r--r--tests/ui/parser/recover/recover-const-async-fn-ptr.stderr32
5 files changed, 96 insertions, 52 deletions
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index f78d9dc2bfc..3d07166274d 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 6497d19a173..dc5919b3630 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:
+        // `<constness> <coroutine_kind> <safety> <extern> 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 e2a2f9486b7..8a97a2f09cc 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 ddc8bac678c..b9d2625d9f4 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 9112a0e135a..4e5927914cc 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