summaryrefslogtreecommitdiffstats
path: root/src/test/ui/consts/const-mut-refs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-17 12:02:58 +0000
commit698f8c2f01ea549d77d7dc3338a12e04c11057b9 (patch)
tree173a775858bd501c378080a10dca74132f05bc50 /src/test/ui/consts/const-mut-refs
parentInitial commit. (diff)
downloadrustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.tar.xz
rustc-698f8c2f01ea549d77d7dc3338a12e04c11057b9.zip
Adding upstream version 1.64.0+dfsg1.upstream/1.64.0+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/test/ui/consts/const-mut-refs')
-rw-r--r--src/test/ui/consts/const-mut-refs/const_mut_address_of.rs28
-rw-r--r--src/test/ui/consts/const-mut-refs/const_mut_refs.rs35
-rw-r--r--src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs8
-rw-r--r--src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr12
-rw-r--r--src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr31
-rw-r--r--src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr31
-rw-r--r--src/test/ui/consts/const-mut-refs/issue-76510.rs18
-rw-r--r--src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs55
-rw-r--r--src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr60
-rw-r--r--src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs27
-rw-r--r--src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr21
11 files changed, 326 insertions, 0 deletions
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs
new file mode 100644
index 000000000..03b2f9e3c
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/const_mut_address_of.rs
@@ -0,0 +1,28 @@
+// check-pass
+#![feature(const_mut_refs)]
+#![feature(raw_ref_op)]
+
+struct Foo {
+ x: usize
+}
+
+const fn foo() -> Foo {
+ Foo { x: 0 }
+}
+
+impl Foo {
+ const fn bar(&mut self) -> *mut usize {
+ &raw mut self.x
+ }
+}
+
+const fn baz(foo: &mut Foo)-> *mut usize {
+ &raw mut foo.x
+}
+
+const _: () = {
+ foo().bar();
+ baz(&mut foo());
+};
+
+fn main() {}
diff --git a/src/test/ui/consts/const-mut-refs/const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
new file mode 100644
index 000000000..544458dfc
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/const_mut_refs.rs
@@ -0,0 +1,35 @@
+// check-pass
+#![feature(const_mut_refs)]
+
+struct Foo {
+ x: usize
+}
+
+const fn foo() -> Foo {
+ Foo { x: 0 }
+}
+
+impl Foo {
+ const fn bar(&mut self) -> usize {
+ self.x = 1;
+ self.x
+ }
+
+}
+
+const fn baz(foo: &mut Foo) -> usize {
+ let x = &mut foo.x;
+ *x = 2;
+ *x
+}
+
+const fn bazz(foo: &mut Foo) -> usize {
+ foo.x = 3;
+ foo.x
+}
+
+fn main() {
+ let _: [(); foo().bar()] = [(); 1];
+ let _: [(); baz(&mut foo())] = [(); 2];
+ let _: [(); bazz(&mut foo())] = [(); 3];
+}
diff --git a/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs
new file mode 100644
index 000000000..ce9be4ac5
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.rs
@@ -0,0 +1,8 @@
+fn main() {
+ foo(&mut 5);
+}
+
+const fn foo(x: &mut i32) -> i32 { //~ ERROR mutable references
+ *x + 1
+
+}
diff --git a/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr
new file mode 100644
index 000000000..3f9bd3705
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/feature-gate-const_mut_refs.stderr
@@ -0,0 +1,12 @@
+error[E0658]: mutable references are not allowed in constant functions
+ --> $DIR/feature-gate-const_mut_refs.rs:5:14
+ |
+LL | const fn foo(x: &mut i32) -> i32 {
+ | ^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr
new file mode 100644
index 000000000..0f420ae1b
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/issue-76510.32bit.stderr
@@ -0,0 +1,31 @@
+error[E0764]: mutable references are not allowed in the final value of constants
+ --> $DIR/issue-76510.rs:5:29
+ |
+LL | const S: &'static mut str = &mut " hello ";
+ | ^^^^^^^^^^^^^^
+
+error[E0658]: mutation through a reference is not allowed in constants
+ --> $DIR/issue-76510.rs:5:29
+ |
+LL | const S: &'static mut str = &mut " hello ";
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+ --> $DIR/issue-76510.rs:5:29
+ |
+LL | const S: &'static mut str = &mut " hello ";
+ | ^^^^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/issue-76510.rs:11:70
+ |
+LL | let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
+ | ^ referenced constant has errors
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0080, E0596, E0658, E0764.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr
new file mode 100644
index 000000000..0f420ae1b
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/issue-76510.64bit.stderr
@@ -0,0 +1,31 @@
+error[E0764]: mutable references are not allowed in the final value of constants
+ --> $DIR/issue-76510.rs:5:29
+ |
+LL | const S: &'static mut str = &mut " hello ";
+ | ^^^^^^^^^^^^^^
+
+error[E0658]: mutation through a reference is not allowed in constants
+ --> $DIR/issue-76510.rs:5:29
+ |
+LL | const S: &'static mut str = &mut " hello ";
+ | ^^^^^^^^^^^^^^
+ |
+ = note: see issue #57349 <https://github.com/rust-lang/rust/issues/57349> for more information
+ = help: add `#![feature(const_mut_refs)]` to the crate attributes to enable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+ --> $DIR/issue-76510.rs:5:29
+ |
+LL | const S: &'static mut str = &mut " hello ";
+ | ^^^^^^^^^^^^^^ cannot borrow as mutable
+
+error[E0080]: evaluation of constant value failed
+ --> $DIR/issue-76510.rs:11:70
+ |
+LL | let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
+ | ^ referenced constant has errors
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0080, E0596, E0658, E0764.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/const-mut-refs/issue-76510.rs b/src/test/ui/consts/const-mut-refs/issue-76510.rs
new file mode 100644
index 000000000..08cf64ee3
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/issue-76510.rs
@@ -0,0 +1,18 @@
+// stderr-per-bitwidth
+
+use std::mem::{transmute, ManuallyDrop};
+
+const S: &'static mut str = &mut " hello ";
+//~^ ERROR: mutable references are not allowed in the final value of constants
+//~| ERROR: mutation through a reference is not allowed in constants
+//~| ERROR: cannot borrow data in a `&` reference as mutable
+
+const fn trigger() -> [(); unsafe {
+ let s = transmute::<(*const u8, usize), &ManuallyDrop<str>>((S.as_ptr(), 3));
+ //~^ ERROR evaluation of constant value failed
+ 0
+ }] {
+ [(); 0]
+}
+
+fn main() {}
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
new file mode 100644
index 000000000..a7d329f12
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.rs
@@ -0,0 +1,55 @@
+#![feature(const_mut_refs)]
+#![feature(raw_ref_op)]
+
+const NULL: *mut i32 = std::ptr::null_mut();
+const A: *const i32 = &4;
+
+// It could be made sound to allow it to compile,
+// but we do not want to allow this to compile,
+// 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(x: &mut i32) -> Option<&mut i32> { Some(x) }
+const B4: Option<&mut i32> = helper(&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 = &{
+ let mut x = 42;
+ x += 3;
+ x
+};
+
+use std::cell::UnsafeCell;
+struct NotAMutex<T>(UnsafeCell<T>);
+
+unsafe impl<T> Sync for NotAMutex<T> {}
+
+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
new file mode 100644
index 000000000..3a9ce79f1
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final.stderr
@@ -0,0 +1,60 @@
+error[E0764]: mutable references are not allowed in the final value of constants
+ --> $DIR/mut_ref_in_final.rs:10:21
+ |
+LL | const B: *mut i32 = &mut 4;
+ | ^^^^^^
+
+error[E0716]: temporary value dropped while borrowed
+ --> $DIR/mut_ref_in_final.rs:16: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:19:42
+ |
+LL | const B4: Option<&mut i32> = helper(&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:34: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:37: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:40: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
+
+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_dynamic_check.rs b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs
new file mode 100644
index 000000000..074beaab2
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.rs
@@ -0,0 +1,27 @@
+#![feature(const_mut_refs)]
+#![feature(raw_ref_op)]
+
+// This file checks that our dynamic checks catch things that the static checks miss.
+// We do not have static checks for these, because 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 B4/helper test in
+// mut_ref_in_final.rs).
+
+const fn helper() -> Option<&'static mut i32> { unsafe {
+ // Undefined behaviour (integer as pointer), 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)) //~ ERROR evaluation of constant value failed
+ //~| 0x2a[noalloc] is a dangling pointer
+} }
+// The error is an evaluation error and not a validation error, so the error is reported
+// directly at the site where it occurs.
+const A: Option<&mut i32> = helper();
+
+const fn helper2() -> Option<&'static mut i32> { unsafe {
+ // Undefined behaviour (dangling pointer), who doesn't love tests like this.
+ // This code never gets executed, because the static checks fail before that.
+ Some(&mut *(&mut 42 as *mut i32))
+} }
+const B: Option<&mut i32> = helper2(); //~ ERROR encountered dangling pointer in final constant
+
+fn main() {}
diff --git a/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr
new file mode 100644
index 000000000..234e55e3a
--- /dev/null
+++ b/src/test/ui/consts/const-mut-refs/mut_ref_in_final_dynamic_check.stderr
@@ -0,0 +1,21 @@
+error[E0080]: evaluation of constant value failed
+ --> $DIR/mut_ref_in_final_dynamic_check.rs:13:10
+ |
+LL | Some(&mut *(42 as *mut i32))
+ | ^^^^^^^^^^^^^^^^^^^^^^
+ | |
+ | dereferencing pointer failed: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+ | inside `helper` at $DIR/mut_ref_in_final_dynamic_check.rs:13:10
+...
+LL | const A: Option<&mut i32> = helper();
+ | -------- inside `A` at $DIR/mut_ref_in_final_dynamic_check.rs:18:29
+
+error: encountered dangling pointer in final constant
+ --> $DIR/mut_ref_in_final_dynamic_check.rs:25:1
+ |
+LL | const B: Option<&mut i32> = helper2();
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0080`.