//! 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::mir::interpret::ConstValue; 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 = ConstValue<'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 InternedConstraints = Vec>>; type DefId = DefId; type InternedAdtId = &'tcx AdtDef; 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 conds = conditions.len(); if conds == 0 { return Ok(()); } write!(fmt, " :- ")?; for cond in &conditions[..conds - 1] { write!(fmt, "{:?}, ", cond)?; } write!(fmt, "{:?}", conditions[conds - 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((|| { 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::TyData) -> Self::InternedType { Box::new(ty) } fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData { ty } fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData) -> Self::InternedLifetime { Box::new(lifetime) } fn lifetime_data<'a>( &self, lifetime: &'a Self::InternedLifetime, ) -> &'a chalk_ir::LifetimeData { &lifetime } fn intern_const(&self, constant: chalk_ir::ConstData) -> Self::InternedConst { Box::new(constant) } fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a 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<'a>( &self, data: &'a Self::InternedGenericArg, ) -> &'a chalk_ir::GenericArgData { &data } fn intern_goal(&self, goal: chalk_ir::GoalData) -> Self::InternedGoal { Box::new(goal) } fn goal_data<'a>(&self, goal: &'a Self::InternedGoal) -> &'a chalk_ir::GoalData { &goal } fn intern_goals( &self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn goals_data<'a>(&self, goals: &'a Self::InternedGoals) -> &'a [chalk_ir::Goal] { goals } fn intern_substitution( &self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn substitution_data<'a>( &self, substitution: &'a Self::InternedSubstitution, ) -> &'a [chalk_ir::GenericArg] { substitution } fn intern_program_clause( &self, data: chalk_ir::ProgramClauseData, ) -> Self::InternedProgramClause { Box::new(data) } fn program_clause_data<'a>( &self, clause: &'a Self::InternedProgramClause, ) -> &'a chalk_ir::ProgramClauseData { &clause } fn intern_program_clauses( &self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn program_clauses_data<'a>( &self, clauses: &'a Self::InternedProgramClauses, ) -> &'a [chalk_ir::ProgramClause] { clauses } fn intern_quantified_where_clauses( &self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn quantified_where_clauses_data<'a>( &self, clauses: &'a Self::InternedQuantifiedWhereClauses, ) -> &'a [chalk_ir::QuantifiedWhereClause] { clauses } fn intern_generic_arg_kinds( &self, data: impl IntoIterator, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn variable_kinds_data<'a>( &self, parameter_kinds: &'a Self::InternedVariableKinds, ) -> &'a [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<'a>( &self, canonical_var_kinds: &'a Self::InternedCanonicalVarKinds, ) -> &'a [chalk_ir::CanonicalVarKind] { canonical_var_kinds } fn intern_constraints( &self, data: impl IntoIterator>, E>>, ) -> Result { data.into_iter().collect::, _>>() } fn constraints_data<'a>( &self, constraints: &'a Self::InternedConstraints, ) -> &'a [chalk_ir::InEnvironment>] { constraints } } 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)] 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) } }