From bd837e899bdb13a6207a0494556380fc4491f2eb Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Oct 2020 17:46:01 +0100 Subject: [PATCH 1/3] make sure we do not promote things with interior mutability --- src/test/ui/consts/promote-not.rs | 7 ++++++- src/test/ui/consts/promote-not.stderr | 22 ++++++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/test/ui/consts/promote-not.rs b/src/test/ui/consts/promote-not.rs index 30bb9917bf7ad..a7938fabad56f 100644 --- a/src/test/ui/consts/promote-not.rs +++ b/src/test/ui/consts/promote-not.rs @@ -3,6 +3,8 @@ #![allow(unconditional_panic, const_err)] #![feature(const_fn, const_fn_union)] +use std::cell::Cell; + // We do not promote mutable references. static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]); //~ ERROR temporary value dropped while borrowed @@ -32,4 +34,7 @@ const TEST_UNION: () = { let _x: &'static i32 = &unsafe { U { x: 0 }.x }; //~ ERROR temporary value dropped while borrowed }; -fn main() {} +fn main() { + // We must not promote things with interior mutability. + let _val: &'static _ = &(Cell::new(1), 2).0; //~ ERROR temporary value dropped while borrowed +} diff --git a/src/test/ui/consts/promote-not.stderr b/src/test/ui/consts/promote-not.stderr index 6ca7a4c273ee2..2698424c16526 100644 --- a/src/test/ui/consts/promote-not.stderr +++ b/src/test/ui/consts/promote-not.stderr @@ -1,5 +1,5 @@ error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:7:50 + --> $DIR/promote-not.rs:9:50 | LL | static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]); | ----------^^^^^^^^^- @@ -9,7 +9,7 @@ LL | static mut TEST1: Option<&mut [i32]> = Some(&mut [1, 2, 3]); | using this value as a static requires that borrow lasts for `'static` error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:10:18 + --> $DIR/promote-not.rs:12:18 | LL | let x = &mut [1,2,3]; | ^^^^^^^ creates a temporary which is freed while still in use @@ -19,7 +19,7 @@ LL | }; | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:19:32 + --> $DIR/promote-not.rs:21:32 | LL | let _x: &'static () = &foo(); | ----------- ^^^^^ creates a temporary which is freed while still in use @@ -29,7 +29,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:27:29 + --> $DIR/promote-not.rs:29:29 | LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x }; | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use @@ -39,7 +39,7 @@ LL | } | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:32:29 + --> $DIR/promote-not.rs:34:29 | LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x }; | ------------ ^^^^^^^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use @@ -48,6 +48,16 @@ LL | let _x: &'static i32 = &unsafe { U { x: 0 }.x }; LL | }; | - temporary value is freed at the end of this statement -error: aborting due to 5 previous errors +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:39:29 + | +LL | let _val: &'static _ = &(Cell::new(1), 2).0; + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | } + | - temporary value is freed at the end of this statement + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0716`. From 99a44ed086978339d531aa40f84efdaa1bacbb45 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 25 Oct 2020 18:06:41 +0100 Subject: [PATCH 2/3] remove a hack that seems to only benefit a few very special cases --- .../rustc_mir/src/transform/promote_consts.rs | 58 ++----------------- src/test/ui/consts/promote-not.rs | 9 ++- src/test/ui/consts/promote-not.stderr | 25 +++++++- 3 files changed, 37 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index 927aae82a36ef..8d5ed747c3f8f 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -22,7 +22,7 @@ use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::{self, List, TyCtxt, TypeFoldable}; use rustc_span::symbol::sym; -use rustc_span::{Span, DUMMY_SP}; +use rustc_span::Span; use rustc_index::vec::{Idx, IndexVec}; use rustc_target::spec::abi::Abi; @@ -326,41 +326,16 @@ impl<'tcx> Validator<'_, 'tcx> { if place.projection.contains(&ProjectionElem::Deref) { return Err(Unpromotable); } - - let mut has_mut_interior = - self.qualif_local::(place.local); - // HACK(eddyb) this should compute the same thing as - // `::in_projection` from - // `check_consts::qualifs` but without recursion. - if has_mut_interior { - // This allows borrowing fields which don't have - // `HasMutInterior`, from a type that does, e.g.: - // `let _: &'static _ = &(Cell::new(1), 2).1;` - let mut place_projection = &place.projection[..]; - // FIXME(eddyb) use a forward loop instead of a reverse one. - while let &[ref proj_base @ .., elem] = place_projection { - // FIXME(eddyb) this is probably excessive, with - // the exception of `union` member accesses. - let ty = - Place::ty_from(place.local, proj_base, self.body, self.tcx) - .projection_ty(self.tcx, elem) - .ty; - if ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env) { - has_mut_interior = false; - break; - } - - place_projection = proj_base; - } + if self.qualif_local::(place.local) { + return Err(Unpromotable); } // FIXME(eddyb) this duplicates part of `validate_rvalue`. + let has_mut_interior = + self.qualif_local::(place.local); if has_mut_interior { return Err(Unpromotable); } - if self.qualif_local::(place.local) { - return Err(Unpromotable); - } if let BorrowKind::Mut { .. } = kind { let ty = place.ty(self.body, self.tcx).ty; @@ -692,28 +667,7 @@ impl<'tcx> Validator<'_, 'tcx> { self.validate_place(place)?; - // HACK(eddyb) this should compute the same thing as - // `::in_projection` from - // `check_consts::qualifs` but without recursion. - let mut has_mut_interior = - self.qualif_local::(place.local); - if has_mut_interior { - let mut place_projection = place.projection; - // FIXME(eddyb) use a forward loop instead of a reverse one. - while let &[ref proj_base @ .., elem] = place_projection { - // FIXME(eddyb) this is probably excessive, with - // the exception of `union` member accesses. - let ty = Place::ty_from(place.local, proj_base, self.body, self.tcx) - .projection_ty(self.tcx, elem) - .ty; - if ty.is_freeze(self.tcx.at(DUMMY_SP), self.param_env) { - has_mut_interior = false; - break; - } - - place_projection = proj_base; - } - } + let has_mut_interior = self.qualif_local::(place.local); if has_mut_interior { return Err(Unpromotable); } diff --git a/src/test/ui/consts/promote-not.rs b/src/test/ui/consts/promote-not.rs index a7938fabad56f..1e4d8586b872c 100644 --- a/src/test/ui/consts/promote-not.rs +++ b/src/test/ui/consts/promote-not.rs @@ -34,7 +34,14 @@ const TEST_UNION: () = { let _x: &'static i32 = &unsafe { U { x: 0 }.x }; //~ ERROR temporary value dropped while borrowed }; +// In a `const`, we do not promote things with interior mutability. Not even if we "project it away". +const TEST_INTERIOR_MUT: () = { + // The "0." case is already ruled out by not permitting any interior mutability in `const`. + let _val: &'static _ = &(Cell::new(1), 2).1; //~ ERROR temporary value dropped while borrowed +}; + fn main() { - // We must not promote things with interior mutability. + // We must not promote things with interior mutability. Not even if we "project it away". let _val: &'static _ = &(Cell::new(1), 2).0; //~ ERROR temporary value dropped while borrowed + let _val: &'static _ = &(Cell::new(1), 2).1; //~ ERROR temporary value dropped while borrowed } diff --git a/src/test/ui/consts/promote-not.stderr b/src/test/ui/consts/promote-not.stderr index 2698424c16526..6e76d9ee6c165 100644 --- a/src/test/ui/consts/promote-not.stderr +++ b/src/test/ui/consts/promote-not.stderr @@ -49,15 +49,36 @@ LL | }; | - temporary value is freed at the end of this statement error[E0716]: temporary value dropped while borrowed - --> $DIR/promote-not.rs:39:29 + --> $DIR/promote-not.rs:40:29 + | +LL | let _val: &'static _ = &(Cell::new(1), 2).1; + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` +LL | }; + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:45:29 | LL | let _val: &'static _ = &(Cell::new(1), 2).0; | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use | | | type annotation requires that borrow lasts for `'static` +LL | let _val: &'static _ = &(Cell::new(1), 2).1; +LL | } + | - temporary value is freed at the end of this statement + +error[E0716]: temporary value dropped while borrowed + --> $DIR/promote-not.rs:46:29 + | +LL | let _val: &'static _ = &(Cell::new(1), 2).1; + | ---------- ^^^^^^^^^^^^^^^^^ creates a temporary which is freed while still in use + | | + | type annotation requires that borrow lasts for `'static` LL | } | - temporary value is freed at the end of this statement -error: aborting due to 6 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0716`. From d057a93e6f43eb410b9c348a8fe590bdc4452ae6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 15 Nov 2020 15:22:38 +0100 Subject: [PATCH 3/3] remove a test that does not work any more --- src/test/ui/issues/issue-49955-2.rs | 19 ------------------- 1 file changed, 19 deletions(-) delete mode 100644 src/test/ui/issues/issue-49955-2.rs diff --git a/src/test/ui/issues/issue-49955-2.rs b/src/test/ui/issues/issue-49955-2.rs deleted file mode 100644 index 267ed746322ea..0000000000000 --- a/src/test/ui/issues/issue-49955-2.rs +++ /dev/null @@ -1,19 +0,0 @@ -// run-pass -// compile-flags: -Z borrowck=mir - -use std::cell::Cell; - -const FIVE: Cell = Cell::new(5); - -#[inline(never)] -fn tuple_field() -> &'static u32 { - // This test is MIR-borrowck-only because the old borrowck - // doesn't agree that borrows of "frozen" (i.e., without any - // interior mutability) fields of non-frozen temporaries, - // should be promoted, while MIR promotion does promote them. - &(FIVE, 42).1 -} - -fn main() { - assert_eq!(tuple_field().to_string(), "42"); -}