@@ -162,3 +162,107 @@ where
162162 if p. has_vars_bound_at_or_above ( self . current_index ) { p. super_fold_with ( self ) } else { p }
163163 }
164164}
165+
166+ /// The inverse of [`BoundVarReplacer`]: replaces placeholders with the bound vars from which
167+ /// they came.
168+ pub struct PlaceholderReplacer < ' a , I : Interner > {
169+ cx : I ,
170+ mapped_regions : IndexMap < ty:: PlaceholderRegion < I > , ty:: BoundRegion < I > > ,
171+ mapped_types : IndexMap < ty:: PlaceholderType < I > , ty:: BoundTy < I > > ,
172+ mapped_consts : IndexMap < ty:: PlaceholderConst < I > , ty:: BoundConst < I > > ,
173+ universe_indices : & ' a [ Option < ty:: UniverseIndex > ] ,
174+ current_index : ty:: DebruijnIndex ,
175+ }
176+
177+ impl < ' a , I : Interner > PlaceholderReplacer < ' a , I > {
178+ pub fn replace_placeholders < T : TypeFoldable < I > > (
179+ cx : I ,
180+ mapped_regions : IndexMap < ty:: PlaceholderRegion < I > , ty:: BoundRegion < I > > ,
181+ mapped_types : IndexMap < ty:: PlaceholderType < I > , ty:: BoundTy < I > > ,
182+ mapped_consts : IndexMap < ty:: PlaceholderConst < I > , ty:: BoundConst < I > > ,
183+ universe_indices : & ' a [ Option < ty:: UniverseIndex > ] ,
184+ value : T ,
185+ ) -> T {
186+ let mut replacer = PlaceholderReplacer {
187+ cx,
188+ mapped_regions,
189+ mapped_types,
190+ mapped_consts,
191+ universe_indices,
192+ current_index : ty:: INNERMOST ,
193+ } ;
194+ value. fold_with ( & mut replacer)
195+ }
196+
197+ fn debruijn_for_universe ( & self , universe : ty:: UniverseIndex ) -> ty:: DebruijnIndex {
198+ let index = self
199+ . universe_indices
200+ . iter ( )
201+ . position ( |u| matches ! ( u, Some ( u_idx) if * u_idx == universe) )
202+ . unwrap_or_else ( || panic ! ( "unexpected placeholder universe {universe:?}" ) ) ;
203+
204+ ty:: DebruijnIndex :: from_usize (
205+ self . universe_indices . len ( ) - index + self . current_index . as_usize ( ) - 1 ,
206+ )
207+ }
208+ }
209+
210+ impl < I : Interner > TypeFolder < I > for PlaceholderReplacer < ' _ , I > {
211+ fn cx ( & self ) -> I {
212+ self . cx
213+ }
214+
215+ fn fold_binder < T : TypeFoldable < I > > ( & mut self , t : ty:: Binder < I , T > ) -> ty:: Binder < I , T > {
216+ if !t. has_placeholders ( ) && !t. has_infer ( ) {
217+ return t;
218+ }
219+
220+ self . current_index . shift_in ( 1 ) ;
221+ let t = t. super_fold_with ( self ) ;
222+ self . current_index . shift_out ( 1 ) ;
223+ t
224+ }
225+
226+ fn fold_region ( & mut self , r : I :: Region ) -> I :: Region {
227+ if let ty:: RePlaceholder ( p) = r. kind ( ) {
228+ if let Some ( replace_var) = self . mapped_regions . get ( & p) {
229+ let db = self . debruijn_for_universe ( p. universe ( ) ) ;
230+ return Region :: new_bound ( self . cx ( ) , db, * replace_var) ;
231+ }
232+ }
233+
234+ r
235+ }
236+
237+ fn fold_ty ( & mut self , ty : I :: Ty ) -> I :: Ty {
238+ if let ty:: Placeholder ( p) = ty. kind ( ) {
239+ match self . mapped_types . get ( & p) {
240+ Some ( replace_var) => {
241+ let db = self . debruijn_for_universe ( p. universe ( ) ) ;
242+ Ty :: new_bound ( self . cx ( ) , db, * replace_var)
243+ }
244+ None => ty,
245+ }
246+ } else if ty. has_placeholders ( ) || ty. has_infer ( ) {
247+ ty. super_fold_with ( self )
248+ } else {
249+ ty
250+ }
251+ }
252+
253+ fn fold_const ( & mut self , ct : I :: Const ) -> I :: Const {
254+ if let ty:: ConstKind :: Placeholder ( p) = ct. kind ( ) {
255+ match self . mapped_consts . get ( & p) {
256+ Some ( replace_var) => {
257+ let db = self . debruijn_for_universe ( p. universe ( ) ) ;
258+ Const :: new_bound ( self . cx ( ) , db, * replace_var)
259+ }
260+ None => ct,
261+ }
262+ } else if ct. has_placeholders ( ) || ct. has_infer ( ) {
263+ ct. super_fold_with ( self )
264+ } else {
265+ ct
266+ }
267+ }
268+ }
0 commit comments