Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/next_solver/opaques.rs')
| -rw-r--r-- | crates/hir-ty/src/next_solver/opaques.rs | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/crates/hir-ty/src/next_solver/opaques.rs b/crates/hir-ty/src/next_solver/opaques.rs new file mode 100644 index 0000000000..43589ab2ef --- /dev/null +++ b/crates/hir-ty/src/next_solver/opaques.rs @@ -0,0 +1,167 @@ +//! Things related to opaques in the next-trait-solver. + +use intern::Interned; +use rustc_ast_ir::try_visit; + +use crate::next_solver::SolverDefId; + +use super::{CanonicalVarKind, DbInterner, interned_vec_nolifetime_salsa}; + +pub type OpaqueTypeKey<'db> = rustc_type_ir::OpaqueTypeKey<DbInterner<'db>>; +pub type PredefinedOpaquesData<'db> = rustc_type_ir::solve::PredefinedOpaquesData<DbInterner<'db>>; +pub type ExternalConstraintsData<'db> = + rustc_type_ir::solve::ExternalConstraintsData<DbInterner<'db>>; + +#[salsa::interned(constructor = new_, debug)] +pub struct PredefinedOpaques<'db> { + #[returns(ref)] + kind_: rustc_type_ir::solve::PredefinedOpaquesData<DbInterner<'db>>, +} + +impl<'db> PredefinedOpaques<'db> { + pub fn new(interner: DbInterner<'db>, data: PredefinedOpaquesData<'db>) -> Self { + PredefinedOpaques::new_(interner.db(), data) + } + + pub fn inner(&self) -> &PredefinedOpaquesData<'db> { + salsa::with_attached_database(|db| { + let inner = self.kind_(db); + // SAFETY: ¯\_(ツ)_/¯ + unsafe { std::mem::transmute(inner) } + }) + .unwrap() + } +} + +impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for PredefinedOpaques<'db> { + fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>( + &self, + visitor: &mut V, + ) -> V::Result { + self.opaque_types.visit_with(visitor) + } +} + +impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for PredefinedOpaques<'db> { + fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>( + self, + folder: &mut F, + ) -> Result<Self, F::Error> { + Ok(PredefinedOpaques::new( + folder.cx(), + PredefinedOpaquesData { + opaque_types: self + .opaque_types + .iter() + .cloned() + .map(|opaque| opaque.try_fold_with(folder)) + .collect::<Result<_, F::Error>>()?, + }, + )) + } + fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self { + PredefinedOpaques::new( + folder.cx(), + PredefinedOpaquesData { + opaque_types: self + .opaque_types + .iter() + .cloned() + .map(|opaque| opaque.fold_with(folder)) + .collect(), + }, + ) + } +} + +impl<'db> std::ops::Deref for PredefinedOpaques<'db> { + type Target = PredefinedOpaquesData<'db>; + + fn deref(&self) -> &Self::Target { + self.inner() + } +} + +interned_vec_nolifetime_salsa!(SolverDefIds, SolverDefId); + +#[salsa::interned(constructor = new_, debug)] +pub struct ExternalConstraints<'db> { + #[returns(ref)] + kind_: rustc_type_ir::solve::ExternalConstraintsData<DbInterner<'db>>, +} + +impl<'db> ExternalConstraints<'db> { + pub fn new(interner: DbInterner<'db>, data: ExternalConstraintsData<'db>) -> Self { + ExternalConstraints::new_(interner.db(), data) + } + + pub fn inner(&self) -> &ExternalConstraintsData<'db> { + salsa::with_attached_database(|db| { + let inner = self.kind_(db); + // SAFETY: ¯\_(ツ)_/¯ + unsafe { std::mem::transmute(inner) } + }) + .unwrap() + } +} + +impl<'db> std::ops::Deref for ExternalConstraints<'db> { + type Target = ExternalConstraintsData<'db>; + + fn deref(&self) -> &Self::Target { + self.inner() + } +} + +impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for ExternalConstraints<'db> { + fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>( + &self, + visitor: &mut V, + ) -> V::Result { + try_visit!(self.region_constraints.visit_with(visitor)); + try_visit!(self.opaque_types.visit_with(visitor)); + self.normalization_nested_goals.visit_with(visitor) + } +} + +impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for ExternalConstraints<'db> { + fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>( + self, + folder: &mut F, + ) -> Result<Self, F::Error> { + Ok(ExternalConstraints::new( + folder.cx(), + ExternalConstraintsData { + region_constraints: self.region_constraints.clone().try_fold_with(folder)?, + opaque_types: self + .opaque_types + .iter() + .cloned() + .map(|opaque| opaque.try_fold_with(folder)) + .collect::<Result<_, F::Error>>()?, + normalization_nested_goals: self + .normalization_nested_goals + .clone() + .try_fold_with(folder)?, + }, + )) + } + fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self { + ExternalConstraints::new( + folder.cx(), + ExternalConstraintsData { + region_constraints: self.region_constraints.clone().fold_with(folder), + opaque_types: self + .opaque_types + .iter() + .cloned() + .map(|opaque| opaque.fold_with(folder)) + .collect(), + normalization_nested_goals: self + .normalization_nested_goals + .clone() + .fold_with(folder), + }, + ) + } +} |