chalk_solve/infer/
instantiate.rs1use chalk_ir::fold::*;
2use chalk_ir::interner::HasInterner;
3use std::fmt::Debug;
4use tracing::instrument;
5
6use super::*;
7
8impl<I: Interner> InferenceTable<I> {
9 pub(super) fn fresh_subst(
15 &mut self,
16 interner: I,
17 binders: &[CanonicalVarKind<I>],
18 ) -> Substitution<I> {
19 Substitution::from_iter(
20 interner,
21 binders.iter().map(|kind| {
22 let param_infer_var = kind.map_ref(|&ui| self.new_variable(ui));
23 param_infer_var.to_generic_arg(interner)
24 }),
25 )
26 }
27
28 pub fn instantiate_canonical<T>(&mut self, interner: I, bound: Canonical<T>) -> T
30 where
31 T: HasInterner<Interner = I> + TypeFoldable<I> + Debug,
32 {
33 let subst = self.fresh_subst(interner, bound.binders.as_slice(interner));
34 subst.apply(bound.value, interner)
35 }
36
37 fn instantiate_in<T>(
43 &mut self,
44 interner: I,
45 universe: UniverseIndex,
46 binders: impl Iterator<Item = VariableKind<I>>,
47 arg: T,
48 ) -> T
49 where
50 T: TypeFoldable<I>,
51 {
52 let binders: Vec<_> = binders
53 .map(|pk| CanonicalVarKind::new(pk, universe))
54 .collect();
55 let subst = self.fresh_subst(interner, &binders);
56 subst.apply(arg, interner)
57 }
58
59 #[instrument(level = "debug", skip(self, interner))]
61 pub fn instantiate_binders_existentially<T>(&mut self, interner: I, arg: Binders<T>) -> T
62 where
63 T: TypeFoldable<I> + HasInterner<Interner = I>,
64 {
65 let (value, binders) = arg.into_value_and_skipped_binders();
66
67 let max_universe = self.max_universe;
68 self.instantiate_in(
69 interner,
70 max_universe,
71 binders.iter(interner).cloned(),
72 value,
73 )
74 }
75
76 #[instrument(level = "debug", skip(self, interner))]
77 pub fn instantiate_binders_universally<T>(&mut self, interner: I, arg: Binders<T>) -> T
78 where
79 T: TypeFoldable<I> + HasInterner<Interner = I>,
80 {
81 let (value, binders) = arg.into_value_and_skipped_binders();
82
83 let mut lazy_ui = None;
84 let mut ui = || {
85 lazy_ui.unwrap_or_else(|| {
86 let ui = self.new_universe();
87 lazy_ui = Some(ui);
88 ui
89 })
90 };
91 let parameters: Vec<_> = binders
92 .iter(interner)
93 .cloned()
94 .enumerate()
95 .map(|(idx, pk)| {
96 let placeholder_idx = PlaceholderIndex { ui: ui(), idx };
97 match pk {
98 VariableKind::Lifetime => {
99 let lt = placeholder_idx.to_lifetime(interner);
100 lt.cast(interner)
101 }
102 VariableKind::Ty(_) => placeholder_idx.to_ty(interner).cast(interner),
103 VariableKind::Const(ty) => {
104 placeholder_idx.to_const(interner, ty).cast(interner)
105 }
106 }
107 })
108 .collect();
109 Subst::apply(interner, ¶meters, value)
110 }
111}