From e8e9f6a32af51fab7aae62f3f551aa3be8ff1ba2 Mon Sep 17 00:00:00 2001
From: Michael Goulet <michael@errs.io>
Date: Thu, 19 Oct 2023 16:41:43 +0000
Subject: [PATCH] Uplift movability and mutability, the simple way

---
 Cargo.lock                              |  1 +
 compiler/rustc_ast/Cargo.toml           |  2 +
 compiler/rustc_ast/src/ast.rs           | 63 +------------------
 compiler/rustc_ast/src/lib.rs           |  4 +-
 compiler/rustc_middle/src/ty/context.rs |  8 +--
 compiler/rustc_type_ir/src/lib.rs       |  5 +-
 compiler/rustc_type_ir/src/sty.rs       | 84 ++++++++++++++++++++-----
 7 files changed, 79 insertions(+), 88 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index aa2f9c4147e..9d7e5ee4f92 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3419,6 +3419,7 @@ dependencies = [
  "rustc_macros",
  "rustc_serialize",
  "rustc_span",
+ "rustc_type_ir",
  "smallvec",
  "thin-vec",
  "tracing",
diff --git a/compiler/rustc_ast/Cargo.toml b/compiler/rustc_ast/Cargo.toml
index f0632ac92e9..e0948471acb 100644
--- a/compiler/rustc_ast/Cargo.toml
+++ b/compiler/rustc_ast/Cargo.toml
@@ -14,6 +14,8 @@ rustc_lexer = { path = "../rustc_lexer" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_serialize = { path = "../rustc_serialize" }
 rustc_span = { path = "../rustc_span" }
+# depends on Mutability and Movability, which could be uplifted into a common crate.
+rustc_type_ir = { path = "../rustc_type_ir" }
 smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
 thin-vec = "0.2.12"
 tracing = "0.1"
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index e8cbd7b69fb..e94e26a63bc 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -34,6 +34,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{ErrorGuaranteed, Span, DUMMY_SP};
+pub use rustc_type_ir::{Movability, Mutability};
 use std::fmt;
 use std::mem;
 use thin_vec::{thin_vec, ThinVec};
@@ -800,57 +801,6 @@ pub enum PatKind {
     MacCall(P<MacCall>),
 }
 
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
-#[derive(HashStable_Generic, Encodable, Decodable)]
-pub enum Mutability {
-    // N.B. Order is deliberate, so that Not < Mut
-    Not,
-    Mut,
-}
-
-impl Mutability {
-    pub fn invert(self) -> Self {
-        match self {
-            Mutability::Mut => Mutability::Not,
-            Mutability::Not => Mutability::Mut,
-        }
-    }
-
-    /// Returns `""` (empty string) or `"mut "` depending on the mutability.
-    pub fn prefix_str(self) -> &'static str {
-        match self {
-            Mutability::Mut => "mut ",
-            Mutability::Not => "",
-        }
-    }
-
-    /// Returns `"&"` or `"&mut "` depending on the mutability.
-    pub fn ref_prefix_str(self) -> &'static str {
-        match self {
-            Mutability::Not => "&",
-            Mutability::Mut => "&mut ",
-        }
-    }
-
-    /// Returns `""` (empty string) or `"mutably "` depending on the mutability.
-    pub fn mutably_str(self) -> &'static str {
-        match self {
-            Mutability::Not => "",
-            Mutability::Mut => "mutably ",
-        }
-    }
-
-    /// Return `true` if self is mutable
-    pub fn is_mut(self) -> bool {
-        matches!(self, Self::Mut)
-    }
-
-    /// Return `true` if self is **not** mutable
-    pub fn is_not(self) -> bool {
-        matches!(self, Self::Not)
-    }
-}
-
 /// The kind of borrow in an `AddrOf` expression,
 /// e.g., `&place` or `&raw const place`.
 #[derive(Clone, Copy, PartialEq, Eq, Debug)]
@@ -1579,17 +1529,6 @@ pub enum CaptureBy {
     Ref,
 }
 
