diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 7ba57b3b7a266..0ec10dc9ea32d 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -83,7 +83,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         self.annotate_expected_due_to_let_ty(err, expr, error);
         self.emit_type_mismatch_suggestions(err, expr, expr_ty, expected, expected_ty_expr, error);
         self.note_type_is_not_clone(err, expected, expr_ty, expr);
-        self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
+        self.note_internal_mutation_in_method(err, expr, Some(expected), expr_ty);
         self.check_for_range_as_method_call(err, expr, expr_ty, expected);
         self.check_for_binding_assigned_block_without_tail_expression(err, expr, expr_ty, expected);
         self.check_wrong_return_type_due_to_generic_arg(err, expr, expr_ty);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 2075537cad71f..578e5b0104657 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -955,44 +955,75 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         err: &mut Diagnostic,
         expr: &hir::Expr<'_>,
-        expected: Ty<'tcx>,
+        expected: Option<Ty<'tcx>>,
         found: Ty<'tcx>,
     ) {
         if found != self.tcx.types.unit {
             return;
         }
-        if let ExprKind::MethodCall(path_segment, rcvr, ..) = expr.kind {
-            if self
-                .typeck_results
+
+        let ExprKind::MethodCall(path_segment, rcvr, ..) = expr.kind else {
+            return;
+        };
+
+        let rcvr_has_the_expected_type = self
+            .typeck_results
+            .borrow()
+            .expr_ty_adjusted_opt(rcvr)
+            .and_then(|ty| expected.map(|expected_ty| expected_ty.peel_refs() == ty.peel_refs()))
+            .unwrap_or(false);
+
+        let prev_call_mutates_and_returns_unit = || {
+            self.typeck_results
                 .borrow()
-                .expr_ty_adjusted_opt(rcvr)
-                .map_or(true, |ty| expected.peel_refs() != ty.peel_refs())
-            {
-                return;
-            }
-            let mut sp = MultiSpan::from_span(path_segment.ident.span);
-            sp.push_span_label(
-                path_segment.ident.span,
-                format!(
-                    "this call modifies {} in-place",
-                    match rcvr.kind {
-                        ExprKind::Path(QPath::Resolved(
-                            None,
-                            hir::Path { segments: [segment], .. },
-                        )) => format!("`{}`", segment.ident),
-                        _ => "its receiver".to_string(),
-                    }
-                ),
-            );
+                .type_dependent_def_id(expr.hir_id)
+                .map(|def_id| self.tcx.fn_sig(def_id).skip_binder().skip_binder())
+                .and_then(|sig| sig.inputs_and_output.split_last())
+                .map(|(output, inputs)| {
+                    output.is_unit()
+                        && inputs
+                            .get(0)
+                            .and_then(|self_ty| self_ty.ref_mutability())
+                            .map_or(false, rustc_ast::Mutability::is_mut)
+                })
+                .unwrap_or(false)
+        };
+
+        if !(rcvr_has_the_expected_type || prev_call_mutates_and_returns_unit()) {
+            return;
+        }
+
+        let mut sp = MultiSpan::from_span(path_segment.ident.span);
+        sp.push_span_label(
+            path_segment.ident.span,
+            format!(
+                "this call modifies {} in-place",
+                match rcvr.kind {
+                    ExprKind::Path(QPath::Resolved(
+                        None,
+                        hir::Path { segments: [segment], .. },
+                    )) => format!("`{}`", segment.ident),
+                    _ => "its receiver".to_string(),
+                }
+            ),
+        );
+
+        let modifies_rcvr_note =
+            format!("method `{}` modifies its receiver in-place", path_segment.ident);
+        if rcvr_has_the_expected_type {
             sp.push_span_label(
                 rcvr.span,
                 "you probably want to use this value after calling the method...",
             );
+            err.span_note(sp, &modifies_rcvr_note);
+            err.note(&format!("...instead of the `()` output of method `{}`", path_segment.ident));
+        } else if let ExprKind::MethodCall(..) = rcvr.kind {
             err.span_note(
                 sp,
-                &format!("method `{}` modifies its receiver in-place", path_segment.ident),
+                modifies_rcvr_note.clone() + ", it is not meant to be used in method chains.",
             );
-            err.note(&format!("...instead of the `()` output of method `{}`", path_segment.ident));
+        } else {
+            err.span_note(sp, &modifies_rcvr_note);
         }
     }
 
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 7055d9257ec90..50f2b71250c01 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -416,6 +416,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
                 probe.is_ok()
             });
