diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index cd4106ebf83af..017ae943e9161 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -6,6 +6,7 @@
 use std::cell::Cell;
 use std::slice;
 
+use rustc_ast::BindingMode;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync;
 use rustc_data_structures::unord::UnordMap;
@@ -14,6 +15,7 @@ use rustc_feature::Features;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
+use rustc_hir::{Pat, PatKind};
 use rustc_middle::bug;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
@@ -890,7 +892,12 @@ impl<'tcx> LateContext<'tcx> {
             }
             && let Some(init) = match parent_node {
                 hir::Node::Expr(expr) => Some(expr),
-                hir::Node::LetStmt(hir::LetStmt { init, .. }) => *init,
+                hir::Node::LetStmt(hir::LetStmt {
+                    init,
+                    // Binding is immutable, init cannot be re-assigned
+                    pat: Pat { kind: PatKind::Binding(BindingMode::NONE, ..), .. },
+                    ..
+                }) => *init,
                 _ => None,
             }
         {
@@ -935,7 +942,12 @@ impl<'tcx> LateContext<'tcx> {
             }
             && let Some(init) = match parent_node {
                 hir::Node::Expr(expr) => Some(expr),
-                hir::Node::LetStmt(hir::LetStmt { init, .. }) => *init,
+                hir::Node::LetStmt(hir::LetStmt {
+                    init,
+                    // Binding is immutable, init cannot be re-assigned
+                    pat: Pat { kind: PatKind::Binding(BindingMode::NONE, ..), .. },
+                    ..
+                }) => *init,
                 hir::Node::Item(item) => match item.kind {
                     hir::ItemKind::Const(.., body_id) | hir::ItemKind::Static(.., body_id) => {
                         Some(self.tcx.hir_body(body_id).value)
diff --git a/tests/ui/lint/invalid_from_utf8.rs b/tests/ui/lint/invalid_from_utf8.rs
index 87a906761c075..cbc1d8e90459d 100644
--- a/tests/ui/lint/invalid_from_utf8.rs
+++ b/tests/ui/lint/invalid_from_utf8.rs
@@ -128,18 +128,21 @@ pub fn from_utf8() {
 }
 
 pub fn from_utf8_with_indirections() {
-    let mut a = [99, 108, 130, 105, 112, 112, 121];
-    std::str::from_utf8_mut(&mut a);
-    //~^ WARN calls to `std::str::from_utf8_mut`
-    str::from_utf8_mut(&mut a);
-    //~^ WARN calls to `str::from_utf8_mut`
-    let mut b = &mut a;
-    let mut c = b;
-    std::str::from_utf8_mut(c);
-    //~^ WARN calls to `std::str::from_utf8_mut`
-    str::from_utf8_mut(c);
-    //~^ WARN calls to `str::from_utf8_mut`
-    let mut c = &[99, 108, 130, 105, 112, 112, 121];
+    // NOTE: We used to lint on the patterns below, but due to the
+    // binding being mutable it could be changed between the
+    // declaration and the call and that would have created a
+    // false-positive, so until we can reliably avoid those false
+    // postive we don't lint on them. Example of FP below.
+    //
+    // let mut a = [99, 108, 130, 105, 112, 112, 121];
+    // std::str::from_utf8_mut(&mut a);
+    // str::from_utf8_mut(&mut a);
+    // let mut b = &mut a;
+    // let mut c = b;
+    // std::str::from_utf8_mut(c);
+    // str::from_utf8_mut(c);
+
+    let c = &[99, 108, 130, 105, 112, 112, 121];
     std::str::from_utf8(c);
     //~^ WARN calls to `std::str::from_utf8`
     str::from_utf8(c);
@@ -164,6 +167,20 @@ pub fn from_utf8_with_indirections() {
     //~^ WARN calls to `std::str::from_utf8`
     str::from_utf8(INVALID_4);
     //~^ WARN calls to `str::from_utf8`
+
+    let mut a = [99, 108, 130, 105, 112, 112, 121]; // invalid
+    loop {
+        a = [99, 108, 130, 105, 112, 112, 121]; // still invalid, but too complex
+        break;
+    }
+    std::str::from_utf8_mut(&mut a);
+
+    let mut a = [99, 108, 130, 105, 112, 112]; // invalid
+    loop {
+        a = *b"clippy"; // valid
+        break;
+    }
+    std::str::from_utf8_mut(&mut a);
 }
 
 fn main() {}
diff --git a/tests/ui/lint/invalid_from_utf8.stderr b/tests/ui/lint/invalid_from_utf8.stderr
index 3cd4d227fc276..26bee5c403862 100644
--- a/tests/ui/lint/invalid_from_utf8.stderr
+++ b/tests/ui/lint/invalid_from_utf8.stderr
@@ -202,60 +202,25 @@ LL |         str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
    |                        |
    |                        the literal was valid UTF-8 up to the 2 bytes
 
-warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:132:5
-   |
-LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
-   |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
-LL |     std::str::from_utf8_mut(&mut a);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:134:5
-   |
-LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
-   |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
-...
-LL |     str::from_utf8_mut(&mut a);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:138:5
-   |
-LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
-   |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
-...
-LL |     std::str::from_utf8_mut(c);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:140:5
-   |
-LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
-   |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
-...
-LL |     str::from_utf8_mut(c);
-   |     ^^^^^^^^^^^^^^^^^^^^^
-
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:143:5
+  --> $DIR/invalid_from_utf8.rs:146:5
    |
-LL |     let mut c = &[99, 108, 130, 105, 112, 112, 121];
-   |                  ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
+LL |     let c = &[99, 108, 130, 105, 112, 112, 121];
+   |              ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
 LL |     std::str::from_utf8(c);
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:145:5
+  --> $DIR/invalid_from_utf8.rs:148:5
    |
-LL |     let mut c = &[99, 108, 130, 105, 112, 112, 121];
-   |                  ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
+LL |     let c = &[99, 108, 130, 105, 112, 112, 121];
+   |              ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
 ...
 LL |     str::from_utf8(c);
    |     ^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:148:5
+  --> $DIR/invalid_from_utf8.rs:151:5
    |
 LL |     const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -263,7 +228,7 @@ LL |     std::str::from_utf8(&INVALID_1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:150:5
+  --> $DIR/invalid_from_utf8.rs:153:5
    |
 LL |     const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -272,7 +237,7 @@ LL |     str::from_utf8(&INVALID_1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:153:5
+  --> $DIR/invalid_from_utf8.rs:156:5
    |
 LL |     static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -280,7 +245,7 @@ LL |     std::str::from_utf8(&INVALID_2);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:155:5
+  --> $DIR/invalid_from_utf8.rs:158:5
    |
 LL |     static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -289,7 +254,7 @@ LL |     str::from_utf8(&INVALID_2);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:158:5
+  --> $DIR/invalid_from_utf8.rs:161:5
    |
 LL |     const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121];
    |                                          ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -297,7 +262,7 @@ LL |     std::str::from_utf8(INVALID_3);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:160:5
+  --> $DIR/invalid_from_utf8.rs:163:5
    |
 LL |     const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121];
    |                                          ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -306,7 +271,7 @@ LL |     str::from_utf8(INVALID_3);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:163:5
+  --> $DIR/invalid_from_utf8.rs:166:5
    |
 LL |     const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] };
    |                                            ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -314,7 +279,7 @@ LL |     std::str::from_utf8(INVALID_4);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:165:5
+  --> $DIR/invalid_from_utf8.rs:168:5
    |
 LL |     const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] };
    |                                            ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -322,5 +287,5 @@ LL |     const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 12
 LL |     str::from_utf8(INVALID_4);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: 38 warnings emitted
+warning: 34 warnings emitted