diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 02847a0f5f91..769c469a5ab2 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -292,6 +292,9 @@ resolve_underscore_lifetime_name_cannot_be_used_here =
 resolve_unexpected_res_change_ty_to_const_param_sugg =
     you might have meant to write a const parameter here
 
+resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg =
+    if you meant to collect the rest of the slice in `{$ident}`, use the at operator
+
 resolve_unreachable_label =
     use of unreachable label `{$name}`
     .label = unreachable label `{$name}`
diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs
index 655fc9812d74..49a0e597dbc7 100644
--- a/compiler/rustc_resolve/src/errors.rs
+++ b/compiler/rustc_resolve/src/errors.rs
@@ -800,3 +800,17 @@ pub(crate) struct UnexpectedResChangeTyToConstParamSugg {
     #[applicability]
     pub applicability: Applicability,
 }
+
+#[derive(Subdiagnostic)]
+#[suggestion(
+    resolve_unexpected_res_use_at_op_in_slice_pat_with_range_sugg,
+    code = "{snippet}",
+    applicability = "maybe-incorrect",
+    style = "verbose"
+)]
+pub(crate) struct UnexpectedResUseAtOpInSlicePatWithRangeSugg {
+    #[primary_span]
+    pub span: Span,
+    pub ident: Ident,
+    pub snippet: String,
+}
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 310c126213ad..5d712461993d 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -1077,24 +1077,34 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         err: &mut Diagnostic,
         path: &[Segment],
     ) {
-        if let Some(pat) = self.diagnostic_metadata.current_pat
-            && let ast::PatKind::Range(Some(start), None, range) = &pat.kind
-            && let ExprKind::Path(None, range_path) = &start.kind
+        let Some(pat) = self.diagnostic_metadata.current_pat else { return };
+        let (bound, side, range) = match &pat.kind {
+            ast::PatKind::Range(Some(bound), None, range) => (bound, Side::Start, range),
+            ast::PatKind::Range(None, Some(bound), range) => (bound, Side::End, range),
+            _ => return,
+        };
+        if let ExprKind::Path(None, range_path) = &bound.kind
             && let [segment] = &range_path.segments[..]
             && let [s] = path
             && segment.ident == s.ident
+            && segment.ident.span.eq_ctxt(range.span)
         {
-            // We've encountered `[first, rest..]` where the user might have meant
-            // `[first, rest @ ..]` (#88404).
-            err.span_suggestion_verbose(
-                segment.ident.span.between(range.span),
-                format!(
-                    "if you meant to collect the rest of the slice in `{}`, use the at operator",
-                    segment.ident,
-                ),
-                " @ ",
-                Applicability::MaybeIncorrect,
-            );
+            // We've encountered `[first, rest..]` (#88404) or `[first, ..rest]` (#120591)
+            // where the user might have meant `[first, rest @ ..]`.
+            let (span, snippet) = match side {
+                Side::Start => (segment.ident.span.between(range.span), " @ ".into()),
+                Side::End => (range.span.to(segment.ident.span), format!("{} @ ..", segment.ident)),
+            };
+            err.subdiagnostic(errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg {
+                span,
+                ident: segment.ident,
+                snippet,
+            });
+        }
+
+        enum Side {
+            Start,
+            End,
         }
     }
 
diff --git a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs
index a619fcafc861..1eba7aeb4d64 100644
--- a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs
+++ b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.rs
@@ -1,9 +1,23 @@
 fn main() {
     match &[1, 2, 3][..] {
-        [1, rest..] => println!("{rest:?}"),
+        [1, rest..] => println!("{rest}"),
         //~^ ERROR cannot find value `rest` in this scope
         //~| ERROR cannot find value `rest` in this scope
         //~| ERROR `X..` patterns in slices are experimental
         _ => {}
     }
+    match &[4, 5, 6][..] {
+        [] => {}
+        [_, ..tail] => println!("{tail}"),
+        //~^ ERROR cannot find value `tail` in this scope
+        //~| ERROR cannot find value `tail` in this scope
+        //~| ERROR exclusive range pattern syntax is experimental
+    }
+    match &[7, 8, 9][..] {
+        [] => {}
+        [_, ...tail] => println!("{tail}"),
+        //~^ ERROR cannot find value `tail` in this scope
+        //~| ERROR cannot find value `tail` in this scope
+        //~| ERROR range-to patterns with `...` are not allowed
+    }
 }
