Skip to content

Commit

Permalink
Visit patterns in THIR let expressions
Browse files Browse the repository at this point in the history
This fixes some THIR unsafety checking errors not being emitted for
let expressions in these situations.
  • Loading branch information
matthewjasper committed Nov 2, 2023
1 parent 9752fd7 commit 8afbe84
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 38 deletions.
3 changes: 2 additions & 1 deletion compiler/rustc_middle/src/thir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,9 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
Use { source } => visitor.visit_expr(&visitor.thir()[source]),
NeverToAny { source } => visitor.visit_expr(&visitor.thir()[source]),
PointerCoercion { source, cast: _ } => visitor.visit_expr(&visitor.thir()[source]),
Let { expr, .. } => {
Let { expr, ref pat } => {
visitor.visit_expr(&visitor.thir()[expr]);
visitor.visit_pat(pat);
}
Loop { body } => visitor.visit_expr(&visitor.thir()[body]),
Match { scrutinee, ref arms, .. } => {
Expand Down
8 changes: 0 additions & 8 deletions compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -492,14 +492,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
}
}
}
ExprKind::Let { expr: expr_id, .. } => {
let let_expr = &self.thir[expr_id];
if let ty::Adt(adt_def, _) = let_expr.ty.kind()
&& adt_def.is_union()
{
self.requires_unsafe(expr.span, AccessToUnionField);
}
}
_ => {}
}
visit::walk_expr(self, expr);
Expand Down
28 changes: 18 additions & 10 deletions tests/ui/union/union-unsafe.mir.stderr
Original file line number Diff line number Diff line change
@@ -1,75 +1,83 @@
error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:33:5
--> $DIR/union-unsafe.rs:34:5
|
LL | *(u.p) = 13;
| ^^^^^^^^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:46:6
--> $DIR/union-unsafe.rs:47:6
|
LL | *u3.a = T::default();
| ^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:52:6
--> $DIR/union-unsafe.rs:53:6
|
LL | *u3.a = T::default();
| ^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:60:13
--> $DIR/union-unsafe.rs:61:13
|
LL | let a = u1.a;
| ^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:63:14
--> $DIR/union-unsafe.rs:64:14
|
LL | let U1 { a } = u1;
| ^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:64:12
--> $DIR/union-unsafe.rs:65:12
|
LL | if let U1 { a: 12 } = u1 {}
| ^^^^^^^^^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:69:6
--> $DIR/union-unsafe.rs:66:12
|
LL | if let Some(U1 { a: 13 }) = Some(u1) {}
| ^^^^^^^^^^^^^^^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:71:6
|
LL | *u2.a = String::from("new");
| ^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:73:6
--> $DIR/union-unsafe.rs:75:6
|
LL | *u3.a = 1;
| ^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:77:6
--> $DIR/union-unsafe.rs:79:6
|
LL | *u3.a = String::from("new");
| ^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error: aborting due to 9 previous errors
error: aborting due to 10 previous errors

For more information about this error, try `rustc --explain E0133`.
14 changes: 8 additions & 6 deletions tests/ui/union/union-unsafe.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,31 @@
// revisions: mir thir
// [thir]compile-flags: -Z thir-unsafeck

use std::mem::ManuallyDrop;
use std::cell::RefCell;
use std::mem::ManuallyDrop;

union U1 {
a: u8
a: u8,
}

union U2 {
a: ManuallyDrop<String>
a: ManuallyDrop<String>,
}

union U3<T> {
a: ManuallyDrop<T>
a: ManuallyDrop<T>,
}

union U4<T: Copy> {
a: T
a: T,
}

union URef {
p: &'static mut i32,
}

union URefCell { // field that does not drop but is not `Copy`, either
union URefCell {
// field that does not drop but is not `Copy`, either
a: (ManuallyDrop<RefCell<i32>>, i32),
}

Expand Down Expand Up @@ -62,6 +63,7 @@ fn main() {

let U1 { a } = u1; //~ ERROR access to union field is unsafe
if let U1 { a: 12 } = u1 {} //~ ERROR access to union field is unsafe
if let Some(U1 { a: 13 }) = Some(u1) {} //~ ERROR access to union field is unsafe
// let U1 { .. } = u1; // OK

let mut u2 = U2 { a: ManuallyDrop::new(String::from("old")) }; // OK
Expand Down
30 changes: 19 additions & 11 deletions tests/ui/union/union-unsafe.thir.stderr
Original file line number Diff line number Diff line change
@@ -1,75 +1,83 @@
error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:33:6
--> $DIR/union-unsafe.rs:34:6
|
LL | *(u.p) = 13;
| ^^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:46:6
--> $DIR/union-unsafe.rs:47:6
|
LL | *u3.a = T::default();
| ^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:52:6
--> $DIR/union-unsafe.rs:53:6
|
LL | *u3.a = T::default();
| ^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:60:13
--> $DIR/union-unsafe.rs:61:13
|
LL | let a = u1.a;
| ^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:63:14
--> $DIR/union-unsafe.rs:64:14
|
LL | let U1 { a } = u1;
| ^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:64:8
--> $DIR/union-unsafe.rs:65:20
|
LL | if let U1 { a: 12 } = u1 {}
| ^^^^^^^^^^^^^^^^^^^^^ access to union field
| ^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:69:6
--> $DIR/union-unsafe.rs:66:25
|
LL | if let Some(U1 { a: 13 }) = Some(u1) {}
| ^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:71:6
|
LL | *u2.a = String::from("new");
| ^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:73:6
--> $DIR/union-unsafe.rs:75:6
|
LL | *u3.a = 1;
| ^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error[E0133]: access to union field is unsafe and requires unsafe function or block
--> $DIR/union-unsafe.rs:77:6
--> $DIR/union-unsafe.rs:79:6
|
LL | *u3.a = String::from("new");
| ^^^^ access to union field
|
= note: the field may not be properly initialized: using uninitialized data will cause undefined behavior

error: aborting due to 9 previous errors
error: aborting due to 10 previous errors

For more information about this error, try `rustc --explain E0133`.
10 changes: 9 additions & 1 deletion tests/ui/unsafe/ranged_ints2.mirunsafeck.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ LL | let y = &mut x.0;
|
= note: mutating layout constrained fields cannot statically be checked for valid values

error: aborting due to previous error
error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
--> $DIR/ranged_ints2.rs:12:25
|
LL | if let Some(NonZero(ref mut y)) = Some(x) {}
| ^^^^^^^^^ mutation of layout constrained field
|
= note: mutating layout constrained fields cannot statically be checked for valid values

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0133`.
1 change: 1 addition & 0 deletions tests/ui/unsafe/ranged_ints2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ pub(crate) struct NonZero<T>(pub(crate) T);
fn main() {
let mut x = unsafe { NonZero(1) };
let y = &mut x.0; //~ ERROR mutation of layout constrained field is unsafe
if let Some(NonZero(ref mut y)) = Some(x) {} //~ ERROR mutation of layout constrained field is unsafe
}
10 changes: 9 additions & 1 deletion tests/ui/unsafe/ranged_ints2.thirunsafeck.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,14 @@ LL | let y = &mut x.0;
|
= note: mutating layout constrained fields cannot statically be checked for valid values

error: aborting due to previous error
error[E0133]: mutation of layout constrained field is unsafe and requires unsafe function or block
--> $DIR/ranged_ints2.rs:12:25
|
LL | if let Some(NonZero(ref mut y)) = Some(x) {}
| ^^^^^^^^^ mutation of layout constrained field
|
= note: mutating layout constrained fields cannot statically be checked for valid values

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0133`.

0 comments on commit 8afbe84

Please sign in to comment.