about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-04-22 09:54:21 +0000
committerbors <bors@rust-lang.org>2023-04-22 09:54:21 +0000
commit21fab435da99d6ef14c1c870650ee976499564f3 (patch)
treeb95343fbae959c8db04ea9f9fcc6b0dc19bc24c0 /src
parentccb6290e437bdeccbd509795f00a2390dad1fbeb (diff)
parent2870d269f5eb26e77ccf7718080afc62edaca8da (diff)
Auto merge of #104844 - cjgillot:mention-eval-place, r=jackh726,RalfJung
Evaluate place expression in `PlaceMention`

https://github.com/rust-lang/rust/pull/102256 introduces a `PlaceMention(place)` MIR statement which keep trace of `let _ = place` statements from surface rust, but without semantics.

This PR proposes to change the behaviour of `let _ =` patterns with respect to the borrow-checker to verify that the bound place is live.

Specifically, consider this code:
```rust
let _ = {
    let a = 5;
    &a
};
```

This passes borrowck without error on stable. Meanwhile, replacing `_` by `_: _` or `_p` errors with "error[E0597]: `a` does not live long enough", [see playground](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=c448d25a7c205dc95a0967fe96bccce8).

This PR *does not* change how `_` patterns behave with respect to initializedness: it remains ok to bind a moved-from place to `_`.

The relevant test is `tests/ui/borrowck/let_underscore_temporary.rs`. Crater check found no regression.

For consistency, this PR changes miri to evaluate the place found in `PlaceMention`, and report eventual dangling pointers found within it.

r? `@RalfJung`
Diffstat (limited to 'src')
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.fixed4
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.rs4
-rw-r--r--src/tools/clippy/tests/ui/option_if_let_else.stderr8
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.rs13
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.stderr15
6 files changed, 37 insertions, 8 deletions
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.fixed b/src/tools/clippy/tests/ui/option_if_let_else.fixed
index 0456005dce4..35ce89c7986 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.fixed
+++ b/src/tools/clippy/tests/ui/option_if_let_else.fixed
@@ -25,7 +25,7 @@ fn else_if_option(string: Option<&str>) -> Option<(bool, &str)> {
 fn unop_bad(string: &Option<&str>, mut num: Option<i32>) {
     let _ = string.map_or(0, |s| s.len());
     let _ = num.as_ref().map_or(&0, |s| s);
-    let _ = num.as_mut().map_or(&mut 0, |s| {
+    let _ = num.as_mut().map_or(&0, |s| {
         *s += 1;
         s
     });
@@ -34,7 +34,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option<i32>) {
         s += 1;
         s
     });
-    let _ = num.as_mut().map_or(&mut 0, |s| {
+    let _ = num.as_mut().map_or(&0, |s| {
         *s += 1;
         s
     });
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.rs b/src/tools/clippy/tests/ui/option_if_let_else.rs
index 23b148752cb..c8683e5aae2 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.rs
+++ b/src/tools/clippy/tests/ui/option_if_let_else.rs
@@ -33,7 +33,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option<i32>) {
         *s += 1;
         s
     } else {
-        &mut 0
+        &0
     };
     let _ = if let Some(ref s) = num { s } else { &0 };
     let _ = if let Some(mut s) = num {
@@ -46,7 +46,7 @@ fn unop_bad(string: &Option<&str>, mut num: Option<i32>) {
         *s += 1;
         s
     } else {
-        &mut 0
+        &0
     };
 }
 
diff --git a/src/tools/clippy/tests/ui/option_if_let_else.stderr b/src/tools/clippy/tests/ui/option_if_let_else.stderr
index a5dbf6e1f22..f5e4affb672 100644
--- a/src/tools/clippy/tests/ui/option_if_let_else.stderr
+++ b/src/tools/clippy/tests/ui/option_if_let_else.stderr
@@ -30,13 +30,13 @@ LL |       let _ = if let Some(s) = &mut num {
 LL | |         *s += 1;
 LL | |         s
 LL | |     } else {
-LL | |         &mut 0
+LL | |         &0
 LL | |     };
    | |_____^
    |
 help: try
    |
-LL ~     let _ = num.as_mut().map_or(&mut 0, |s| {
+LL ~     let _ = num.as_mut().map_or(&0, |s| {
 LL +         *s += 1;
 LL +         s
 LL ~     });
@@ -76,13 +76,13 @@ LL |       let _ = if let Some(ref mut s) = num {
 LL | |         *s += 1;
 LL | |         s
 LL | |     } else {
-LL | |         &mut 0
+LL | |         &0
 LL | |     };
    | |_____^
    |
 help: try
    |
-LL ~     let _ = num.as_mut().map_or(&mut 0, |s| {
+LL ~     let _ = num.as_mut().map_or(&0, |s| {
 LL +         *s += 1;
 LL +         s
 LL ~     });
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index f67a718ba73..fc938080a0e 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -130,6 +130,7 @@ pub const MIRI_DEFAULT_ARGS: &[&str] = &[
     "-Zalways-encode-mir",
     "-Zextra-const-ub-checks",
     "-Zmir-emit-retag",
+    "-Zmir-keep-place-mention",
     "-Zmir-opt-level=0",
     "-Zmir-enable-passes=-CheckAlignment",
 ];
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.rs b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.rs
new file mode 100644
index 00000000000..7c5f440b774
--- /dev/null
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.rs
@@ -0,0 +1,13 @@
+// Make sure we find these even with many checks disabled.
+//@compile-flags: -Zmiri-disable-alignment-check -Zmiri-disable-stacked-borrows -Zmiri-disable-validation
+
+fn main() {
+    let p = {
+        let b = Box::new(42);
+        &*b as *const i32
+    };
+    unsafe {
+        let _ = *p; //~ ERROR: dereferenced after this allocation got freed
+    }
+    panic!("this should never print");
+}
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.stderr
new file mode 100644
index 00000000000..7b76389c753
--- /dev/null
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref_underscore.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: pointer to ALLOC was dereferenced after this allocation got freed
+  --> $DIR/dangling_pointer_deref_underscore.rs:LL:CC
+   |
+LL |         let _ = *p;
+   |                 ^^ pointer to ALLOC was dereferenced after this allocation got freed
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/dangling_pointer_deref_underscore.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+