From 90004f06d18f4658881230c675974cce0b631653 Mon Sep 17 00:00:00 2001
From: Camelid <camelidcamel@gmail.com>
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() {}