-/// The movability of a generator / closure literal:
-/// whether a generator contains self-references, causing it to be `!Unpin`.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)]
-#[derive(HashStable_Generic)]
-pub enum Movability {
-    /// May contain self-references, `!Unpin`.
-    Static,
-    /// Must not contain self-references, `Unpin`.
-    Movable,
-}
-
 /// Closure lifetime binder, `for<'a, 'b>` in `for<'a, 'b> |_: &'a (), _: &'b ()|`.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub enum ClosureBinder {
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index ddc7c8ee825..ada5c95dc34 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -60,7 +60,9 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 /// Requirements for a `StableHashingContext` to be used in this crate.
 /// This is a hack to allow using the `HashStable_Generic` derive macro
 /// instead of implementing everything in `rustc_middle`.
-pub trait HashStableContext: rustc_span::HashStableContext {
+pub trait HashStableContext:
+    rustc_type_ir::HashStableContext + rustc_span::HashStableContext
+{
     fn hash_attr(&mut self, _: &ast::Attribute, hasher: &mut StableHasher);
 }
 
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 82c7f8ab486..cad3aac23d8 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -88,8 +88,6 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
     type Predicate = Predicate<'tcx>;
     type PredicateKind = ty::PredicateKind<'tcx>;
     type TypeAndMut = TypeAndMut<'tcx>;
-    type Mutability = hir::Mutability;
-    type Movability = hir::Movability;
     type Ty = Ty<'tcx>;
     type Tys = &'tcx List<Ty<'tcx>>;
     type AliasTy = ty::AliasTy<'tcx>;
@@ -118,13 +116,9 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
 
     fn ty_and_mut_to_parts(
         TypeAndMut { ty, mutbl }: TypeAndMut<'tcx>,
-    ) -> (Self::Ty, Self::Mutability) {
+    ) -> (Self::Ty, ty::Mutability) {
         (ty, mutbl)
     }
-
-    fn mutability_is_mut(mutbl: Self::Mutability) -> bool {
-        mutbl.is_mut()
-    }
 }
 
 type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 6b1f0bae91a..0a35e8d3a90 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -59,8 +59,6 @@ pub trait Interner: Sized {
     type PredicateKind: Clone + Debug + Hash + PartialEq + Eq;
 
     type TypeAndMut: Clone + Debug + Hash + Ord;
-    type Mutability: Clone + Debug + Hash + Ord;
-    type Movability: Clone + Debug + Hash + Ord;
 
     // Kinds of tys
     type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord;
@@ -95,8 +93,7 @@ pub trait Interner: Sized {
     type InferRegion: Clone + DebugWithInfcx<Self> + Hash + Ord;
     type PlaceholderRegion: Clone + Debug + Hash + Ord;
 
-    fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Self::Mutability);
-    fn mutability_is_mut(mutbl: Self::Mutability) -> bool;
+    fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability);
 }
 
 /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index 991b8e1589b..5ca77701eb0 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -18,6 +18,68 @@ use self::TyKind::*;
 use rustc_data_structures::stable_hasher::HashStable;
 use rustc_serialize::{Decodable, Decoder, Encodable};
 
