summary refs log tree commit diff
path: root/compiler/rustc_pattern_analysis/src
diff options
context:
space:
mode:
authorLaurențiu Nicola <lnicola@dend.ro>2024-01-27 14:18:33 +0200
committerLaurențiu Nicola <lnicola@dend.ro>2024-01-27 14:21:01 +0200
commitf5c78955c88ac37b7422bef6ee9ec993c0a5dad2 (patch)
tree0e2612a47f528890d719a6f6d698d67b1e2a1412 /compiler/rustc_pattern_analysis/src
parent8b6a431b3d3066a54dffc7f16bf658cf5690efc9 (diff)
downloadrust-f5c78955c88ac37b7422bef6ee9ec993c0a5dad2.tar.gz
rust-f5c78955c88ac37b7422bef6ee9ec993c0a5dad2.zip
Stop using derivative in rustc_pattern_analysis
Diffstat (limited to 'compiler/rustc_pattern_analysis/src')
-rw-r--r--compiler/rustc_pattern_analysis/src/constructor.rs98
-rw-r--r--compiler/rustc_pattern_analysis/src/lib.rs20
-rw-r--r--compiler/rustc_pattern_analysis/src/pat.rs31
-rw-r--r--compiler/rustc_pattern_analysis/src/rustc.rs8
-rw-r--r--compiler/rustc_pattern_analysis/src/usefulness.rs58
5 files changed, 191 insertions, 24 deletions
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs
index e94a0373c79..4996015f863 100644
--- a/compiler/rustc_pattern_analysis/src/constructor.rs
+++ b/compiler/rustc_pattern_analysis/src/constructor.rs
@@ -151,6 +151,7 @@
 use std::cmp::{self, max, min, Ordering};
 use std::fmt;
 use std::iter::once;
+use std::mem;
 
 use smallvec::SmallVec;
 
