diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index a6e2cad509408..2811848424b4e 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -750,7 +750,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
             }
 
             Rvalue::BinaryOp(op, ref lhs, _) => {
-                if let ty::RawPtr(_) = lhs.ty(self.mir, self.tcx).sty {
+                if let ty::RawPtr(_) | ty::FnPtr(..) = lhs.ty(self.mir, self.tcx).sty {
                     assert!(op == BinOp::Eq || op == BinOp::Ne ||
                             op == BinOp::Le || op == BinOp::Lt ||
                             op == BinOp::Ge || op == BinOp::Gt ||
diff --git a/src/librustc_passes/rvalue_promotion.rs b/src/librustc_passes/rvalue_promotion.rs
index 828800465209e..efe59e4face5e 100644
--- a/src/librustc_passes/rvalue_promotion.rs
+++ b/src/librustc_passes/rvalue_promotion.rs
@@ -348,7 +348,7 @@ fn check_expr_kind<'a, 'tcx>(
                 return NotPromotable;
             }
             match v.tables.node_id_to_type(lhs.hir_id).sty {
-                ty::RawPtr(_) => {
+                ty::RawPtr(_) | ty::FnPtr(..) => {
                     assert!(op.node == hir::BinOpKind::Eq || op.node == hir::BinOpKind::Ne ||
                             op.node == hir::BinOpKind::Le || op.node == hir::BinOpKind::Lt ||
                             op.node == hir::BinOpKind::Ge || op.node == hir::BinOpKind::Gt);
diff --git a/src/test/run-pass/issues/issue-54696.rs b/src/test/run-pass/issues/issue-54696.rs
new file mode 100644
index 0000000000000..d8408ed85491f
--- /dev/null
+++ b/src/test/run-pass/issues/issue-54696.rs
@@ -0,0 +1,8 @@
+// run-pass
+
+fn main() {
+    // We shouldn't promote this
+    &(main as fn() == main as fn());
+    // Also check nested case
+    &(&(main as fn()) == &(main as fn()));
+}
diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.nll.stderr b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.nll.stderr
index bc8a99f55483f..f31d962852e4a 100644
--- a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.nll.stderr
+++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.nll.stderr
@@ -14,7 +14,7 @@ error[E0716]: temporary value dropped while borrowed
    |
 LL |     let y: &'static usize = &(&1 as *const i32 as usize + 1); //~ ERROR does not live long enough
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
-LL |     let z: &'static i32 = &(unsafe { *(42 as *const i32) }); //~ ERROR does not live long enough
+...
 LL | }
    | - temporary value is freed at the end of this statement
    |
@@ -25,11 +25,22 @@ error[E0716]: temporary value dropped while borrowed
    |
 LL |     let z: &'static i32 = &(unsafe { *(42 as *const i32) }); //~ ERROR does not live long enough
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
+LL |     let a: &'static bool = &(main as fn() == main as fn()); //~ ERROR does not live long enough
+LL | }
+   | - temporary value is freed at the end of this statement
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/promoted_raw_ptr_ops.rs:18:29
+   |
+LL |     let a: &'static bool = &(main as fn() == main as fn()); //~ ERROR does not live long enough
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use
 LL | }
    | - temporary value is freed at the end of this statement
    |
    = note: borrowed value must be valid for the static lifetime...
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0716`.
diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs
index 3b437f69d8d63..c915886ca2592 100644
--- a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs
+++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs
@@ -15,4 +15,5 @@ fn main() {
     //~^ ERROR does not live long enough
     let y: &'static usize = &(&1 as *const i32 as usize + 1); //~ ERROR does not live long enough
     let z: &'static i32 = &(unsafe { *(42 as *const i32) }); //~ ERROR does not live long enough
+    let a: &'static bool = &(main as fn() == main as fn()); //~ ERROR does not live long enough
 }
diff --git a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr
index 90c73c095fba1..baf12c5ac591d 100644
--- a/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr
+++ b/src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr
@@ -14,7 +14,7 @@ error[E0597]: borrowed value does not live long enough
    |
 LL |     let y: &'static usize = &(&1 as *const i32 as usize + 1); //~ ERROR does not live long enough
    |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
-LL |     let z: &'static i32 = &(unsafe { *(42 as *const i32) }); //~ ERROR does not live long enough
+...
 LL | }
    | - temporary value only lives until here
    |
@@ -25,11 +25,22 @@ error[E0597]: borrowed value does not live long enough
    |
 LL |     let z: &'static i32 = &(unsafe { *(42 as *const i32) }); //~ ERROR does not live long enough
    |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     let a: &'static bool = &(main as fn() == main as fn()); //~ ERROR does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/promoted_raw_ptr_ops.rs:18:29
+   |
+LL |     let a: &'static bool = &(main as fn() == main as fn()); //~ ERROR does not live long enough
+   |                             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
 LL | }
    | - temporary value only lives until here
    |
    = note: borrowed value must be valid for the static lifetime...
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0597`.