hir_ty/
interner.rs

1//! Implementation of the Chalk `Interner` trait, which allows customizing the
2//! representation of the various objects Chalk deals with (types, goals etc.).
3
4use crate::{
5    AliasTy, CanonicalVarKind, CanonicalVarKinds, ClosureId, Const, ConstData, ConstScalar, FnAbi,
6    FnDefId, GenericArg, GenericArgData, Goal, GoalData, InEnvironment, Lifetime, LifetimeData,
7    OpaqueTy, OpaqueTyId, ProgramClause, ProjectionTy, QuantifiedWhereClause,
8    QuantifiedWhereClauses, Substitution, Ty, TyKind, VariableKind, chalk_db, tls,
9};
10use chalk_ir::{ProgramClauseImplication, SeparatorTraitRef, Variance};
11use hir_def::TypeAliasId;
12use intern::{Interned, impl_internable};
13use smallvec::SmallVec;
14use std::fmt;
15use triomphe::Arc;
16
17type TyData = chalk_ir::TyData<Interner>;
18type VariableKinds = chalk_ir::VariableKinds<Interner>;
19type Goals = chalk_ir::Goals<Interner>;
20type ProgramClauseData = chalk_ir::ProgramClauseData<Interner>;
21type Constraint = chalk_ir::Constraint<Interner>;
22type Constraints = chalk_ir::Constraints<Interner>;
23type ProgramClauses = chalk_ir::ProgramClauses<Interner>;
24
25#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
26pub struct Interner;
27
28#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
29pub struct InternedWrapper<T>(pub(crate) T);
30
31impl<T: fmt::Debug> fmt::Debug for InternedWrapper<T> {
32    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33        fmt::Debug::fmt(&self.0, f)
34    }
35}
36
37#[derive(PartialEq, Eq, Hash, PartialOrd, Ord, Clone)]
38pub struct InternedWrapperNoDebug<T>(pub(crate) T);
39
40impl<T> std::ops::Deref for InternedWrapper<T> {
41    type Target = T;
42
43    fn deref(&self) -> &Self::Target {
44        &self.0
45    }
46}
47
48impl_internable!(
49    InternedWrapper<Vec<VariableKind>>,
50    InternedWrapper<SmallVec<[GenericArg; 2]>>,
51    InternedWrapper<TyData>,
52    InternedWrapper<LifetimeData>,
53    InternedWrapper<ConstData>,
54    InternedWrapper<ConstScalar>,
55    InternedWrapper<Vec<CanonicalVarKind>>,
56    InternedWrapper<Box<[ProgramClause]>>,
57    InternedWrapper<Vec<QuantifiedWhereClause>>,
58    InternedWrapper<SmallVec<[Variance; 16]>>,
59);
60
61impl chalk_ir::interner::Interner for Interner {
62    type InternedType = Interned<InternedWrapper<TyData>>;
63    type InternedLifetime = Interned<InternedWrapper<LifetimeData>>;
64    type InternedConst = Interned<InternedWrapper<ConstData>>;
65    type InternedConcreteConst = ConstScalar;
66    type InternedGenericArg = GenericArgData;
67    // We could do the following, but that saves "only" 20mb on self while increasing inference
68    // time by ~2.5%
69    // type InternedGoal = Interned<InternedWrapper<GoalData>>;
70    type InternedGoal = Arc<GoalData>;
71    type InternedGoals = Vec<Goal>;
72    type InternedSubstitution = Interned<InternedWrapper<SmallVec<[GenericArg; 2]>>>;
73    type InternedProgramClauses = Interned<InternedWrapper<Box<[ProgramClause]>>>;
74    type InternedProgramClause = ProgramClauseData;
75    type InternedQuantifiedWhereClauses = Interned<InternedWrapper<Vec<QuantifiedWhereClause>>>;
76    type InternedVariableKinds = Interned<InternedWrapper<Vec<VariableKind>>>;
77    type InternedCanonicalVarKinds = Interned<InternedWrapper<Vec<CanonicalVarKind>>>;
78    type InternedConstraints = Vec<InEnvironment<Constraint>>;
79    type InternedVariances = SmallVec<[Variance; 16]>;
80    type DefId = salsa::Id;
81    type InternedAdtId = hir_def::AdtId;
82    type Identifier = TypeAliasId;
83    type FnAbi = FnAbi;
84
85    fn debug_adt_id(
86        type_kind_id: chalk_db::AdtId,
87        fmt: &mut fmt::Formatter<'_>,
88    ) -> Option<fmt::Result> {
89        tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt)))
90    }
91
92    fn debug_trait_id(
93        type_kind_id: chalk_db::TraitId,
94        fmt: &mut fmt::Formatter<'_>,
95    ) -> Option<fmt::Result> {
96        tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt)))
97    }
98
99    fn debug_assoc_type_id(
100        id: chalk_db::AssocTypeId,
101        fmt: &mut fmt::Formatter<'_>,
102    ) -> Option<fmt::Result> {
103        tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt)))
104    }
105
106    fn debug_opaque_ty_id(
107        opaque_ty_id: OpaqueTyId,
108        fmt: &mut fmt::Formatter<'_>,
109    ) -> Option<fmt::Result> {
110        Some(write!(fmt, "OpaqueTy#{:?}", opaque_ty_id.0))
111    }
112
113    fn debug_fn_def_id(fn_def_id: FnDefId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
114        tls::with_current_program(|prog| Some(prog?.debug_fn_def_id(fn_def_id, fmt)))
115    }
116
117    fn debug_closure_id(
118        _fn_def_id: ClosureId,
119        _fmt: &mut fmt::Formatter<'_>,
120    ) -> Option<fmt::Result> {
121        None
122    }
123
124    fn debug_alias(alias: &AliasTy, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
125        use std::fmt::Debug;
126        match alias {
127            AliasTy::Projection(projection_ty) => Interner::debug_projection_ty(projection_ty, fmt),
128            AliasTy::Opaque(opaque_ty) => Some(opaque_ty.fmt(fmt)),
129        }
130    }
131
132    fn debug_projection_ty(
133        proj: &ProjectionTy,
134        fmt: &mut fmt::Formatter<'_>,
135    ) -> Option<fmt::Result> {
136        tls::with_current_program(|prog| Some(prog?.debug_projection_ty(proj, fmt)))
137            .or_else(|| Some(fmt.write_str("ProjectionTy")))
138    }
139
140    fn debug_opaque_ty(opaque_ty: &OpaqueTy, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
141        Some(write!(fmt, "{:?}", opaque_ty.opaque_ty_id))
142    }
143
144    fn debug_ty(ty: &Ty, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
145        Some(write!(fmt, "{:?}", ty.data(Interner)))
146    }
147
148    fn debug_lifetime(lifetime: &Lifetime, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
149        Some(write!(fmt, "{:?}", lifetime.data(Interner)))
150    }
151
152    fn debug_const(constant: &Const, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
153        Some(write!(fmt, "{:?}", constant.data(Interner)))
154    }
155
156    fn debug_generic_arg(
157        parameter: &GenericArg,
158        fmt: &mut fmt::Formatter<'_>,
159    ) -> Option<fmt::Result> {
160        Some(write!(fmt, "{:?}", parameter.data(Interner).inner_debug()))
161    }
162
163    fn debug_variable_kinds(
164        variable_kinds: &VariableKinds,
165        fmt: &mut fmt::Formatter<'_>,
166    ) -> Option<fmt::Result> {
167        Some(write!(fmt, "{:?}", variable_kinds.as_slice(Interner)))
168    }
169
170    fn debug_variable_kinds_with_angles(
171        variable_kinds: &VariableKinds,
172        fmt: &mut fmt::Formatter<'_>,
173    ) -> Option<fmt::Result> {
174        Some(write!(fmt, "{:?}", variable_kinds.inner_debug(Interner)))
175    }
176
177    fn debug_canonical_var_kinds(
178        canonical_var_kinds: &CanonicalVarKinds,
179        fmt: &mut fmt::Formatter<'_>,
180    ) -> Option<fmt::Result> {
181        Some(write!(fmt, "{:?}", canonical_var_kinds.as_slice(Interner)))
182    }
183    fn debug_goal(goal: &Goal, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
184        let goal_data = goal.data(Interner);
185        Some(write!(fmt, "{goal_data:?}"))
186    }
187    fn debug_goals(goals: &Goals, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> {
188        Some(write!(fmt, "{:?}", goals.debug(Interner)))
189    }
190    fn debug_program_clause_implication(
191        pci: &ProgramClauseImplication<Self>,
192        fmt: &mut fmt::Formatter<'_>,
193    ) -> Option<fmt::Result> {
194        Some(write!(fmt, "{:?}", pci.debug(Interner)))
195    }
196    fn debug_program_clause(
197        clause: &ProgramClause,
198        fmt: &mut fmt::Formatter<'_>,
199    ) -> Option<fmt::Result> {
200        Some(write!(fmt, "{:?}", clause.data(Interner)))
201    }
202    fn debug_program_clauses(
203        clauses: &ProgramClauses,
204        fmt: &mut fmt::Formatter<'_>,
205    ) -> Option<fmt::Result> {
206        Some(write!(fmt, "{:?}", clauses.as_slice(Interner)))
207    }
208    fn debug_substitution(
209        substitution: &Substitution,
210        fmt: &mut fmt::Formatter<'_>,
211    ) -> Option<fmt::Result> {
212        Some(write!(fmt, "{:?}", substitution.debug(Interner)))
213    }
214    fn debug_separator_trait_ref(
215        separator_trait_ref: &SeparatorTraitRef<'_, Interner>,
216        fmt: &mut fmt::Formatter<'_>,
217    ) -> Option<fmt::Result> {
218        Some(write!(fmt, "{:?}", separator_trait_ref.debug(Interner)))
219    }
220
221    fn debug_quantified_where_clauses(
222        clauses: &QuantifiedWhereClauses,
223        fmt: &mut fmt::Formatter<'_>,
224    ) -> Option<fmt::Result> {
225        Some(write!(fmt, "{:?}", clauses.as_slice(Interner)))
226    }
227
228    fn debug_constraints(
229        _clauses: &Constraints,
230        _fmt: &mut fmt::Formatter<'_>,
231    ) -> Option<fmt::Result> {
232        None
233    }
234
235    fn intern_ty(self, kind: TyKind) -> Self::InternedType {
236        let flags = kind.compute_flags(self);
237        Interned::new(InternedWrapper(TyData { kind, flags }))
238    }
239
240    fn ty_data(self, ty: &Self::InternedType) -> &TyData {
241        &ty.0
242    }
243
244    fn intern_lifetime(self, lifetime: LifetimeData) -> Self::InternedLifetime {
245        Interned::new(InternedWrapper(lifetime))
246    }
247
248    fn lifetime_data(self, lifetime: &Self::InternedLifetime) -> &LifetimeData {
249        &lifetime.0
250    }
251
252    fn intern_const(self, constant: ConstData) -> Self::InternedConst {
253        Interned::new(InternedWrapper(constant))
254    }
255
256    fn const_data(self, constant: &Self::InternedConst) -> &ConstData {
257        &constant.0
258    }
259
260    fn const_eq(
261        self,
262        _ty: &Self::InternedType,
263        c1: &Self::InternedConcreteConst,
264        c2: &Self::InternedConcreteConst,
265    ) -> bool {
266        !matches!(c1, ConstScalar::Bytes(..)) || !matches!(c2, ConstScalar::Bytes(..)) || (c1 == c2)
267    }
268
269    fn intern_generic_arg(self, parameter: GenericArgData) -> Self::InternedGenericArg {
270        parameter
271    }
272
273    fn generic_arg_data(self, parameter: &Self::InternedGenericArg) -> &GenericArgData {
274        parameter
275    }
276
277    fn intern_goal(self, goal: GoalData) -> Self::InternedGoal {
278        Arc::new(goal)
279    }
280
281    fn goal_data(self, goal: &Self::InternedGoal) -> &GoalData {
282        goal
283    }
284
285    fn intern_goals<E>(
286        self,
287        data: impl IntoIterator<Item = Result<Goal, E>>,
288    ) -> Result<Self::InternedGoals, E> {
289        // let hash =
290        //     std::hash::BuildHasher::hash_one(&BuildHasherDefault::<FxHasher>::default(), &goal);
291        // Interned::new(InternedWrapper(PreHashedWrapper(goal, hash)))
292        data.into_iter().collect()
293    }
294
295    fn goals_data(self, goals: &Self::InternedGoals) -> &[Goal] {
296        goals
297    }
298
299    fn intern_substitution<E>(
300        self,
301        data: impl IntoIterator<Item = Result<GenericArg, E>>,
302    ) -> Result<Self::InternedSubstitution, E> {
303        Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
304    }
305
306    fn substitution_data(self, substitution: &Self::InternedSubstitution) -> &[GenericArg] {
307        &substitution.as_ref().0
308    }
309
310    fn intern_program_clause(self, data: ProgramClauseData) -> Self::InternedProgramClause {
311        data
312    }
313
314    fn program_clause_data(self, clause: &Self::InternedProgramClause) -> &ProgramClauseData {
315        clause
316    }
317
318    fn intern_program_clauses<E>(
319        self,
320        data: impl IntoIterator<Item = Result<ProgramClause, E>>,
321    ) -> Result<Self::InternedProgramClauses, E> {
322        Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
323    }
324
325    fn program_clauses_data(self, clauses: &Self::InternedProgramClauses) -> &[ProgramClause] {
326        clauses
327    }
328
329    fn intern_quantified_where_clauses<E>(
330        self,
331        data: impl IntoIterator<Item = Result<QuantifiedWhereClause, E>>,
332    ) -> Result<Self::InternedQuantifiedWhereClauses, E> {
333        Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
334    }
335
336    fn quantified_where_clauses_data(
337        self,
338        clauses: &Self::InternedQuantifiedWhereClauses,
339    ) -> &[QuantifiedWhereClause] {
340        clauses
341    }
342
343    fn intern_generic_arg_kinds<E>(
344        self,
345        data: impl IntoIterator<Item = Result<VariableKind, E>>,
346    ) -> Result<Self::InternedVariableKinds, E> {
347        Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
348    }
349
350    fn variable_kinds_data(self, parameter_kinds: &Self::InternedVariableKinds) -> &[VariableKind] {
351        &parameter_kinds.as_ref().0
352    }
353
354    fn intern_canonical_var_kinds<E>(
355        self,
356        data: impl IntoIterator<Item = Result<CanonicalVarKind, E>>,
357    ) -> Result<Self::InternedCanonicalVarKinds, E> {
358        Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
359    }
360
361    fn canonical_var_kinds_data(
362        self,
363        canonical_var_kinds: &Self::InternedCanonicalVarKinds,
364    ) -> &[CanonicalVarKind] {
365        canonical_var_kinds
366    }
367    fn intern_constraints<E>(
368        self,
369        data: impl IntoIterator<Item = Result<InEnvironment<Constraint>, E>>,
370    ) -> Result<Self::InternedConstraints, E> {
371        data.into_iter().collect()
372    }
373    fn constraints_data(
374        self,
375        constraints: &Self::InternedConstraints,
376    ) -> &[InEnvironment<Constraint>] {
377        constraints
378    }
379
380    fn intern_variances<E>(
381        self,
382        data: impl IntoIterator<Item = Result<Variance, E>>,
383    ) -> Result<Self::InternedVariances, E> {
384        data.into_iter().collect::<Result<_, _>>()
385    }
386
387    fn variances_data(self, variances: &Self::InternedVariances) -> &[Variance] {
388        variances
389    }
390}
391
392impl chalk_ir::interner::HasInterner for Interner {
393    type Interner = Self;
394}
395
396#[macro_export]
397macro_rules! has_interner {
398    ($t:ty) => {
399        impl HasInterner for $t {
400            type Interner = $crate::Interner;
401        }
402    };
403}