@@ -648,8 +649,6 @@ impl OpaqueId {
 /// `specialize_constructor` returns the list of fields corresponding to a pattern, given a
 /// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and
 /// `Fields`.
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = ""), Clone(bound = ""), PartialEq(bound = ""))]
 pub enum Constructor<Cx: TypeCx> {
     /// Tuples and structs.
     Struct,
@@ -692,6 +691,101 @@ pub enum Constructor<Cx: TypeCx> {
     Missing,
 }
 
+impl<Cx: TypeCx> Clone for Constructor<Cx> {
+    fn clone(&self) -> Self {
+        match self {
+            Constructor::Struct => Constructor::Struct,
+            Constructor::Variant(idx) => Constructor::Variant(idx.clone()),
+            Constructor::Ref => Constructor::Ref,
+            Constructor::Slice(slice) => Constructor::Slice(slice.clone()),
+            Constructor::UnionField => Constructor::UnionField,
+            Constructor::Bool(b) => Constructor::Bool(b.clone()),
+            Constructor::IntRange(range) => Constructor::IntRange(range.clone()),
+            Constructor::F32Range(lo, hi, end) => {
+                Constructor::F32Range(lo.clone(), hi.clone(), end.clone())
+            }
+            Constructor::F64Range(lo, hi, end) => {
+                Constructor::F64Range(lo.clone(), hi.clone(), end.clone())
+            }
+            Constructor::Str(value) => Constructor::Str(value.clone()),
+            Constructor::Opaque(inner) => Constructor::Opaque(inner.clone()),
+            Constructor::Or => Constructor::Or,
+            Constructor::Wildcard => Constructor::Wildcard,
+            Constructor::NonExhaustive => Constructor::NonExhaustive,
+            Constructor::Hidden => Constructor::Hidden,
+            Constructor::Missing => Constructor::Missing,
+        }
+    }
+}
+
+impl<Cx: TypeCx> fmt::Debug for Constructor<Cx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Constructor::Struct => f.debug_tuple("Struct").finish(),
+            Constructor::Variant(idx) => f.debug_tuple("Variant").field(idx).finish(),
+            Constructor::Ref => f.debug_tuple("Ref").finish(),
+            Constructor::Slice(slice) => f.debug_tuple("Slice").field(slice).finish(),
+            Constructor::UnionField => f.debug_tuple("UnionField").finish(),
+            Constructor::Bool(b) => f.debug_tuple("Bool").field(b).finish(),
+            Constructor::IntRange(range) => f.debug_tuple("IntRange").field(range).finish(),
+            Constructor::F32Range(lo, hi, end) => {
+                f.debug_tuple("F32Range").field(lo).field(hi).field(end).finish()
+            }
+            Constructor::F64Range(lo, hi, end) => {
+                f.debug_tuple("F64Range").field(lo).field(hi).field(end).finish()
+            }
+            Constructor::Str(value) => f.debug_tuple("Str").field(value).finish(),
+            Constructor::Opaque(inner) => f.debug_tuple("Opaque").field(inner).finish(),
+            Constructor::Or => f.debug_tuple("Or").finish(),
+            Constructor::Wildcard => f.debug_tuple("Wildcard").finish(),
+            Constructor::NonExhaustive => f.debug_tuple("NonExhaustive").finish(),
+            Constructor::Hidden => f.debug_tuple("Hidden").finish(),
+            Constructor::Missing => f.debug_tuple("Missing").finish(),
+        }
+    }
+}
+
+impl<Cx: TypeCx> PartialEq for Constructor<Cx> {
+    fn eq(&self, other: &Self) -> bool {
+        (mem::discriminant(self) == mem::discriminant(other))
+            && match (self, other) {
+                (Constructor::Struct, Constructor::Struct) => true,
+                (Constructor::Variant(self_variant), Constructor::Variant(other_variant)) => {
+                    self_variant == other_variant
+                }
+                (Constructor::Ref, Constructor::Ref) => true,
+                (Constructor::Slice(self_slice), Constructor::Slice(other_slice)) => {
+                    self_slice == other_slice
+                }
+                (Constructor::UnionField, Constructor::UnionField) => true,
+                (Constructor::Bool(self_b), Constructor::Bool(other_b)) => self_b == other_b,
+                (Constructor::IntRange(self_range), Constructor::IntRange(other_range)) => {
+                    self_range == other_range
+                }
+                (
+                    Constructor::F32Range(self_lo, self_hi, self_end),
+                    Constructor::F32Range(other_lo, other_hi, other_end),
+                ) => self_lo == other_lo && self_hi == other_hi && self_end == other_end,
+                (
+                    Constructor::F64Range(self_lo, self_hi, self_end),
+                    Constructor::F64Range(other_lo, other_hi, other_end),
+                ) => self_lo == other_lo && self_hi == other_hi && self_end == other_end,
+                (Constructor::Str(self_value), Constructor::Str(other_value)) => {
+                    self_value == other_value
+                }
+                (Constructor::Opaque(self_inner), Constructor::Opaque(other_inner)) => {
+                    self_inner == other_inner
+                }
+                (Constructor::Or, Constructor::Or) => true,
+                (Constructor::Wildcard, Constructor::Wildcard) => true,
+                (Constructor::NonExhaustive, Constructor::NonExhaustive) => true,
+                (Constructor::Hidden, Constructor::Hidden) => true,
+                (Constructor::Missing, Constructor::Missing) => true,
+                _ => unreachable!(),
+            }
+    }
+}
+
 impl<Cx: TypeCx> Constructor<Cx> {
     pub(crate) fn is_non_exhaustive(&self) -> bool {
         matches!(self, NonExhaustive)
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs
index 6374874165f..a53d7a0d809 100644
--- a/compiler/rustc_pattern_analysis/src/lib.rs
+++ b/compiler/rustc_pattern_analysis/src/lib.rs
@@ -136,23 +136,35 @@ pub trait TypeCx: Sized + fmt::Debug {
 }
 
 /// Context that provides information global to a match.
-#[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Copy(bound = ""))]
 pub struct MatchCtxt<'a, Cx: TypeCx> {
     /// The context for type information.
     pub tycx: &'a Cx,
 }
 
+impl<'a, Cx: TypeCx> Clone for MatchCtxt<'a, Cx> {
+    fn clone(&self) -> Self {
+        Self { tycx: self.tycx }
+    }
+}
+
+impl<'a, Cx: TypeCx> Copy for MatchCtxt<'a, Cx> {}
+
 /// The arm of a match expression.
 #[derive(Debug)]
-#[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Copy(bound = ""))]
 pub struct MatchArm<'p, Cx: TypeCx> {
     pub pat: &'p DeconstructedPat<'p, Cx>,
     pub has_guard: bool,
     pub arm_data: Cx::ArmData,
 }
 
+impl<'p, Cx: TypeCx> Clone for MatchArm<'p, Cx> {
+    fn clone(&self) -> Self {
+        Self { pat: self.pat, has_guard: self.has_guard, arm_data: self.arm_data }
+    }
+}
+
+impl<'p, Cx: TypeCx> Copy for MatchArm<'p, Cx> {}
+
 /// The entrypoint for this crate. Computes whether a match is exhaustive and which of its arms are
 /// useful, and runs some lints.
 #[cfg(feature = "rustc")]
