From 90004f06d18f4658881230c675974cce0b631653 Mon Sep 17 00:00:00 2001 From: Camelid Date: Fri, 8 Jan 2021 14:03:44 -0800 Subject: [PATCH] unsafeck: Don't treat AscribeUserType as use Previously, if the MIR had an AscribeUserType statement that ascribed a type to the pointee of a raw pointer, it would be treated as a dereference of the raw pointer for purposes of unsafe-checking. For example, the following code would be treated as containing a raw-pointer dereference: fn foo(ptr: *const bool) { let _: bool = *ptr; } Producing this error: error[E0133]: dereference of raw pointer is unsafe and requires unsafe function or block --> issue-80059.rs:2:12 | 2 | let _: bool = *ptr; | ^^^^ dereference of raw pointer Note that the error points to the type ascription as having a dereference! That's because the generated AscribeUserType MIR statement is treated as containing a dereference of `_1`: AscribeUserType((*_1), +, UserTypeProjection { base: UserType(1), projs: [] }); Now the unsafe-checker ignores uses inside `AscribeUserType` statements, which means this code now compiles successfully. ----- Note that this code: fn foo(ptr: *const bool) { let _: bool = *ptr; } does *not* produce an error (it compiles fine) because of the magical behavior of the `_` (wildcard) pattern (see #80059). --- compiler/rustc_mir/src/transform/check_unsafety.rs | 9 ++++++++- src/test/ui/unsafe/wildcard-type-ascription.rs | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/unsafe/wildcard-type-ascription.rs diff --git a/compiler/rustc_mir/src/transform/check_unsafety.rs b/compiler/rustc_mir/src/transform/check_unsafety.rs index e64955c4986ce..4aa119e4da2e2 100644 --- a/compiler/rustc_mir/src/transform/check_unsafety.rs +++ b/compiler/rustc_mir/src/transform/check_unsafety.rs @@ -113,11 +113,18 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { | StatementKind::StorageLive(..) | StatementKind::StorageDead(..) | StatementKind::Retag { .. } - | StatementKind::AscribeUserType(..) | StatementKind::Coverage(..) | StatementKind::Nop => { // safe (at least as emitted during MIR construction) } + StatementKind::AscribeUserType(..) => { + // safe (at least as emitted during MIR construction) + // This is handled separately because we don't want + // super_statement to be called. + // See this for more: + // https://github.com/rust-lang/rust/issues/80059#issuecomment-756968485 + return; + } StatementKind::LlvmInlineAsm { .. } => self.require_unsafe( UnsafetyViolationKind::General, diff --git a/src/test/ui/unsafe/wildcard-type-ascription.rs b/src/test/ui/unsafe/wildcard-type-ascription.rs new file mode 100644 index 0000000000000..260d80a352ff9 --- /dev/null +++ b/src/test/ui/unsafe/wildcard-type-ascription.rs @@ -0,0 +1,7 @@ +// check-pass + +fn foo(ptr: *const bool) { + let _: bool = *ptr; +} + +fn main() {}