+/// The movability of a generator / closure literal:
+/// whether a generator contains self-references, causing it to be `!Unpin`.
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)]
+#[derive(HashStable_Generic)]
+pub enum Movability {
+    /// May contain self-references, `!Unpin`.
+    Static,
+    /// Must not contain self-references, `Unpin`.
+    Movable,
+}
+
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
+#[derive(HashStable_Generic, Encodable, Decodable)]
+pub enum Mutability {
+    // N.B. Order is deliberate, so that Not < Mut
+    Not,
+    Mut,
+}
+
+impl Mutability {
+    pub fn invert(self) -> Self {
+        match self {
+            Mutability::Mut => Mutability::Not,
+            Mutability::Not => Mutability::Mut,
+        }
+    }
+
+    /// Returns `""` (empty string) or `"mut "` depending on the mutability.
+    pub fn prefix_str(self) -> &'static str {
+        match self {
+            Mutability::Mut => "mut ",
+            Mutability::Not => "",
+        }
+    }
+
+    /// Returns `"&"` or `"&mut "` depending on the mutability.
+    pub fn ref_prefix_str(self) -> &'static str {
+        match self {
+            Mutability::Not => "&",
+            Mutability::Mut => "&mut ",
+        }
+    }
+
+    /// Returns `""` (empty string) or `"mutably "` depending on the mutability.
+    pub fn mutably_str(self) -> &'static str {
+        match self {
+            Mutability::Not => "",
+            Mutability::Mut => "mutably ",
+        }
+    }
+
+    /// Return `true` if self is mutable
+    pub fn is_mut(self) -> bool {
+        matches!(self, Self::Mut)
+    }
+
+    /// Return `true` if self is **not** mutable
+    pub fn is_not(self) -> bool {
+        matches!(self, Self::Not)
+    }
+}
+
 /// Specifies how a trait object is represented.
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
 #[derive(Encodable, Decodable, HashStable_Generic)]
@@ -98,7 +160,7 @@ pub enum TyKind<I: Interner> {
 
     /// A reference; a pointer with an associated lifetime. Written as
     /// `&'a mut T` or `&'a T`.
-    Ref(I::Region, I::Ty, I::Mutability),
+    Ref(I::Region, I::Ty, Mutability),
 
     /// The anonymous type of a function declaration/definition. Each
     /// function has a unique type.
@@ -141,7 +203,7 @@ pub enum TyKind<I: Interner> {
     ///
     /// For more info about generator args, visit the documentation for
     /// `GeneratorArgs`.
-    Generator(I::DefId, I::GenericArgs, I::Movability),
+    Generator(I::DefId, I::GenericArgs, Movability),
 
     /// A type representing the types stored inside a generator.
     /// This should only appear as part of the `GeneratorArgs`.
@@ -506,15 +568,15 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
             Slice(t) => write!(f, "[{:?}]", &this.wrap(t)),
             RawPtr(p) => {
                 let (ty, mutbl) = I::ty_and_mut_to_parts(p.clone());
-                match I::mutability_is_mut(mutbl) {
-                    true => write!(f, "*mut "),
-                    false => write!(f, "*const "),
+                match mutbl {
+                    Mutability::Mut => write!(f, "*mut "),
+                    Mutability::Not => write!(f, "*const "),
                 }?;
                 write!(f, "{:?}", &this.wrap(ty))
             }
-            Ref(r, t, m) => match I::mutability_is_mut(m.clone()) {
-                true => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)),
-                false => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)),
+            Ref(r, t, m) => match m {
+                Mutability::Mut => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)),
+                Mutability::Not => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)),
             },
             FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, &this.wrap(s)),
             FnPtr(s) => write!(f, "{:?}", &this.wrap(s)),
@@ -573,8 +635,6 @@ where
     I::Const: Encodable<E>,
     I::Region: Encodable<E>,
     I::TypeAndMut: Encodable<E>,
-    I::Mutability: Encodable<E>,
-    I::Movability: Encodable<E>,
     I::PolyFnSig: Encodable<E>,
     I::BoundExistentialPredicates: Encodable<E>,
     I::Tys: Encodable<E>,
@@ -687,8 +747,6 @@ where
     I::Const: Decodable<D>,
     I::Region: Decodable<D>,
     I::TypeAndMut: Decodable<D>,
-    I::Mutability: Decodable<D>,
-    I::Movability: Decodable<D>,
     I::PolyFnSig: Decodable<D>,
     I::BoundExistentialPredicates: Decodable<D>,
     I::Tys: Decodable<D>,
@@ -753,8 +811,6 @@ where
     I::PolyFnSig: HashStable<CTX>,
     I::BoundExistentialPredicates: HashStable<CTX>,
     I::Region: HashStable<CTX>,
-    I::Movability: HashStable<CTX>,
-    I::Mutability: HashStable<CTX>,
     I::Tys: HashStable<CTX>,
     I::AliasTy: HashStable<CTX>,
     I::BoundTy: HashStable<CTX>,