diff --git a/compiler/rustc_pattern_analysis/src/pat.rs b/compiler/rustc_pattern_analysis/src/pat.rs
index 1cc31074556..d476766d466 100644
--- a/compiler/rustc_pattern_analysis/src/pat.rs
+++ b/compiler/rustc_pattern_analysis/src/pat.rs
@@ -218,8 +218,6 @@ impl<'p, Cx: TypeCx> fmt::Debug for DeconstructedPat<'p, Cx> {
 /// algorithm. Do not use `Wild` to represent a wildcard pattern comping from user input.
 ///
 /// This is morally `Option<&'p DeconstructedPat>` where `None` is interpreted as a wildcard.
-#[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Copy(bound = ""))]
 pub(crate) enum PatOrWild<'p, Cx: TypeCx> {
     /// A non-user-provided wildcard, created during specialization.
     Wild,
@@ -227,6 +225,17 @@ pub(crate) enum PatOrWild<'p, Cx: TypeCx> {
     Pat(&'p DeconstructedPat<'p, Cx>),
 }
 
+impl<'p, Cx: TypeCx> Clone for PatOrWild<'p, Cx> {
+    fn clone(&self) -> Self {
+        match self {
+            PatOrWild::Wild => PatOrWild::Wild,
+            PatOrWild::Pat(pat) => PatOrWild::Pat(pat),
+        }
+    }
+}
+
+impl<'p, Cx: TypeCx> Copy for PatOrWild<'p, Cx> {}
+
 impl<'p, Cx: TypeCx> PatOrWild<'p, Cx> {
     pub(crate) fn as_pat(&self) -> Option<&'p DeconstructedPat<'p, Cx>> {
         match self {
@@ -289,14 +298,28 @@ impl<'p, Cx: TypeCx> fmt::Debug for PatOrWild<'p, Cx> {
 
 /// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics
 /// purposes. As such they don't use interning and can be cloned.
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = ""), Clone(bound = ""))]
 pub struct WitnessPat<Cx: TypeCx> {
     ctor: Constructor<Cx>,
     pub(crate) fields: Vec<WitnessPat<Cx>>,
     ty: Cx::Ty,
 }
 
+impl<Cx: TypeCx> Clone for WitnessPat<Cx> {
+    fn clone(&self) -> Self {
+        Self { ctor: self.ctor.clone(), fields: self.fields.clone(), ty: self.ty.clone() }
+    }
+}
+
+impl<Cx: TypeCx> fmt::Debug for WitnessPat<Cx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_struct("WitnessPat")
+            .field("ctor", &self.ctor)
+            .field("fields", &self.fields)
+            .field("ty", &self.ty)
+            .finish()
+    }
+}
+
 impl<Cx: TypeCx> WitnessPat<Cx> {
     pub(crate) fn new(ctor: Constructor<Cx>, fields: Vec<Self>, ty: Cx::Ty) -> Self {
         Self { ctor, fields, ty }
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index ef90d24b0bf..223d6cefc83 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -46,11 +46,15 @@ pub type WitnessPat<'p, 'tcx> = crate::pat::WitnessPat<RustcMatchCheckCtxt<'p, '
 ///
 /// Use `.inner()` or deref to get to the `Ty<'tcx>`.
 #[repr(transparent)]
-#[derive(derivative::Derivative)]
 #[derive(Clone, Copy)]
-#[derivative(Debug = "transparent")]
 pub struct RevealedTy<'tcx>(Ty<'tcx>);
 
+impl<'tcx> fmt::Debug for RevealedTy<'tcx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        self.0.fmt(fmt)
+    }
+}
+
 impl<'tcx> std::ops::Deref for RevealedTy<'tcx> {
     type Target = Ty<'tcx>;
     fn deref(&self) -> &Self::Target {
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs
index a627bdeef81..b15de1c0ca9 100644
--- a/compiler/rustc_pattern_analysis/src/usefulness.rs
+++ b/compiler/rustc_pattern_analysis/src/usefulness.rs
@@ -731,16 +731,26 @@ pub fn ensure_sufficient_stack<R>(f: impl FnOnce() -> R) -> R {
 }
 
 /// Context that provides information local to a place under investigation.
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = ""), Clone(bound = ""), Copy(bound = ""))]
 pub(crate) struct PlaceCtxt<'a, Cx: TypeCx> {
