diff options
Diffstat (limited to 'vendor/chalk-ir/src/debug.rs')
-rw-r--r-- | vendor/chalk-ir/src/debug.rs | 1016 |
1 files changed, 1016 insertions, 0 deletions
diff --git a/vendor/chalk-ir/src/debug.rs b/vendor/chalk-ir/src/debug.rs new file mode 100644 index 000000000..76d66edf5 --- /dev/null +++ b/vendor/chalk-ir/src/debug.rs @@ -0,0 +1,1016 @@ +//! Debug impls for types. + +use std::fmt::{self, Debug, Display, Error, Formatter}; + +use super::*; + +/// Wrapper to allow forwarding to `Display::fmt`, `Debug::fmt`, etc. +pub struct Fmt<F>(pub F) +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result; + +impl<F> fmt::Display for Fmt<F> +where + F: Fn(&mut fmt::Formatter<'_>) -> fmt::Result, +{ + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + (self.0)(f) + } +} + +impl<I: Interner> Debug for TraitId<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_trait_id(*self, fmt).unwrap_or_else(|| write!(fmt, "TraitId({:?})", self.0)) + } +} + +impl<I: Interner> Debug for AdtId<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_adt_id(*self, fmt).unwrap_or_else(|| write!(fmt, "AdtId({:?})", self.0)) + } +} + +impl<I: Interner> Debug for AssocTypeId<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_assoc_type_id(*self, fmt) + .unwrap_or_else(|| write!(fmt, "AssocTypeId({:?})", self.0)) + } +} + +impl<I: Interner> Debug for FnDefId<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result { + I::debug_fn_def_id(*self, fmt).unwrap_or_else(|| write!(fmt, "FnDefId({:?})", self.0)) + } +} + +impl<I: Interner> Debug for ClosureId<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result { + I::debug_closure_id(*self, fmt).unwrap_or_else(|| write!(fmt, "ClosureId({:?})", self.0)) + } +} + +impl<I: Interner> Debug for GeneratorId<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result { + I::debug_generator_id(*self, fmt) + .unwrap_or_else(|| write!(fmt, "GeneratorId({:?})", self.0)) + } +} + +impl<I: Interner> Debug for ForeignDefId<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> std::fmt::Result { + I::debug_foreign_def_id(*self, fmt) + .unwrap_or_else(|| write!(fmt, "ForeignDefId({:?})", self.0)) + } +} + +impl<I: Interner> Debug for Ty<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_ty(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned)) + } +} + +impl<I: Interner> Debug for Lifetime<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_lifetime(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned)) + } +} + +impl<I: Interner> Debug for Const<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_const(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned)) + } +} + +impl<I: Interner> Debug for ConcreteConst<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "{:?}", self.interned) + } +} + +impl<I: Interner> Debug for GenericArg<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_generic_arg(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned)) + } +} + +impl<I: Interner> Debug for Goal<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_goal(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned)) + } +} + +impl<I: Interner> Debug for Goals<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_goals(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned)) + } +} + +impl<I: Interner> Debug for ProgramClauseImplication<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_program_clause_implication(self, fmt) + .unwrap_or_else(|| write!(fmt, "ProgramClauseImplication(?)")) + } +} + +impl<I: Interner> Debug for ProgramClause<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_program_clause(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned)) + } +} + +impl<I: Interner> Debug for ProgramClauses<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_program_clauses(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned)) + } +} + +impl<I: Interner> Debug for Constraints<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_constraints(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned)) + } +} + +impl<I: Interner> Debug for SeparatorTraitRef<'_, I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_separator_trait_ref(self, fmt) + .unwrap_or_else(|| write!(fmt, "SeparatorTraitRef(?)")) + } +} + +impl<I: Interner> Debug for AliasTy<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_alias(self, fmt).unwrap_or_else(|| write!(fmt, "AliasTy(?)")) + } +} + +impl<I: Interner> Debug for QuantifiedWhereClauses<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_quantified_where_clauses(self, fmt) + .unwrap_or_else(|| write!(fmt, "{:?}", self.interned)) + } +} + +impl<I: Interner> Debug for ProjectionTy<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_projection_ty(self, fmt).unwrap_or_else(|| { + unimplemented!("cannot format ProjectionTy without setting Program in tls") + }) + } +} + +impl<I: Interner> Debug for OpaqueTy<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_opaque_ty(self, fmt).unwrap_or_else(|| { + unimplemented!("cannot format OpaqueTy without setting Program in tls") + }) + } +} + +impl<I: Interner> Display for Substitution<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_substitution(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned)) + } +} + +impl<I: Interner> Debug for OpaqueTyId<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_opaque_ty_id(*self, fmt).unwrap_or_else(|| write!(fmt, "OpaqueTyId({:?})", self.0)) + } +} + +impl Display for UniverseIndex { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "U{}", self.counter) + } +} + +impl Debug for UniverseIndex { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "U{}", self.counter) + } +} + +impl<I: Interner> Debug for TyData<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + self.kind.fmt(fmt) + } +} + +impl<I: Interner> Debug for TyKind<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + match self { + TyKind::BoundVar(db) => write!(fmt, "{:?}", db), + TyKind::Dyn(clauses) => write!(fmt, "{:?}", clauses), + TyKind::InferenceVar(var, TyVariableKind::General) => write!(fmt, "{:?}", var), + TyKind::InferenceVar(var, TyVariableKind::Integer) => write!(fmt, "{:?}i", var), + TyKind::InferenceVar(var, TyVariableKind::Float) => write!(fmt, "{:?}f", var), + TyKind::Alias(alias) => write!(fmt, "{:?}", alias), + TyKind::Placeholder(index) => write!(fmt, "{:?}", index), + TyKind::Function(function) => write!(fmt, "{:?}", function), + TyKind::Adt(id, substitution) => write!(fmt, "{:?}<{:?}>", id, substitution), + TyKind::AssociatedType(assoc_ty, substitution) => { + write!(fmt, "{:?}<{:?}>", assoc_ty, substitution) + } + TyKind::Scalar(scalar) => write!(fmt, "{:?}", scalar), + TyKind::Str => write!(fmt, "Str"), + TyKind::Tuple(arity, substitution) => write!(fmt, "{:?}<{:?}>", arity, substitution), + TyKind::OpaqueType(opaque_ty, substitution) => { + write!(fmt, "!{:?}<{:?}>", opaque_ty, substitution) + } + TyKind::Slice(substitution) => write!(fmt, "{{slice}}<{:?}>", substitution), + TyKind::FnDef(fn_def, substitution) => write!(fmt, "{:?}<{:?}>", fn_def, substitution), + TyKind::Ref(mutability, lifetime, ty) => match mutability { + Mutability::Mut => write!(fmt, "(&{:?} mut {:?})", lifetime, ty), + Mutability::Not => write!(fmt, "(&{:?} {:?})", lifetime, ty), + }, + TyKind::Raw(mutability, ty) => match mutability { + Mutability::Mut => write!(fmt, "(*mut {:?})", ty), + Mutability::Not => write!(fmt, "(*const {:?})", ty), + }, + TyKind::Never => write!(fmt, "Never"), + TyKind::Array(ty, const_) => write!(fmt, "[{:?}; {:?}]", ty, const_), + TyKind::Closure(id, substitution) => { + write!(fmt, "{{closure:{:?}}}<{:?}>", id, substitution) + } + TyKind::Generator(generator, substitution) => { + write!(fmt, "{:?}<{:?}>", generator, substitution) + } + TyKind::GeneratorWitness(witness, substitution) => { + write!(fmt, "{:?}<{:?}>", witness, substitution) + } + TyKind::Foreign(foreign_ty) => write!(fmt, "{:?}", foreign_ty), + TyKind::Error => write!(fmt, "{{error}}"), + } + } +} + +impl Debug for BoundVar { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + let BoundVar { debruijn, index } = self; + write!(fmt, "{:?}.{:?}", debruijn, index) + } +} + +impl Debug for DebruijnIndex { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + let DebruijnIndex { depth } = self; + write!(fmt, "^{}", depth) + } +} + +impl<I: Interner> Debug for DynTy<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + let DynTy { bounds, lifetime } = self; + write!(fmt, "dyn {:?} + {:?}", bounds, lifetime) + } +} + +impl Debug for InferenceVar { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "?{}", self.index) + } +} + +impl<I: Interner> Debug for FnSubst<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "{:?}", self.0) + } +} + +impl<I: Interner> Debug for FnPointer<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + // FIXME -- we should introduce some names or something here + let FnPointer { + num_binders, + substitution, + sig, + } = self; + write!( + fmt, + "{}{:?} for<{}> {:?}", + match sig.safety { + Safety::Unsafe => "unsafe ", + Safety::Safe => "", + }, + sig.abi, + num_binders, + substitution + ) + } +} + +impl<I: Interner> Debug for LifetimeData<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + match self { + LifetimeData::BoundVar(db) => write!(fmt, "'{:?}", db), + LifetimeData::InferenceVar(var) => write!(fmt, "'{:?}", var), + LifetimeData::Placeholder(index) => write!(fmt, "'{:?}", index), + LifetimeData::Static => write!(fmt, "'static"), + LifetimeData::Erased => write!(fmt, "'<erased>"), + LifetimeData::Phantom(..) => unreachable!(), + } + } +} + +impl<I: Interner> VariableKinds<I> { + fn debug(&self) -> VariableKindsDebug<'_, I> { + VariableKindsDebug(self) + } + + /// Helper method for debugging variable kinds. + pub fn inner_debug(&self, interner: I) -> VariableKindsInnerDebug<'_, I> { + VariableKindsInnerDebug { + variable_kinds: self, + interner, + } + } +} + +struct VariableKindsDebug<'a, I: Interner>(&'a VariableKinds<I>); + +impl<'a, I: Interner> Debug for VariableKindsDebug<'a, I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_variable_kinds_with_angles(self.0, fmt) + .unwrap_or_else(|| write!(fmt, "{:?}", self.0.interned)) + } +} + +/// Helper struct for showing debug output for `VariableKinds`. +pub struct VariableKindsInnerDebug<'a, I: Interner> { + variable_kinds: &'a VariableKinds<I>, + interner: I, +} + +impl<'a, I: Interner> Debug for VariableKindsInnerDebug<'a, I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + // NB: We print variable kinds as a list delimited by `<>`, + // like `<K1, K2, ..>`. This is because variable kind lists + // are always associated with binders like `forall<type> { + // ... }`. + write!(fmt, "<")?; + for (index, binder) in self.variable_kinds.iter(self.interner).enumerate() { + if index > 0 { + write!(fmt, ", ")?; + } + match binder { + VariableKind::Ty(TyVariableKind::General) => write!(fmt, "type")?, + VariableKind::Ty(TyVariableKind::Integer) => write!(fmt, "integer type")?, + VariableKind::Ty(TyVariableKind::Float) => write!(fmt, "float type")?, + VariableKind::Lifetime => write!(fmt, "lifetime")?, + VariableKind::Const(ty) => write!(fmt, "const: {:?}", ty)?, + } + } + write!(fmt, ">") + } +} + +impl<I: Interner> Debug for ConstData<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + match &self.value { + ConstValue::BoundVar(db) => write!(fmt, "{:?}", db), + ConstValue::InferenceVar(var) => write!(fmt, "{:?}", var), + ConstValue::Placeholder(index) => write!(fmt, "{:?}", index), + ConstValue::Concrete(evaluated) => write!(fmt, "{:?}", evaluated), + } + } +} + +impl<I: Interner> Debug for GoalData<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + match self { + GoalData::Quantified(qkind, ref subgoal) => write!( + fmt, + "{:?}{:?} {{ {:?} }}", + qkind, + subgoal.binders.debug(), + subgoal.value + ), + GoalData::Implies(ref wc, ref g) => write!(fmt, "if ({:?}) {{ {:?} }}", wc, g), + GoalData::All(ref goals) => write!(fmt, "all{:?}", goals), + GoalData::Not(ref g) => write!(fmt, "not {{ {:?} }}", g), + GoalData::EqGoal(ref wc) => write!(fmt, "{:?}", wc), + GoalData::SubtypeGoal(ref wc) => write!(fmt, "{:?}", wc), + GoalData::DomainGoal(ref wc) => write!(fmt, "{:?}", wc), + GoalData::CannotProve => write!(fmt, r"¯\_(ツ)_/¯"), + } + } +} + +/// Helper struct for showing debug output for `Goals`. +pub struct GoalsDebug<'a, I: Interner> { + goals: &'a Goals<I>, + interner: I, +} + +impl<'a, I: Interner> Debug for GoalsDebug<'a, I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "(")?; + for (goal, index) in self.goals.iter(self.interner).zip(0..) { + if index > 0 { + write!(fmt, ", ")?; + } + write!(fmt, "{:?}", goal)?; + } + write!(fmt, ")")?; + Ok(()) + } +} + +impl<I: Interner> Goals<I> { + /// Show debug output for `Goals`. + pub fn debug(&self, interner: I) -> GoalsDebug<'_, I> { + GoalsDebug { + goals: self, + interner, + } + } +} + +/// Helper struct for showing debug output for `GenericArgData`. +pub struct GenericArgDataInnerDebug<'a, I: Interner>(&'a GenericArgData<I>); + +impl<'a, I: Interner> Debug for GenericArgDataInnerDebug<'a, I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + match self.0 { + GenericArgData::Ty(n) => write!(fmt, "{:?}", n), + GenericArgData::Lifetime(n) => write!(fmt, "{:?}", n), + GenericArgData::Const(n) => write!(fmt, "{:?}", n), + } + } +} + +impl<I: Interner> GenericArgData<I> { + /// Helper method for debugging `GenericArgData`. + pub fn inner_debug(&self) -> GenericArgDataInnerDebug<'_, I> { + GenericArgDataInnerDebug(self) + } +} + +/// Helper struct for showing debug output for program clause implications. +pub struct ProgramClauseImplicationDebug<'a, I: Interner> { + pci: &'a ProgramClauseImplication<I>, + interner: I, +} + +impl<'a, I: Interner> Debug for ProgramClauseImplicationDebug<'a, I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + let ProgramClauseImplicationDebug { pci, interner } = self; + write!(fmt, "{:?}", pci.consequence)?; + + let conditions = pci.conditions.as_slice(*interner); + + let conds = conditions.len(); + if conds == 0 { + return Ok(()); + } + + write!(fmt, " :- ")?; + for cond in &conditions[..conds - 1] { + write!(fmt, "{:?}, ", cond)?; + } + write!(fmt, "{:?}", conditions[conds - 1]) + } +} + +impl<I: Interner> ProgramClauseImplication<I> { + /// Show debug output for the program clause implication. + pub fn debug(&self, interner: I) -> ProgramClauseImplicationDebug<'_, I> { + ProgramClauseImplicationDebug { + pci: self, + interner, + } + } +} + +/// Helper struct for showing debug output for application types. +pub struct TyKindDebug<'a, I: Interner> { + ty: &'a TyKind<I>, + interner: I, +} + +impl<'a, I: Interner> Debug for TyKindDebug<'a, I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + let interner = self.interner; + match self.ty { + TyKind::BoundVar(db) => write!(fmt, "{:?}", db), + TyKind::Dyn(clauses) => write!(fmt, "{:?}", clauses), + TyKind::InferenceVar(var, TyVariableKind::General) => write!(fmt, "{:?}", var), + TyKind::InferenceVar(var, TyVariableKind::Integer) => write!(fmt, "{:?}i", var), + TyKind::InferenceVar(var, TyVariableKind::Float) => write!(fmt, "{:?}f", var), + TyKind::Alias(alias) => write!(fmt, "{:?}", alias), + TyKind::Placeholder(index) => write!(fmt, "{:?}", index), + TyKind::Function(function) => write!(fmt, "{:?}", function), + TyKind::Adt(id, substitution) => { + write!(fmt, "{:?}{:?}", id, substitution.with_angle(interner)) + } + TyKind::AssociatedType(assoc_ty, substitution) => { + write!(fmt, "{:?}{:?}", assoc_ty, substitution.with_angle(interner)) + } + TyKind::Scalar(scalar) => write!(fmt, "{:?}", scalar), + TyKind::Str => write!(fmt, "Str"), + TyKind::Tuple(arity, substitution) => { + write!(fmt, "{:?}{:?}", arity, substitution.with_angle(interner)) + } + TyKind::OpaqueType(opaque_ty, substitution) => write!( + fmt, + "!{:?}{:?}", + opaque_ty, + substitution.with_angle(interner) + ), + TyKind::Slice(ty) => write!(fmt, "[{:?}]", ty), + TyKind::FnDef(fn_def, substitution) => { + write!(fmt, "{:?}{:?}", fn_def, substitution.with_angle(interner)) + } + TyKind::Ref(mutability, lifetime, ty) => match mutability { + Mutability::Mut => write!(fmt, "(&{:?} mut {:?})", lifetime, ty), + Mutability::Not => write!(fmt, "(&{:?} {:?})", lifetime, ty), + }, + TyKind::Raw(mutability, ty) => match mutability { + Mutability::Mut => write!(fmt, "(*mut {:?})", ty), + Mutability::Not => write!(fmt, "(*const {:?})", ty), + }, + TyKind::Never => write!(fmt, "Never"), + TyKind::Array(ty, const_) => write!(fmt, "[{:?}; {:?}]", ty, const_), + TyKind::Closure(id, substitution) => write!( + fmt, + "{{closure:{:?}}}{:?}", + id, + substitution.with_angle(interner) + ), + TyKind::Generator(generator, substitution) => write!( + fmt, + "{:?}{:?}", + generator, + substitution.with_angle(interner) + ), + TyKind::GeneratorWitness(witness, substitution) => { + write!(fmt, "{:?}{:?}", witness, substitution.with_angle(interner)) + } + TyKind::Foreign(foreign_ty) => write!(fmt, "{:?}", foreign_ty,), + TyKind::Error => write!(fmt, "{{error}}"), + } + } +} + +impl<I: Interner> TyKind<I> { + /// Show debug output for the application type. + pub fn debug(&self, interner: I) -> TyKindDebug<'_, I> { + TyKindDebug { ty: self, interner } + } +} + +/// Helper struct for showing debug output for substitutions. +pub struct SubstitutionDebug<'a, I: Interner> { + substitution: &'a Substitution<I>, + interner: I, +} + +impl<'a, I: Interner> Debug for SubstitutionDebug<'a, I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + let SubstitutionDebug { + substitution, + interner, + } = self; + let mut first = true; + + write!(fmt, "[")?; + + for (index, value) in substitution.iter(*interner).enumerate() { + if first { + first = false; + } else { + write!(fmt, ", ")?; + } + + write!(fmt, "?{} := {:?}", index, value)?; + } + + write!(fmt, "]")?; + + Ok(()) + } +} + +impl<I: Interner> Substitution<I> { + /// Show debug output for the substitution. + pub fn debug(&self, interner: I) -> SubstitutionDebug<'_, I> { + SubstitutionDebug { + substitution: self, + interner, + } + } +} + +impl Debug for PlaceholderIndex { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + let PlaceholderIndex { ui, idx } = self; + write!(fmt, "!{}_{}", ui.counter, idx) + } +} + +impl<I: Interner> TraitRef<I> { + /// Returns a "Debuggable" type that prints like `P0 as Trait<P1..>`. + pub fn with_as(&self) -> impl std::fmt::Debug + '_ { + SeparatorTraitRef { + trait_ref: self, + separator: " as ", + } + } + + /// Returns a "Debuggable" type that prints like `P0: Trait<P1..>`. + pub fn with_colon(&self) -> impl std::fmt::Debug + '_ { + SeparatorTraitRef { + trait_ref: self, + separator: ": ", + } + } +} + +impl<I: Interner> Debug for TraitRef<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + Debug::fmt(&self.with_as(), fmt) + } +} + +/// Trait ref with associated separator used for debug output. +pub struct SeparatorTraitRef<'me, I: Interner> { + /// The `TraitRef` itself. + pub trait_ref: &'me TraitRef<I>, + + /// The separator used for displaying the `TraitRef`. + pub separator: &'me str, +} + +/// Helper struct for showing debug output for the `SeperatorTraitRef`. +pub struct SeparatorTraitRefDebug<'a, 'me, I: Interner> { + separator_trait_ref: &'a SeparatorTraitRef<'me, I>, + interner: I, +} + +impl<'a, 'me, I: Interner> Debug for SeparatorTraitRefDebug<'a, 'me, I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + let SeparatorTraitRefDebug { + separator_trait_ref, + interner, + } = self; + let parameters = separator_trait_ref + .trait_ref + .substitution + .as_slice(*interner); + write!( + fmt, + "{:?}{}{:?}{:?}", + parameters[0], + separator_trait_ref.separator, + separator_trait_ref.trait_ref.trait_id, + Angle(¶meters[1..]) + ) + } +} + +impl<'me, I: Interner> SeparatorTraitRef<'me, I> { + /// Show debug output for the `SeperatorTraitRef`. + pub fn debug<'a>(&'a self, interner: I) -> SeparatorTraitRefDebug<'a, 'me, I> { + SeparatorTraitRefDebug { + separator_trait_ref: self, + interner, + } + } +} + +impl<I: Interner> Debug for LifetimeOutlives<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "{:?}: {:?}", self.a, self.b) + } +} + +impl<I: Interner> Debug for TypeOutlives<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "{:?}: {:?}", self.ty, self.lifetime) + } +} + +/// Helper struct for showing debug output for projection types. +pub struct ProjectionTyDebug<'a, I: Interner> { + projection_ty: &'a ProjectionTy<I>, + interner: I, +} + +impl<'a, I: Interner> Debug for ProjectionTyDebug<'a, I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + let ProjectionTyDebug { + projection_ty, + interner, + } = self; + write!( + fmt, + "({:?}){:?}", + projection_ty.associated_ty_id, + projection_ty.substitution.with_angle(*interner) + ) + } +} + +impl<I: Interner> ProjectionTy<I> { + /// Show debug output for the projection type. + pub fn debug(&self, interner: I) -> ProjectionTyDebug<'_, I> { + ProjectionTyDebug { + projection_ty: self, + interner, + } + } +} + +/// Helper struct for showing debug output for opaque types. +pub struct OpaqueTyDebug<'a, I: Interner> { + opaque_ty: &'a OpaqueTy<I>, + interner: I, +} + +impl<'a, I: Interner> Debug for OpaqueTyDebug<'a, I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + let OpaqueTyDebug { + opaque_ty, + interner, + } = self; + write!( + fmt, + "{:?}{:?}", + opaque_ty.opaque_ty_id, + opaque_ty.substitution.with_angle(*interner) + ) + } +} + +impl<I: Interner> OpaqueTy<I> { + /// Show debug output for the opaque type. + pub fn debug(&self, interner: I) -> OpaqueTyDebug<'_, I> { + OpaqueTyDebug { + opaque_ty: self, + interner, + } + } +} + +/// Wraps debug output in angle brackets (`<>`). +pub struct Angle<'a, T>(pub &'a [T]); + +impl<'a, T: Debug> Debug for Angle<'a, T> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + if !self.0.is_empty() { + write!(fmt, "<")?; + for (index, elem) in self.0.iter().enumerate() { + if index > 0 { + write!(fmt, ", {:?}", elem)?; + } else { + write!(fmt, "{:?}", elem)?; + } + } + write!(fmt, ">")?; + } + Ok(()) + } +} + +impl<I: Interner> Debug for Normalize<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "Normalize({:?} -> {:?})", self.alias, self.ty) + } +} + +impl<I: Interner> Debug for AliasEq<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "AliasEq({:?} = {:?})", self.alias, self.ty) + } +} + +impl<I: Interner> Debug for WhereClause<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + match self { + WhereClause::Implemented(tr) => write!(fmt, "Implemented({:?})", tr.with_colon()), + WhereClause::AliasEq(a) => write!(fmt, "{:?}", a), + WhereClause::LifetimeOutlives(l_o) => write!(fmt, "{:?}", l_o), + WhereClause::TypeOutlives(t_o) => write!(fmt, "{:?}", t_o), + } + } +} + +impl<I: Interner> Debug for FromEnv<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + match self { + FromEnv::Trait(t) => write!(fmt, "FromEnv({:?})", t.with_colon()), + FromEnv::Ty(t) => write!(fmt, "FromEnv({:?})", t), + } + } +} + +impl<I: Interner> Debug for WellFormed<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + match self { + WellFormed::Trait(t) => write!(fmt, "WellFormed({:?})", t.with_colon()), + WellFormed::Ty(t) => write!(fmt, "WellFormed({:?})", t), + } + } +} + +impl<I: Interner> Debug for DomainGoal<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + match self { + DomainGoal::Holds(n) => write!(fmt, "{:?}", n), + DomainGoal::WellFormed(n) => write!(fmt, "{:?}", n), + DomainGoal::FromEnv(n) => write!(fmt, "{:?}", n), + DomainGoal::Normalize(n) => write!(fmt, "{:?}", n), + DomainGoal::IsLocal(n) => write!(fmt, "IsLocal({:?})", n), + DomainGoal::IsUpstream(n) => write!(fmt, "IsUpstream({:?})", n), + DomainGoal::IsFullyVisible(n) => write!(fmt, "IsFullyVisible({:?})", n), + DomainGoal::LocalImplAllowed(tr) => { + write!(fmt, "LocalImplAllowed({:?})", tr.with_colon(),) + } + DomainGoal::Compatible => write!(fmt, "Compatible"), + DomainGoal::DownstreamType(n) => write!(fmt, "DownstreamType({:?})", n), + DomainGoal::Reveal => write!(fmt, "Reveal"), + DomainGoal::ObjectSafe(n) => write!(fmt, "ObjectSafe({:?})", n), + } + } +} + +impl<I: Interner> Debug for EqGoal<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "({:?} = {:?})", self.a, self.b) + } +} + +impl<I: Interner> Debug for SubtypeGoal<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "({:?} <: {:?})", self.a, self.b) + } +} + +impl<T: HasInterner + Debug> Debug for Binders<T> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + let Binders { + ref binders, + ref value, + } = *self; + write!(fmt, "for{:?} ", binders.debug())?; + Debug::fmt(value, fmt) + } +} + +impl<I: Interner> Debug for ProgramClauseData<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "{:?}", self.0) + } +} + +impl<I: Interner> Debug for Environment<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + write!(fmt, "Env({:?})", self.clauses) + } +} + +impl<I: Interner> Debug for CanonicalVarKinds<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_canonical_var_kinds(self, fmt) + .unwrap_or_else(|| write!(fmt, "{:?}", self.interned)) + } +} + +impl<T: HasInterner + Display> Canonical<T> { + /// Display the canonicalized item. + pub fn display(&self, interner: T::Interner) -> CanonicalDisplay<'_, T> { + CanonicalDisplay { + canonical: self, + interner, + } + } +} + +/// Helper struct for displaying canonicalized items. +pub struct CanonicalDisplay<'a, T: HasInterner> { + canonical: &'a Canonical<T>, + interner: T::Interner, +} + +impl<'a, T: HasInterner + Display> Display for CanonicalDisplay<'a, T> { + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + let Canonical { binders, value } = self.canonical; + let interner = self.interner; + let binders = binders.as_slice(interner); + if binders.is_empty() { + // Ordinarily, we try to print all binder levels, if they + // are empty, but we can skip in this *particular* case + // because we know that `Canonical` terms are never + // supposed to contain free variables. In other words, + // all "bound variables" that appear inside the canonical + // value must reference values that appear in `binders`. + write!(f, "{}", value)?; + } else { + write!(f, "for<")?; + + for (i, pk) in binders.iter().enumerate() { + if i > 0 { + write!(f, ",")?; + } + write!(f, "?{}", pk.skip_kind())?; + } + + write!(f, "> {{ {} }}", value)?; + } + + Ok(()) + } +} + +impl<I: Interner> Debug for GenericArgData<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + match self { + GenericArgData::Ty(t) => write!(fmt, "Ty({:?})", t), + GenericArgData::Lifetime(l) => write!(fmt, "Lifetime({:?})", l), + GenericArgData::Const(c) => write!(fmt, "Const({:?})", c), + } + } +} + +impl<I: Interner> Debug for VariableKind<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + match self { + VariableKind::Ty(TyVariableKind::General) => write!(fmt, "type"), + VariableKind::Ty(TyVariableKind::Integer) => write!(fmt, "integer type"), + VariableKind::Ty(TyVariableKind::Float) => write!(fmt, "float type"), + VariableKind::Lifetime => write!(fmt, "lifetime"), + VariableKind::Const(ty) => write!(fmt, "const: {:?}", ty), + } + } +} + +impl<I: Interner, T: Debug> Debug for WithKind<I, T> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + let value = self.skip_kind(); + match &self.kind { + VariableKind::Ty(TyVariableKind::General) => write!(fmt, "{:?} with kind type", value), + VariableKind::Ty(TyVariableKind::Integer) => { + write!(fmt, "{:?} with kind integer type", value) + } + VariableKind::Ty(TyVariableKind::Float) => { + write!(fmt, "{:?} with kind float type", value) + } + VariableKind::Lifetime => write!(fmt, "{:?} with kind lifetime", value), + VariableKind::Const(ty) => write!(fmt, "{:?} with kind {:?}", value, ty), + } + } +} + +impl<I: Interner> Debug for Constraint<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + match self { + Constraint::LifetimeOutlives(a, b) => write!(fmt, "{:?}: {:?}", a, b), + Constraint::TypeOutlives(ty, lifetime) => write!(fmt, "{:?}: {:?}", ty, lifetime), + } + } +} + +impl<I: Interner> Display for ConstrainedSubst<I> { + #[rustfmt::skip] + fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error> { + let ConstrainedSubst { subst, constraints } = self; + + let mut first = true; + + let subst = format!("{}", Fmt(|f| Display::fmt(subst, f))); + if subst != "[]" { + write!(f, "substitution {}", subst)?; + first = false; + } + + let constraints = format!("{}", Fmt(|f| Debug::fmt(constraints, f))); + if constraints != "[]" { + if !first { write!(f, ", ")?; } + write!(f, "lifetime constraints {}", constraints)?; + first = false; + } + + let _ = first; + Ok(()) + } +} + +impl<I: Interner> Substitution<I> { + /// Displays the substitution in the form `< P0, .. Pn >`, or (if + /// the substitution is empty) as an empty string. + pub fn with_angle(&self, interner: I) -> Angle<'_, GenericArg<I>> { + Angle(self.as_slice(interner)) + } +} + +impl<I: Interner> Debug for Substitution<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + Display::fmt(self, fmt) + } +} + +impl<I: Interner> Debug for Variances<I> { + fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error> { + I::debug_variances(self, fmt).unwrap_or_else(|| write!(fmt, "{:?}", self.interned)) + } +} |