hir_ty/next_solver/
opaques.rs

1//! Things related to opaques in the next-trait-solver.
2
3use intern::Interned;
4use rustc_ast_ir::try_visit;
5
6use crate::next_solver::SolverDefId;
7
8use super::{CanonicalVarKind, DbInterner, interned_vec_nolifetime_salsa};
9
10pub type OpaqueTypeKey<'db> = rustc_type_ir::OpaqueTypeKey<DbInterner<'db>>;
11pub type PredefinedOpaquesData<'db> = rustc_type_ir::solve::PredefinedOpaquesData<DbInterner<'db>>;
12pub type ExternalConstraintsData<'db> =
13    rustc_type_ir::solve::ExternalConstraintsData<DbInterner<'db>>;
14
15#[salsa::interned(constructor = new_, debug)]
16pub struct PredefinedOpaques<'db> {
17    #[returns(ref)]
18    kind_: rustc_type_ir::solve::PredefinedOpaquesData<DbInterner<'db>>,
19}
20
21impl<'db> PredefinedOpaques<'db> {
22    pub fn new(interner: DbInterner<'db>, data: PredefinedOpaquesData<'db>) -> Self {
23        PredefinedOpaques::new_(interner.db(), data)
24    }
25
26    pub fn inner(&self) -> &PredefinedOpaquesData<'db> {
27        salsa::with_attached_database(|db| {
28            let inner = self.kind_(db);
29            // SAFETY: ¯\_(ツ)_/¯
30            unsafe { std::mem::transmute(inner) }
31        })
32        .unwrap()
33    }
34}
35
36impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for PredefinedOpaques<'db> {
37    fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
38        &self,
39        visitor: &mut V,
40    ) -> V::Result {
41        self.opaque_types.visit_with(visitor)
42    }
43}
44
45impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for PredefinedOpaques<'db> {
46    fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
47        self,
48        folder: &mut F,
49    ) -> Result<Self, F::Error> {
50        Ok(PredefinedOpaques::new(
51            folder.cx(),
52            PredefinedOpaquesData {
53                opaque_types: self
54                    .opaque_types
55                    .iter()
56                    .cloned()
57                    .map(|opaque| opaque.try_fold_with(folder))
58                    .collect::<Result<_, F::Error>>()?,
59            },
60        ))
61    }
62    fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
63        PredefinedOpaques::new(
64            folder.cx(),
65            PredefinedOpaquesData {
66                opaque_types: self
67                    .opaque_types
68                    .iter()
69                    .cloned()
70                    .map(|opaque| opaque.fold_with(folder))
71                    .collect(),
72            },
73        )
74    }
75}
76
77impl<'db> std::ops::Deref for PredefinedOpaques<'db> {
78    type Target = PredefinedOpaquesData<'db>;
79
80    fn deref(&self) -> &Self::Target {
81        self.inner()
82    }
83}
84
85interned_vec_nolifetime_salsa!(SolverDefIds, SolverDefId);
86
87#[salsa::interned(constructor = new_, debug)]
88pub struct ExternalConstraints<'db> {
89    #[returns(ref)]
90    kind_: rustc_type_ir::solve::ExternalConstraintsData<DbInterner<'db>>,
91}
92
93impl<'db> ExternalConstraints<'db> {
94    pub fn new(interner: DbInterner<'db>, data: ExternalConstraintsData<'db>) -> Self {
95        ExternalConstraints::new_(interner.db(), data)
96    }
97
98    pub fn inner(&self) -> &ExternalConstraintsData<'db> {
99        salsa::with_attached_database(|db| {
100            let inner = self.kind_(db);
101            // SAFETY: ¯\_(ツ)_/¯
102            unsafe { std::mem::transmute(inner) }
103        })
104        .unwrap()
105    }
106}
107
108impl<'db> std::ops::Deref for ExternalConstraints<'db> {
109    type Target = ExternalConstraintsData<'db>;
110
111    fn deref(&self) -> &Self::Target {
112        self.inner()
113    }
114}
115
116impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for ExternalConstraints<'db> {
117    fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
118        &self,
119        visitor: &mut V,
120    ) -> V::Result {
121        try_visit!(self.region_constraints.visit_with(visitor));
122        try_visit!(self.opaque_types.visit_with(visitor));
123        self.normalization_nested_goals.visit_with(visitor)
124    }
125}
126
127impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for ExternalConstraints<'db> {
128    fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
129        self,
130        folder: &mut F,
131    ) -> Result<Self, F::Error> {
132        Ok(ExternalConstraints::new(
133            folder.cx(),
134            ExternalConstraintsData {
135                region_constraints: self.region_constraints.clone().try_fold_with(folder)?,
136                opaque_types: self
137                    .opaque_types
138                    .iter()
139                    .cloned()
140                    .map(|opaque| opaque.try_fold_with(folder))
141                    .collect::<Result<_, F::Error>>()?,
142                normalization_nested_goals: self
143                    .normalization_nested_goals
144                    .clone()
145                    .try_fold_with(folder)?,
146            },
147        ))
148    }
149    fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
150        ExternalConstraints::new(
151            folder.cx(),
152            ExternalConstraintsData {
153                region_constraints: self.region_constraints.clone().fold_with(folder),
154                opaque_types: self
155                    .opaque_types
156                    .iter()
157                    .cloned()
158                    .map(|opaque| opaque.fold_with(folder))
159                    .collect(),
160                normalization_nested_goals: self
161                    .normalization_nested_goals
162                    .clone()
163                    .fold_with(folder),
164            },
165        )
166    }
167}