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`.