Visit patterns in THIR let expressions

This fixes some THIR unsafety checking errors not being emitted for
let expressions in these situations.
This commit is contained in:
Matthew Jasper 2023-10-31 15:47:18 +00:00
parent 2b59992736
commit 868de8e76b
8 changed files with 66 additions and 38 deletions

View File

@ -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, .. } => {

View File

@ -495,14 +495,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);

View File

@ -1,5 +1,5 @@
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
@ -7,7 +7,7 @@ LL | *(u.p) = 13;
= 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
@ -15,7 +15,7 @@ LL | *u3.a = T::default();
= 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
@ -23,7 +23,7 @@ LL | *u3.a = T::default();
= 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
@ -31,7 +31,7 @@ LL | let a = u1.a;
= 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
@ -39,7 +39,7 @@ LL | let U1 { a } = u1;
= 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
@ -47,7 +47,15 @@ LL | if let U1 { a: 12 } = u1 {}
= 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
@ -55,7 +63,7 @@ LL | *u2.a = String::from("new");
= 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
@ -63,13 +71,13 @@ LL | *u3.a = 1;
= 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`.

View File

@ -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),
}
@ -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

View File

@ -1,5 +1,5 @@
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
@ -7,7 +7,7 @@ LL | *(u.p) = 13;
= 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
@ -15,7 +15,7 @@ LL | *u3.a = T::default();
= 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
@ -23,7 +23,7 @@ LL | *u3.a = T::default();
= 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
@ -31,7 +31,7 @@ LL | let a = u1.a;
= 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
@ -39,15 +39,23 @@ LL | let U1 { a } = u1;
= 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
@ -55,7 +63,7 @@ LL | *u2.a = String::from("new");
= 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
@ -63,13 +71,13 @@ LL | *u3.a = 1;
= 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`.

View File

@ -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`.

View File

@ -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
}

View File

@ -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`.