about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPietro Albini <pietro@pietroalbini.org>2018-10-02 22:54:35 +0200
committerGitHub <noreply@github.com>2018-10-02 22:54:35 +0200
commitd9d96637d4996051fb4fdda9adef73e8da2c71cd (patch)
tree7ac476bdd4fd91aec68e8f1d878355171d7932d8
parent958f1c55822c259ee5f7e906f2399a917a532331 (diff)
parent4cbfc9398d93d9eb0b1178b129f80de9be5c8ef9 (diff)
downloadrust-d9d96637d4996051fb4fdda9adef73e8da2c71cd.tar.gz
rust-d9d96637d4996051fb4fdda9adef73e8da2c71cd.zip
Rollup merge of #54702 - RalfJung:fn-ptr-promotion, r=oli-obk
do not promote comparing function pointers

This *could* break existing code that relied on fn ptr comparison getting promoted to `'static` lifetime.

Fixes https://github.com/rust-lang/rust/issues/54696
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs2
-rw-r--r--src/librustc_passes/rvalue_promotion.rs2
-rw-r--r--src/test/run-pass/issues/issue-54696.rs8
-rw-r--r--src/test/ui/consts/const-eval/promoted_raw_ptr_ops.nll.stderr15
-rw-r--r--src/test/ui/consts/const-eval/promoted_raw_ptr_ops.rs1
-rw-r--r--src/test/ui/consts/const-eval/promoted_raw_ptr_ops.stderr15
6 files changed, 37 insertions, 6 deletions
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index a6e2cad5094..2811848424b 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 82880046520..efe59e4face 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 00000000000..d8408ed8549
--- /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 bc8a99f5548..f31d962852e 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 3b437f69d8d..c915886ca25 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 90c73c095fb..baf12c5ac59 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`.