+
+            self.note_internal_mutation_in_method(
+                &mut err,
+                rcvr_expr,
+                expected.to_option(&self),
+                rcvr_ty,
+            );
         }
 
         let mut custom_span_label = false;
diff --git a/tests/ui/suggestions/chain-method-call-mutation-in-place.rs b/tests/ui/suggestions/chain-method-call-mutation-in-place.rs
index cb92ab87a8ff7..7a4c747961c62 100644
--- a/tests/ui/suggestions/chain-method-call-mutation-in-place.rs
+++ b/tests/ui/suggestions/chain-method-call-mutation-in-place.rs
@@ -1,4 +1,8 @@
-fn main() {}
+fn main() {
+    let x: Vec<i32> = vec![1, 2, 3].into_iter().collect::<Vec<i32>>().sort_by_key(|i| i); //~ ERROR mismatched types
+    vec![1, 2, 3].into_iter().collect::<Vec<i32>>().sort_by_key(|i| i).sort(); //~ ERROR no method named `sort` found for unit type `()` in the current scope
+}
+
 fn foo(mut s: String) -> String {
     s.push_str("asdf") //~ ERROR mismatched types
 }
diff --git a/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr
index 11d9b8391f6d2..128160f10adb3 100644
--- a/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr
+++ b/tests/ui/suggestions/chain-method-call-mutation-in-place.stderr
@@ -1,5 +1,33 @@
 error[E0308]: mismatched types
-  --> $DIR/chain-method-call-mutation-in-place.rs:3:5
+  --> $DIR/chain-method-call-mutation-in-place.rs:2:23
+   |
+LL |     let x: Vec<i32> = vec![1, 2, 3].into_iter().collect::<Vec<i32>>().sort_by_key(|i| i);
+   |            --------   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Vec<i32>`, found `()`
+   |            |
+   |            expected due to this
+   |
+   = note: expected struct `Vec<i32>`
+           found unit type `()`
+note: method `sort_by_key` modifies its receiver in-place, it is not meant to be used in method chains.
+  --> $DIR/chain-method-call-mutation-in-place.rs:2:71
+   |
+LL |     let x: Vec<i32> = vec![1, 2, 3].into_iter().collect::<Vec<i32>>().sort_by_key(|i| i);
+   |                                                                       ^^^^^^^^^^^ this call modifies its receiver in-place
+
+error[E0599]: no method named `sort` found for unit type `()` in the current scope
+  --> $DIR/chain-method-call-mutation-in-place.rs:3:72
+   |
+LL |     vec![1, 2, 3].into_iter().collect::<Vec<i32>>().sort_by_key(|i| i).sort();
+   |                                                                        ^^^^ method not found in `()`
+   |
+note: method `sort_by_key` modifies its receiver in-place, it is not meant to be used in method chains.
+  --> $DIR/chain-method-call-mutation-in-place.rs:3:53
+   |
+LL |     vec![1, 2, 3].into_iter().collect::<Vec<i32>>().sort_by_key(|i| i).sort();
+   |                                                     ^^^^^^^^^^^ this call modifies its receiver in-place
+
+error[E0308]: mismatched types
+  --> $DIR/chain-method-call-mutation-in-place.rs:7:5
    |
 LL | fn foo(mut s: String) -> String {
    |                          ------ expected `String` because of return type
@@ -7,7 +35,7 @@ LL |     s.push_str("asdf")
    |     ^^^^^^^^^^^^^^^^^^ expected `String`, found `()`
    |
 note: method `push_str` modifies its receiver in-place
-  --> $DIR/chain-method-call-mutation-in-place.rs:3:7
+  --> $DIR/chain-method-call-mutation-in-place.rs:7:7
    |
 LL |     s.push_str("asdf")
    |     - ^^^^^^^^ this call modifies `s` in-place
@@ -15,6 +43,7 @@ LL |     s.push_str("asdf")
    |     you probably want to use this value after calling the method...
    = note: ...instead of the `()` output of method `push_str`
 
-error: aborting due to previous error
+error: aborting due to 3 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0308, E0599.
+For more information about an error, try `rustc --explain E0308`.