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