-    #[derivative(Debug = "ignore")]
     pub(crate) mcx: MatchCtxt<'a, Cx>,
     /// Type of the place under investigation.
-    #[derivative(Clone(clone_with = "Clone::clone"))] // See rust-derivative#90
     pub(crate) ty: &'a Cx::Ty,
 }
 
+impl<'a, Cx: TypeCx> Clone for PlaceCtxt<'a, Cx> {
+    fn clone(&self) -> Self {
+        Self { mcx: self.mcx, ty: self.ty }
+    }
+}
+
+impl<'a, Cx: TypeCx> Copy for PlaceCtxt<'a, Cx> {}
+
+impl<'a, Cx: TypeCx> fmt::Debug for PlaceCtxt<'a, Cx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_struct("PlaceCtxt").field("ty", self.ty).finish()
+    }
+}
+
 impl<'a, Cx: TypeCx> PlaceCtxt<'a, Cx> {
     /// A `PlaceCtxt` when code other than `is_useful` needs one.
     #[cfg_attr(not(feature = "rustc"), allow(dead_code))]
@@ -813,8 +823,6 @@ impl fmt::Display for ValidityConstraint {
 // The three lifetimes are:
 // - 'p coming from the input
 // - Cx global compilation context
-#[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""))]
 struct PatStack<'p, Cx: TypeCx> {
     // Rows of len 1 are very common, which is why `SmallVec[_; 2]` works well.
     pats: SmallVec<[PatOrWild<'p, Cx>; 2]>,
@@ -824,6 +832,12 @@ struct PatStack<'p, Cx: TypeCx> {
     relevant: bool,
 }
 
+impl<'p, Cx: TypeCx> Clone for PatStack<'p, Cx> {
+    fn clone(&self) -> Self {
+        Self { pats: self.pats.clone(), relevant: self.relevant }
+    }
+}
+
 impl<'p, Cx: TypeCx> PatStack<'p, Cx> {
     fn from_pattern(pat: &'p DeconstructedPat<'p, Cx>) -> Self {
         PatStack { pats: smallvec![PatOrWild::Pat(pat)], relevant: true }
@@ -1184,10 +1198,20 @@ impl<'p, Cx: TypeCx> fmt::Debug for Matrix<'p, Cx> {
 /// The final `Pair(Some(_), true)` is then the resulting witness.
 ///
 /// See the top of the file for more detailed explanations and examples.
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = ""), Clone(bound = ""))]
 struct WitnessStack<Cx: TypeCx>(Vec<WitnessPat<Cx>>);
 
+impl<Cx: TypeCx> Clone for WitnessStack<Cx> {
+    fn clone(&self) -> Self {
+        Self(self.0.clone())
+    }
+}
+
+impl<Cx: TypeCx> fmt::Debug for WitnessStack<Cx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple("WitnessStack").field(&self.0).finish()
+    }
+}
+
 impl<Cx: TypeCx> WitnessStack<Cx> {
     /// Asserts that the witness contains a single pattern, and returns it.
     fn single_pattern(self) -> WitnessPat<Cx> {
@@ -1232,18 +1256,28 @@ impl<Cx: TypeCx> WitnessStack<Cx> {
 ///
 /// Just as the `Matrix` starts with a single column, by the end of the algorithm, this has a single
 /// column, which contains the patterns that are missing for the match to be exhaustive.
-#[derive(derivative::Derivative)]
-#[derivative(Debug(bound = ""), Clone(bound = ""))]
 struct WitnessMatrix<Cx: TypeCx>(Vec<WitnessStack<Cx>>);
 
+impl<Cx: TypeCx> Clone for WitnessMatrix<Cx> {
+    fn clone(&self) -> Self {
+        Self(self.0.clone())
+    }
+}
+
+impl<Cx: TypeCx> fmt::Debug for WitnessMatrix<Cx> {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt.debug_tuple("WitnessMatrix").field(&self.0).finish()
+    }
+}
+
 impl<Cx: TypeCx> WitnessMatrix<Cx> {
     /// New matrix with no witnesses.
     fn empty() -> Self {
-        WitnessMatrix(vec![])
+        WitnessMatrix(Vec::new())
     }
     /// New matrix with one `()` witness, i.e. with no columns.
     fn unit_witness() -> Self {
-        WitnessMatrix(vec![WitnessStack(vec![])])
+        WitnessMatrix(vec![WitnessStack(Vec::new())])
     }
 
     /// Whether this has any witnesses.