diff --git a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr
index c3c9131b63eb..3a19517c85bd 100644
--- a/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr
+++ b/tests/ui/pattern/range-pattern-meant-to-be-slice-rest-pattern.stderr
@@ -1,31 +1,82 @@
+error: range-to patterns with `...` are not allowed
+  --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:13
+   |
+LL |         [_, ...tail] => println!("{tail}"),
+   |             ^^^ help: use `..=` instead
+
 error[E0425]: cannot find value `rest` in this scope
   --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13
    |
-LL |         [1, rest..] => println!("{rest:?}"),
+LL |         [1, rest..] => println!("{rest}"),
    |             ^^^^ not found in this scope
    |
 help: if you meant to collect the rest of the slice in `rest`, use the at operator
    |
-LL |         [1, rest @ ..] => println!("{rest:?}"),
+LL |         [1, rest @ ..] => println!("{rest}"),
    |                  +
 
 error[E0425]: cannot find value `rest` in this scope
   --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:35
    |
-LL |         [1, rest..] => println!("{rest:?}"),
+LL |         [1, rest..] => println!("{rest}"),
+   |                                   ^^^^ not found in this scope
+
+error[E0425]: cannot find value `tail` in this scope
+  --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:15
+   |
+LL |         [_, ..tail] => println!("{tail}"),
+   |               ^^^^ not found in this scope
+   |
+help: if you meant to collect the rest of the slice in `tail`, use the at operator
+   |
+LL |         [_, tail @ ..] => println!("{tail}"),
+   |             ~~~~~~~~~
+
+error[E0425]: cannot find value `tail` in this scope
+  --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:35
+   |
+LL |         [_, ..tail] => println!("{tail}"),
    |                                   ^^^^ not found in this scope
 
+error[E0425]: cannot find value `tail` in this scope
+  --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:16
+   |
+LL |         [_, ...tail] => println!("{tail}"),
+   |                ^^^^ not found in this scope
+   |
+help: if you meant to collect the rest of the slice in `tail`, use the at operator
+   |
+LL |         [_, tail @ ..] => println!("{tail}"),
+   |             ~~~~~~~~~
+
+error[E0425]: cannot find value `tail` in this scope
+  --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:18:36
+   |
+LL |         [_, ...tail] => println!("{tail}"),
+   |                                    ^^^^ not found in this scope
+
 error[E0658]: `X..` patterns in slices are experimental
   --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:3:13
    |
-LL |         [1, rest..] => println!("{rest:?}"),
+LL |         [1, rest..] => println!("{rest}"),
    |             ^^^^^^
    |
    = note: see issue #67264 <https://github.com/rust-lang/rust/issues/67264> for more information
    = help: add `#![feature(half_open_range_patterns_in_slices)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error: aborting due to 3 previous errors
+error[E0658]: exclusive range pattern syntax is experimental
+  --> $DIR/range-pattern-meant-to-be-slice-rest-pattern.rs:11:13
+   |
+LL |         [_, ..tail] => println!("{tail}"),
+   |             ^^^^^^
+   |
+   = note: see issue #37854 <https://github.com/rust-lang/rust/issues/37854> for more information
+   = help: add `#![feature(exclusive_range_pattern)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = help: use an inclusive range pattern, like N..=M
+
+error: aborting due to 9 previous errors
 
 Some errors have detailed explanations: E0425, E0658.
 For more information about an error, try `rustc --explain E0425`.