rustc_infer/infer/canonical/
instantiate.rs
1use rustc_macros::extension;
10use rustc_middle::bug;
11use rustc_middle::ty::fold::{FnMutDelegate, TypeFoldable};
12use rustc_middle::ty::{self, GenericArgKind, TyCtxt};
13
14use crate::infer::canonical::{Canonical, CanonicalVarValues};
15
16#[extension(pub trait CanonicalExt<'tcx, V>)]
19impl<'tcx, V> Canonical<'tcx, V> {
20 fn instantiate(&self, tcx: TyCtxt<'tcx>, var_values: &CanonicalVarValues<'tcx>) -> V
23 where
24 V: TypeFoldable<TyCtxt<'tcx>>,
25 {
26 self.instantiate_projected(tcx, var_values, |value| value.clone())
27 }
28
29 fn instantiate_projected<T>(
36 &self,
37 tcx: TyCtxt<'tcx>,
38 var_values: &CanonicalVarValues<'tcx>,
39 projection_fn: impl FnOnce(&V) -> T,
40 ) -> T
41 where
42 T: TypeFoldable<TyCtxt<'tcx>>,
43 {
44 assert_eq!(self.variables.len(), var_values.len());
45 let value = projection_fn(&self.value);
46 instantiate_value(tcx, var_values, value)
47 }
48}
49
50pub(super) fn instantiate_value<'tcx, T>(
54 tcx: TyCtxt<'tcx>,
55 var_values: &CanonicalVarValues<'tcx>,
56 value: T,
57) -> T
58where
59 T: TypeFoldable<TyCtxt<'tcx>>,
60{
61 if var_values.var_values.is_empty() {
62 value
63 } else {
64 let delegate = FnMutDelegate {
65 regions: &mut |br: ty::BoundRegion| match var_values[br.var].unpack() {
66 GenericArgKind::Lifetime(l) => l,
67 r => bug!("{:?} is a region but value is {:?}", br, r),
68 },
69 types: &mut |bound_ty: ty::BoundTy| match var_values[bound_ty.var].unpack() {
70 GenericArgKind::Type(ty) => ty,
71 r => bug!("{:?} is a type but value is {:?}", bound_ty, r),
72 },
73 consts: &mut |bound_ct: ty::BoundVar| match var_values[bound_ct].unpack() {
74 GenericArgKind::Const(ct) => ct,
75 c => bug!("{:?} is a const but value is {:?}", bound_ct, c),
76 },
77 };
78
79 tcx.replace_escaping_bound_vars_uncached(value, delegate)
80 }
81}