about summary refs log tree commit diff
path: root/compiler
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2022-12-27 12:31:17 +0100
committerRalf Jung <post@ralfj.de>2023-02-06 11:46:32 +0100
commit201ae7387245caa4591d4c8db4c35c170c64faf0 (patch)
tree011ec2bc77cfee914cfab9d89b61c40232046986 /compiler
parent0c13c172507f01d921808107d2c4ec37b43b982d (diff)
downloadrust-201ae7387245caa4591d4c8db4c35c170c64faf0.tar.gz
rust-201ae7387245caa4591d4c8db4c35c170c64faf0.zip
make PointerKind directly reflect pointer types
The code that consumes PointerKind (`adjust_for_rust_scalar` in rustc_ty_utils)
ended up using PointerKind variants to talk about Rust reference types (& and
&mut) anyway, making the old code structure quite confusing: one always had to
keep in mind which PointerKind corresponds to which type. So this changes
PointerKind to directly reflect the type.

This does not change behavior.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/rustc_abi/src/lib.rs21
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs39
-rw-r--r--compiler/rustc_ty_utils/src/abi.rs33
3 files changed, 34 insertions, 59 deletions
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index 5af6206c0bb..9126c516d38 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -1439,21 +1439,12 @@ impl<V: Idx> fmt::Debug for LayoutS<V> {
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug)]
 pub enum PointerKind {
-    /// Most general case, we know no restrictions to tell LLVM.
-    SharedMutable,
-
-    /// `&T` where `T` contains no `UnsafeCell`, is `dereferenceable`, `noalias` and `readonly`.
-    Frozen,
-
-    /// `&mut T` which is `dereferenceable` and `noalias` but not `readonly`.
-    UniqueBorrowed,
-
-    /// `&mut !Unpin`, which is `dereferenceable` but neither `noalias` nor `readonly`.
-    UniqueBorrowedPinned,
-
-    /// `Box<T>`, which is `noalias` (even on return types, unlike the above) but neither `readonly`
-    /// nor `dereferenceable`.
-    UniqueOwned,
+    /// Shared reference. `frozen` indicates the absence of any `UnsafeCell`.
+    SharedRef { frozen: bool },
+    /// Mutable reference. `unpin` indicates the absence of any pinned data.
+    MutableRef { unpin: bool },
+    /// Box.
+    Box,
 }
 
 /// Note that this information is advisory only, and backends are free to ignore it.
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index cdcd6281f20..1244922c6d4 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -833,32 +833,17 @@ where
                     })
                 }
                 ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
