From cd0987115765efdf4f834f0f0bf24c4cef063b1a Mon Sep 17 00:00:00 2001 From: oli Date: Sat, 23 Jan 2021 11:58:58 +0000 Subject: [PATCH] Cover more cases in the test suite --- .../consts/const-mut-refs/mut_ref_in_final.rs | 45 +++++++++++++++ .../const-mut-refs/mut_ref_in_final.stderr | 57 ++++++++++++++++++- .../const-mut-refs/mut_ref_in_final_ok.rs | 22 ------- .../const-mut-refs/mut_ref_in_final_ok.stderr | 13 ----- 4 files changed, 99 insertions(+), 38 deletions(-) delete mode 100644 src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.rs delete mode 100644 src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.stderr diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs index 98960ec6c6e8a..b2230697037f3 100644 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs @@ -1,6 +1,9 @@ #![feature(const_mut_refs)] #![feature(const_fn)] +#![feature(const_transmute)] #![feature(raw_ref_op)] +#![feature(const_raw_ptr_deref)] + const NULL: *mut i32 = std::ptr::null_mut(); const A: *const i32 = &4; @@ -9,6 +12,25 @@ const A: *const i32 = &4; // as that would be an enormous footgun in oli-obk's opinion. const B: *mut i32 = &mut 4; //~ ERROR mutable references are not allowed +// Ok, no actual mutable allocation exists +const B2: Option<&mut i32> = None; + +// Not ok, can't prove that no mutable allocation ends up in final value +const B3: Option<&mut i32> = Some(&mut 42); //~ ERROR temporary value dropped while borrowed + +const fn helper() -> Option<&'static mut i32> { unsafe { + // Undefined behaviour, who doesn't love tests like this. + // This code never gets executed, because the static checks fail before that. + Some(&mut *(42 as *mut i32)) +} } +// Check that we do not look into function bodies. +// We treat all functions as not returning a mutable reference, because there is no way to +// do that without causing the borrow checker to complain (see the B5/helper2 test below). +const B4: Option<&mut i32> = helper(); + +const fn helper2(x: &mut i32) -> Option<&mut i32> { Some(x) } +const B5: Option<&mut i32> = helper2(&mut 42); //~ ERROR temporary value dropped while borrowed + // Ok, because no references to mutable data exist here, since the `{}` moves // its value and then takes a reference to that. const C: *const i32 = &{ @@ -17,7 +39,30 @@ const C: *const i32 = &{ x }; +use std::cell::UnsafeCell; +struct NotAMutex(UnsafeCell); + +unsafe impl Sync for NotAMutex {} + +const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); +//~^ ERROR temporary value dropped while borrowed + +static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); +//~^ ERROR temporary value dropped while borrowed + +static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); +//~^ ERROR temporary value dropped while borrowed + +// `BAR` works, because `&42` promotes immediately instead of relying on +// the enclosing scope rule. +const BAR: NotAMutex<&i32> = NotAMutex(UnsafeCell::new(&42)); + fn main() { println!("{}", unsafe { *A }); unsafe { *B = 4 } // Bad news + + unsafe { + **FOO.0.get() = 99; + assert_eq!(**FOO.0.get(), 99); + } } diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr index 57bf5f7395de4..389b88955cec4 100644 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr +++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr @@ -1,9 +1,60 @@ error[E0764]: mutable references are not allowed in the final value of constants - --> $DIR/mut_ref_in_final.rs:10:21 + --> $DIR/mut_ref_in_final.rs:13:21 | LL | const B: *mut i32 = &mut 4; | ^^^^^^ -error: aborting due to previous error +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:19:40 + | +LL | const B3: Option<&mut i32> = Some(&mut 42); + | ----------^^- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary which is freed while still in use + | using this value as a constant requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:32:43 + | +LL | const B5: Option<&mut i32> = helper2(&mut 42); + | -------------^^- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary which is freed while still in use + | using this value as a constant requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:47:65 + | +LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); + | -------------------------------^^-- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary which is freed while still in use + | using this value as a constant requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:50:67 + | +LL | static FOO2: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); + | -------------------------------^^-- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary which is freed while still in use + | using this value as a static requires that borrow lasts for `'static` + +error[E0716]: temporary value dropped while borrowed + --> $DIR/mut_ref_in_final.rs:53:71 + | +LL | static mut FOO3: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); + | -------------------------------^^-- + | | | | + | | | temporary value is freed at the end of this statement + | | creates a temporary which is freed while still in use + | using this value as a static requires that borrow lasts for `'static` + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0764`. +Some errors have detailed explanations: E0716, E0764. +For more information about an error, try `rustc --explain E0716`. diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.rs b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.rs deleted file mode 100644 index 3f2995df2d769..0000000000000 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.rs +++ /dev/null @@ -1,22 +0,0 @@ -#![feature(const_mut_refs)] -#![feature(const_fn)] -#![feature(raw_ref_op)] - -use std::cell::UnsafeCell; -struct NotAMutex(UnsafeCell); - -unsafe impl Sync for NotAMutex {} - -const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); -//~^ ERROR temporary value dropped while borrowed - -// `BAR` works, because `&42` promotes immediately instead of relying on -// "final value lifetime extension". -const BAR: NotAMutex<&i32> = NotAMutex(UnsafeCell::new(&42)); - -fn main() { - unsafe { - **FOO.0.get() = 99; - assert_eq!(**FOO.0.get(), 99); - } -} diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.stderr deleted file mode 100644 index 8b51e44e16956..0000000000000 --- a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_ok.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0716]: temporary value dropped while borrowed - --> $DIR/mut_ref_in_final_ok.rs:10:65 - | -LL | const FOO: NotAMutex<&mut i32> = NotAMutex(UnsafeCell::new(&mut 42)); - | -------------------------------^^-- - | | | | - | | | temporary value is freed at the end of this statement - | | creates a temporary which is freed while still in use - | using this value as a constant requires that borrow lasts for `'static` - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0716`.