//! Types required for Chalk-related queries //! //! The primary purpose of this file is defining an implementation for the //! `chalk_ir::interner::Interner` trait. The primary purpose of this trait, as //! its name suggest, is to provide an abstraction boundary for creating //! interned Chalk types. use rustc_middle::ty::{self, AdtDef, TyCtxt}; use rustc_hir::def_id::DefId; use rustc_target::spec::abi::Abi; use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; #[derive(Copy, Clone)] pub struct RustInterner<'tcx> { pub tcx: TyCtxt<'tcx>, } /// We don't ever actually need this. It's only required for derives. impl<'tcx> Hash for RustInterner<'tcx> { fn hash(&self, _state: &mut H) {} } /// We don't ever actually need this. It's only required for derives. impl<'tcx> Ord for RustInterner<'tcx> { fn cmp(&self, _other: &Self) -> Ordering { Ordering::Equal } } /// We don't ever actually need this. It's only required for derives. impl<'tcx> PartialOrd for RustInterner<'tcx> { fn partial_cmp(&self, _other: &Self) -> Option { None } } /// We don't ever actually need this. It's only required for derives. impl<'tcx> PartialEq for RustInterner<'tcx> { fn eq(&self, _other: &Self) -> bool { false } } /// We don't ever actually need this. It's only required for derives. impl<'tcx> Eq for RustInterner<'tcx> {} impl fmt::Debug for RustInterner<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "RustInterner") } } // Right now, there is no interning at all. I was running into problems with // adding interning in `ty/context.rs` for Chalk types with // `parallel-compiler = true`. -jackh726 impl<'tcx> chalk_ir::interner::Interner for RustInterner<'tcx> { type InternedType = Box>; type InternedLifetime = Box>; type InternedConst = Box>; type InternedConcreteConst = ty::ValTree<'tcx>; type InternedGenericArg = Box>; type InternedGoal = Box>; type InternedGoals = Vec>; type InternedSubstitution = Vec>; type InternedProgramClause = Box>; type InternedProgramClauses = Vec>; type InternedQuantifiedWhereClauses = Vec>; type InternedVariableKinds = Vec>; type InternedCanonicalVarKinds = Vec>; type InternedVariances = Vec; type InternedConstraints = Vec>>; type DefId = DefId; type InternedAdtId = AdtDef<'tcx>; type Identifier = (); type FnAbi = Abi; fn debug_program_clause_implication( pci: &chalk_ir::ProgramClauseImplication, fmt: &mut fmt::Formatter<'_>, ) -> Option { let mut write = || { write!(fmt, "{:?}", pci.consequence)?; let conditions = pci.conditions.interned(); let constraints = pci.constraints.interned(); let conds = conditions.len(); let consts = constraints.len(); if conds == 0 && consts == 0 { return Ok(()); } write!(fmt, " :- ")?; if conds != 0 { for cond in &conditions[..conds - 1] { write!(fmt, "{:?}, ", cond)?; } write!(fmt, "{:?}", conditions[conds - 1])?; } if conds != 0 && consts != 0 { write!(fmt, " ; ")?; } if consts != 0 { for constraint in &constraints[..consts - 1] { write!(fmt, "{:?}, ", constraint)?; } write!(fmt, "{:?}", constraints[consts - 1])?; } Ok(()) }; Some(write()) } fn debug_substitution( substitution: &chalk_ir::Substitution, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", substitution.interned())) } fn debug_separator_trait_ref( separator_trait_ref: &chalk_ir::SeparatorTraitRef<'_, Self>, fmt: &mut fmt::Formatter<'_>, ) -> Option { let substitution = &separator_trait_ref.trait_ref.substitution; let parameters = substitution.interned(); Some(write!( fmt, "{:?}{}{:?}{:?}", parameters[0], separator_trait_ref.separator, separator_trait_ref.trait_ref.trait_id, chalk_ir::debug::Angle(¶meters[1..]) )) } fn debug_quantified_where_clauses( clauses: &chalk_ir::QuantifiedWhereClauses, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", clauses.interned())) } fn debug_ty(ty: &chalk_ir::Ty, fmt: &mut fmt::Formatter<'_>) -> Option { match &ty.interned().kind { chalk_ir::TyKind::Ref(chalk_ir::Mutability::Not, lifetime, ty) => { Some(write!(fmt, "(&{:?} {:?})", lifetime, ty)) } chalk_ir::TyKind::Ref(chalk_ir::Mutability::Mut, lifetime, ty) => { Some(write!(fmt, "(&{:?} mut {:?})", lifetime, ty)) } chalk_ir::TyKind::Array(ty, len) => Some(write!(fmt, "[{:?}; {:?}]", ty, len)), chalk_ir::TyKind::Slice(ty) => Some(write!(fmt, "[{:?}]", ty)), chalk_ir::TyKind::Tuple(len, substs) => Some( try { write!(fmt, "(")?; for (idx, substitution) in substs.interned().iter().enumerate() { if idx == *len && *len != 1 { // Don't add a trailing comma if the tuple has more than one element write!(fmt, "{:?}", substitution)?; } else { write!(fmt, "{:?},", substitution)?; } } write!(fmt, ")")?; }, ), _ => None, } } fn debug_alias( alias_ty: &chalk_ir::AliasTy, fmt: &mut fmt::Formatter<'_>, ) -> Option { match alias_ty { chalk_ir::AliasTy::Projection(projection_ty) => { Self::debug_projection_ty(projection_ty, fmt) } chalk_ir::AliasTy::Opaque(opaque_ty) => Self::debug_opaque_ty(opaque_ty, fmt), } } fn debug_projection_ty( projection_ty: &chalk_ir::ProjectionTy, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!( fmt, "projection: {:?} {:?}", projection_ty.associated_ty_id, projection_ty.substitution, )) } fn debug_opaque_ty( opaque_ty: &chalk_ir::OpaqueTy, fmt: &mut fmt::Formatter<'_>, ) -> Option { Some(write!(fmt, "{:?}", opaque_ty.opaque_ty_id)) } fn intern_ty(self, ty: chalk_ir::TyKind) -> Self::InternedType { let flags = ty.compute_flags(self); Box::new(chalk_ir::TyData { kind: ty, flags: flags }) } fn ty_data(self, ty: &Self::InternedType) -> &chalk_ir::TyData { ty } fn intern_lifetime(self, lifetime: chalk_ir::LifetimeData) -> Self::InternedLifetime { Box::new(lifetime) } fn lifetime_data(self, lifetime: &Self::InternedLifetime) -> &chalk_ir::LifetimeData { &lifetime } fn intern_const(self, constant: chalk_ir::ConstData) -> Self::InternedConst { Box::new(constant) } fn const_data(self, constant: &Self::InternedConst) -> &chalk_ir::ConstData { &constant } fn const_eq( self, _ty: &Self::InternedType, c1: &Self::InternedConcreteConst, c2: &Self::InternedConcreteConst, ) -> bool { c1 == c2 } fn intern_generic_arg(self, data: chalk_ir::GenericArgData) -> Self::InternedGenericArg { Box::new(data) } fn generic_arg_data(self, data: &Self::InternedGenericArg) -> &chalk_ir::GenericArgData { &data } fn intern_goal(self, goal: chalk_ir::GoalData) -> Self::InternedGoal { Box::new(goal) } fn goal_data(self, goal: &Self::InternedGoal) -> &chalk_ir::GoalData { &goal } fn intern_goals( self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn goals_data(self, goals: &Self::InternedGoals) -> &[chalk_ir::Goal] { goals } fn intern_substitution( self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn substitution_data( self, substitution: &Self::InternedSubstitution, ) -> &[chalk_ir::GenericArg] { substitution } fn intern_program_clause( self, data: chalk_ir::ProgramClauseData, ) -> Self::InternedProgramClause { Box::new(data) } fn program_clause_data( self, clause: &Self::InternedProgramClause, ) -> &chalk_ir::ProgramClauseData { &clause } fn intern_program_clauses( self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn program_clauses_data( self, clauses: &Self::InternedProgramClauses, ) -> &[chalk_ir::ProgramClause] { clauses } fn intern_quantified_where_clauses( self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn quantified_where_clauses_data( self, clauses: &Self::InternedQuantifiedWhereClauses, ) -> &[chalk_ir::QuantifiedWhereClause] { clauses } fn intern_generic_arg_kinds( self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn variable_kinds_data( self, parameter_kinds: &Self::InternedVariableKinds, ) -> &[chalk_ir::VariableKind] { parameter_kinds } fn intern_canonical_var_kinds( self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn canonical_var_kinds_data( self, canonical_var_kinds: &Self::InternedCanonicalVarKinds, ) -> &[chalk_ir::CanonicalVarKind] { canonical_var_kinds } fn intern_constraints( self, data: impl IntoIterator>, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn constraints_data( self, constraints: &Self::InternedConstraints, ) -> &[chalk_ir::InEnvironment>] { constraints } fn intern_variances( self, data: impl IntoIterator>, ) -> Result { data.into_iter().collect::, _>>() } fn variances_data(self, variances: &Self::InternedVariances) -> &[chalk_ir::Variance] { variances } } impl<'tcx> chalk_ir::interner::HasInterner for RustInterner<'tcx> { type Interner = Self; } /// A chalk environment and goal. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, HashStable, TypeFoldable, TypeVisitable)] pub struct ChalkEnvironmentAndGoal<'tcx> { pub environment: &'tcx ty::List>, pub goal: ty::Predicate<'tcx>, } impl<'tcx> fmt::Display for ChalkEnvironmentAndGoal<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "environment: {:?}, goal: {}", self.environment, self.goal) } }