-                    let kind = if tcx.sess.opts.optimize == OptLevel::No {
-                        // Use conservative pointer kind if not optimizing. This saves us the
-                        // Freeze/Unpin queries, and can save time in the codegen backend (noalias
-                        // attributes in LLVM have compile-time cost even in unoptimized builds).
-                        PointerKind::SharedMutable
-                    } else {
-                        match mt {
-                            hir::Mutability::Not => {
-                                if ty.is_freeze(tcx, cx.param_env()) {
-                                    PointerKind::Frozen
-                                } else {
-                                    PointerKind::SharedMutable
-                                }
-                            }
-                            hir::Mutability::Mut => {
-                                // References to self-referential structures should not be considered
-                                // noalias, as another pointer to the structure can be obtained, that
-                                // is not based-on the original reference. We consider all !Unpin
-                                // types to be potentially self-referential here.
-                                if ty.is_unpin(tcx, cx.param_env()) {
-                                    PointerKind::UniqueBorrowed
-                                } else {
-                                    PointerKind::UniqueBorrowedPinned
-                                }
-                            }
-                        }
+                    // Use conservative pointer kind if not optimizing. This saves us the
+                    // Freeze/Unpin queries, and can save time in the codegen backend (noalias
+                    // attributes in LLVM have compile-time cost even in unoptimized builds).
+                    let optimize = tcx.sess.opts.optimize != OptLevel::No;
+                    let kind = match mt {
+                        hir::Mutability::Not => PointerKind::SharedRef {
+                            frozen: optimize && ty.is_freeze(tcx, cx.param_env()),
+                        },
+                        hir::Mutability::Mut => PointerKind::MutableRef {
+                            unpin: optimize && ty.is_unpin(tcx, cx.param_env()),
+                        },
                     };
 
                     tcx.layout_of(param_env.and(ty)).ok().map(|layout| PointeeInfo {
@@ -929,7 +914,7 @@ where
                     if let Some(ref mut pointee) = result {
                         if let ty::Adt(def, _) = this.ty.kind() {
                             if def.is_box() && offset.bytes() == 0 {
-                                pointee.safe = Some(PointerKind::UniqueOwned);
+                                pointee.safe = Some(PointerKind::Box);
                             }
                         }
                     }
diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs
index 1c74aeca5ab..884087987ce 100644
--- a/compiler/rustc_ty_utils/src/abi.rs
+++ b/compiler/rustc_ty_utils/src/abi.rs
@@ -254,15 +254,15 @@ fn adjust_for_rust_scalar<'tcx>(
         if let Some(kind) = pointee.safe {
             attrs.pointee_align = Some(pointee.align);
 
-            // `Box` (`UniqueBorrowed`) are not necessarily dereferenceable
-            // for the entire duration of the function as they can be deallocated
-            // at any time. Same for shared mutable references. If LLVM had a
-            // way to say "dereferenceable on entry" we could use it here.
+            // `Box` are not necessarily dereferenceable for the entire duration of the function as
+            // they can be deallocated at any time. Same for non-frozen shared references (see
+            // <https://github.com/rust-lang/rust/pull/98017>). If LLVM had a way to say
+            // "dereferenceable on entry" we could use it here.
             attrs.pointee_size = match kind {
-                PointerKind::UniqueBorrowed
-                | PointerKind::UniqueBorrowedPinned
-                | PointerKind::Frozen => pointee.size,
-                PointerKind::SharedMutable | PointerKind::UniqueOwned => Size::ZERO,
+                PointerKind::Box | PointerKind::SharedRef { frozen: false } => Size::ZERO,
+                PointerKind::SharedRef { frozen: true } | PointerKind::MutableRef { .. } => {
+                    pointee.size
+                }
             };
 
             // The aliasing rules for `Box<T>` are still not decided, but currently we emit
@@ -278,15 +278,14 @@ fn adjust_for_rust_scalar<'tcx>(
             // `&mut` pointer parameters never alias other parameters,
             // or mutable global data
             //
-            // `&T` where `T` contains no `UnsafeCell<U>` is immutable,
-            // and can be marked as both `readonly` and `noalias`, as
-            // LLVM's definition of `noalias` is based solely on memory
-            // dependencies rather than pointer equality
+            // `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as both
+            // `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely on memory
+            // dependencies rather than pointer equality. However this only applies to arguments,
+            // not return values.
             let no_alias = match kind {
-                PointerKind::SharedMutable | PointerKind::UniqueBorrowedPinned => false,
-                PointerKind::UniqueBorrowed => noalias_mut_ref,
-                PointerKind::UniqueOwned => noalias_for_box,
-                PointerKind::Frozen => true,
+                PointerKind::SharedRef { frozen } => frozen,
+                PointerKind::MutableRef { unpin } => unpin && noalias_mut_ref,
+                PointerKind::Box => noalias_for_box,
             };
             // We can never add `noalias` in return position; that LLVM attribute has some very surprising semantics
             // (see <https://github.com/rust-lang/unsafe-code-guidelines/issues/385#issuecomment-1368055745>).
@@ -294,7 +293,7 @@ fn adjust_for_rust_scalar<'tcx>(
                 attrs.set(ArgAttribute::NoAlias);
             }
 
-            if kind == PointerKind::Frozen && !is_return {
+            if matches!(kind, PointerKind::SharedRef { frozen: true }) && !is_return {
                 attrs.set(ArgAttribute::ReadOnly);
             }
         }