]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/subst.rs
std: Rename Show/String to Debug/Display
[rust.git] / src / librustc / middle / subst.rs
1 // Copyright 2012 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 // Type substitutions.
12
13 pub use self::ParamSpace::*;
14 pub use self::RegionSubsts::*;
15
16 use middle::ty::{self, Ty};
17 use middle::ty_fold::{self, TypeFoldable, TypeFolder};
18 use util::ppaux::Repr;
19
20 use std::fmt;
21 use std::slice::Iter;
22 use std::vec::{Vec, IntoIter};
23 use syntax::codemap::{Span, DUMMY_SP};
24
25 ///////////////////////////////////////////////////////////////////////////
26
27 /// A substitution mapping type/region parameters to new values. We
28 /// identify each in-scope parameter by an *index* and a *parameter
29 /// space* (which indices where the parameter is defined; see
30 /// `ParamSpace`).
31 #[derive(Clone, PartialEq, Eq, Hash, Show)]
32 pub struct Substs<'tcx> {
33     pub types: VecPerParamSpace<Ty<'tcx>>,
34     pub regions: RegionSubsts,
35 }
36
37 /// Represents the values to use when substituting lifetime parameters.
38 /// If the value is `ErasedRegions`, then this subst is occurring during
39 /// trans, and all region parameters will be replaced with `ty::ReStatic`.
40 #[derive(Clone, PartialEq, Eq, Hash, Show)]
41 pub enum RegionSubsts {
42     ErasedRegions,
43     NonerasedRegions(VecPerParamSpace<ty::Region>)
44 }
45
46 impl<'tcx> Substs<'tcx> {
47     pub fn new(t: VecPerParamSpace<Ty<'tcx>>,
48                r: VecPerParamSpace<ty::Region>)
49                -> Substs<'tcx>
50     {
51         Substs { types: t, regions: NonerasedRegions(r) }
52     }
53
54     pub fn new_type(t: Vec<Ty<'tcx>>,
55                     r: Vec<ty::Region>)
56                     -> Substs<'tcx>
57     {
58         Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new()),
59                     VecPerParamSpace::new(r, Vec::new(), Vec::new()))
60     }
61
62     pub fn new_trait(t: Vec<Ty<'tcx>>,
63                      r: Vec<ty::Region>,
64                      s: Ty<'tcx>)
65                     -> Substs<'tcx>
66     {
67         Substs::new(VecPerParamSpace::new(t, vec!(s), Vec::new()),
68                     VecPerParamSpace::new(r, Vec::new(), Vec::new()))
69     }
70
71     pub fn erased(t: VecPerParamSpace<Ty<'tcx>>) -> Substs<'tcx>
72     {
73         Substs { types: t, regions: ErasedRegions }
74     }
75
76     pub fn empty() -> Substs<'tcx> {
77         Substs {
78             types: VecPerParamSpace::empty(),
79             regions: NonerasedRegions(VecPerParamSpace::empty()),
80         }
81     }
82
83     pub fn trans_empty() -> Substs<'tcx> {
84         Substs {
85             types: VecPerParamSpace::empty(),
86             regions: ErasedRegions
87         }
88     }
89
90     pub fn is_noop(&self) -> bool {
91         let regions_is_noop = match self.regions {
92             ErasedRegions => false, // may be used to canonicalize
93             NonerasedRegions(ref regions) => regions.is_empty(),
94         };
95
96         regions_is_noop && self.types.is_empty()
97     }
98
99     pub fn type_for_def(&self, ty_param_def: &ty::TypeParameterDef) -> Ty<'tcx> {
100         *self.types.get(ty_param_def.space, ty_param_def.index as uint)
101     }
102
103     pub fn has_regions_escaping_depth(&self, depth: u32) -> bool {
104         self.types.iter().any(|&t| ty::type_escapes_depth(t, depth)) || {
105             match self.regions {
106                 ErasedRegions =>
107                     false,
108                 NonerasedRegions(ref regions) =>
109                     regions.iter().any(|r| r.escapes_depth(depth)),
110             }
111         }
112     }
113
114     pub fn self_ty(&self) -> Option<Ty<'tcx>> {
115         self.types.get_self().map(|&t| t)
116     }
117
118     pub fn with_self_ty(&self, self_ty: Ty<'tcx>) -> Substs<'tcx> {
119         assert!(self.self_ty().is_none());
120         let mut s = (*self).clone();
121         s.types.push(SelfSpace, self_ty);
122         s
123     }
124
125     pub fn erase_regions(self) -> Substs<'tcx> {
126         let Substs { types, regions: _ } = self;
127         Substs { types: types, regions: ErasedRegions }
128     }
129
130     /// Since ErasedRegions are only to be used in trans, most of the compiler can use this method
131     /// to easily access the set of region substitutions.
132     pub fn regions<'a>(&'a self) -> &'a VecPerParamSpace<ty::Region> {
133         match self.regions {
134             ErasedRegions => panic!("Erased regions only expected in trans"),
135             NonerasedRegions(ref r) => r
136         }
137     }
138
139     /// Since ErasedRegions are only to be used in trans, most of the compiler can use this method
140     /// to easily access the set of region substitutions.
141     pub fn mut_regions<'a>(&'a mut self) -> &'a mut VecPerParamSpace<ty::Region> {
142         match self.regions {
143             ErasedRegions => panic!("Erased regions only expected in trans"),
144             NonerasedRegions(ref mut r) => r
145         }
146     }
147
148     pub fn with_method(self,
149                        m_types: Vec<Ty<'tcx>>,
150                        m_regions: Vec<ty::Region>)
151                        -> Substs<'tcx>
152     {
153         let Substs { types, regions } = self;
154         let types = types.with_vec(FnSpace, m_types);
155         let regions = regions.map(m_regions,
156                                   |r, m_regions| r.with_vec(FnSpace, m_regions));
157         Substs { types: types, regions: regions }
158     }
159 }
160
161 impl RegionSubsts {
162     fn map<A, F>(self, a: A, op: F) -> RegionSubsts where
163         F: FnOnce(VecPerParamSpace<ty::Region>, A) -> VecPerParamSpace<ty::Region>,
164     {
165         match self {
166             ErasedRegions => ErasedRegions,
167             NonerasedRegions(r) => NonerasedRegions(op(r, a))
168         }
169     }
170
171     pub fn is_erased(&self) -> bool {
172         match *self {
173             ErasedRegions => true,
174             NonerasedRegions(_) => false,
175         }
176     }
177 }
178
179 ///////////////////////////////////////////////////////////////////////////
180 // ParamSpace
181
182 #[derive(PartialOrd, Ord, PartialEq, Eq, Copy,
183            Clone, Hash, RustcEncodable, RustcDecodable, Show)]
184 pub enum ParamSpace {
185     TypeSpace,  // Type parameters attached to a type definition, trait, or impl
186     SelfSpace,  // Self parameter on a trait
187     FnSpace,    // Type parameters attached to a method or fn
188 }
189
190 impl ParamSpace {
191     pub fn all() -> [ParamSpace; 3] {
192         [TypeSpace, SelfSpace, FnSpace]
193     }
194
195     pub fn to_uint(self) -> uint {
196         match self {
197             TypeSpace => 0,
198             SelfSpace => 1,
199             FnSpace => 2,
200         }
201     }
202
203     pub fn from_uint(u: uint) -> ParamSpace {
204         match u {
205             0 => TypeSpace,
206             1 => SelfSpace,
207             2 => FnSpace,
208             _ => panic!("Invalid ParamSpace: {}", u)
209         }
210     }
211 }
212
213 /// Vector of things sorted by param space. Used to keep
214 /// the set of things declared on the type, self, or method
215 /// distinct.
216 #[derive(PartialEq, Eq, Clone, Hash, RustcEncodable, RustcDecodable)]
217 pub struct VecPerParamSpace<T> {
218     // This was originally represented as a tuple with one Vec<T> for
219     // each variant of ParamSpace, and that remains the abstraction
220     // that it provides to its clients.
221     //
222     // Here is how the representation corresponds to the abstraction
223     // i.e. the "abstraction function" AF:
224     //
225     // AF(self) = (self.content[..self.type_limit],
226     //             self.content[self.type_limit..self.self_limit],
227     //             self.content[self.self_limit..])
228     type_limit: uint,
229     self_limit: uint,
230     content: Vec<T>,
231 }
232
233 /// The `split` function converts one `VecPerParamSpace` into this
234 /// `SeparateVecsPerParamSpace` structure.
235 pub struct SeparateVecsPerParamSpace<T> {
236     pub types: Vec<T>,
237     pub selfs: Vec<T>,
238     pub fns: Vec<T>,
239 }
240
241 impl<T: fmt::Debug> fmt::Debug for VecPerParamSpace<T> {
242     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
243         try!(write!(fmt, "VecPerParamSpace {{"));
244         for space in ParamSpace::all().iter() {
245             try!(write!(fmt, "{:?}: {:?}, ", *space, self.get_slice(*space)));
246         }
247         try!(write!(fmt, "}}"));
248         Ok(())
249     }
250 }
251
252 impl<T> VecPerParamSpace<T> {
253     fn limits(&self, space: ParamSpace) -> (uint, uint) {
254         match space {
255             TypeSpace => (0, self.type_limit),
256             SelfSpace => (self.type_limit, self.self_limit),
257             FnSpace => (self.self_limit, self.content.len()),
258         }
259     }
260
261     pub fn empty() -> VecPerParamSpace<T> {
262         VecPerParamSpace {
263             type_limit: 0,
264             self_limit: 0,
265             content: Vec::new()
266         }
267     }
268
269     pub fn params_from_type(types: Vec<T>) -> VecPerParamSpace<T> {
270         VecPerParamSpace::empty().with_vec(TypeSpace, types)
271     }
272
273     /// `t` is the type space.
274     /// `s` is the self space.
275     /// `a` is the assoc space.
276     /// `f` is the fn space.
277     pub fn new(t: Vec<T>, s: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
278         let type_limit = t.len();
279         let self_limit = type_limit + s.len();
280
281         let mut content = t;
282         content.extend(s.into_iter());
283         content.extend(f.into_iter());
284
285         VecPerParamSpace {
286             type_limit: type_limit,
287             self_limit: self_limit,
288             content: content,
289         }
290     }
291
292     fn new_internal(content: Vec<T>, type_limit: uint, self_limit: uint)
293                     -> VecPerParamSpace<T>
294     {
295         VecPerParamSpace {
296             type_limit: type_limit,
297             self_limit: self_limit,
298             content: content,
299         }
300     }
301
302     /// Appends `value` to the vector associated with `space`.
303     ///
304     /// Unlike the `push` method in `Vec`, this should not be assumed
305     /// to be a cheap operation (even when amortized over many calls).
306     pub fn push(&mut self, space: ParamSpace, value: T) {
307         let (_, limit) = self.limits(space);
308         match space {
309             TypeSpace => { self.type_limit += 1; self.self_limit += 1; }
310             SelfSpace => { self.self_limit += 1; }
311             FnSpace => { }
312         }
313         self.content.insert(limit, value);
314     }
315
316     /// Appends `values` to the vector associated with `space`.
317     ///
318     /// Unlike the `extend` method in `Vec`, this should not be assumed
319     /// to be a cheap operation (even when amortized over many calls).
320     pub fn extend<I:Iterator<Item=T>>(&mut self, space: ParamSpace, mut values: I) {
321         // This could be made more efficient, obviously.
322         for item in values {
323             self.push(space, item);
324         }
325     }
326
327     pub fn pop(&mut self, space: ParamSpace) -> Option<T> {
328         let (start, limit) = self.limits(space);
329         if start == limit {
330             None
331         } else {
332             match space {
333                 TypeSpace => { self.type_limit -= 1; self.self_limit -= 1; }
334                 SelfSpace => { self.self_limit -= 1; }
335                 FnSpace => {}
336             }
337             if self.content.is_empty() {
338                 None
339             } else {
340                 Some(self.content.remove(limit - 1))
341             }
342         }
343     }
344
345     pub fn truncate(&mut self, space: ParamSpace, len: uint) {
346         // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
347         while self.len(space) > len {
348             self.pop(space);
349         }
350     }
351
352     pub fn replace(&mut self, space: ParamSpace, elems: Vec<T>) {
353         // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
354         self.truncate(space, 0);
355         for t in elems.into_iter() {
356             self.push(space, t);
357         }
358     }
359
360     pub fn get_self<'a>(&'a self) -> Option<&'a T> {
361         let v = self.get_slice(SelfSpace);
362         assert!(v.len() <= 1);
363         if v.len() == 0 { None } else { Some(&v[0]) }
364     }
365
366     pub fn len(&self, space: ParamSpace) -> uint {
367         self.get_slice(space).len()
368     }
369
370     pub fn is_empty_in(&self, space: ParamSpace) -> bool {
371         self.len(space) == 0
372     }
373
374     pub fn get_slice<'a>(&'a self, space: ParamSpace) -> &'a [T] {
375         let (start, limit) = self.limits(space);
376         self.content.slice(start, limit)
377     }
378
379     pub fn get_mut_slice<'a>(&'a mut self, space: ParamSpace) -> &'a mut [T] {
380         let (start, limit) = self.limits(space);
381         self.content.slice_mut(start, limit)
382     }
383
384     pub fn opt_get<'a>(&'a self,
385                        space: ParamSpace,
386                        index: uint)
387                        -> Option<&'a T> {
388         let v = self.get_slice(space);
389         if index < v.len() { Some(&v[index]) } else { None }
390     }
391
392     pub fn get<'a>(&'a self, space: ParamSpace, index: uint) -> &'a T {
393         &self.get_slice(space)[index]
394     }
395
396     pub fn iter<'a>(&'a self) -> Iter<'a,T> {
397         self.content.iter()
398     }
399
400     pub fn into_iter(self) -> IntoIter<T> {
401         self.content.into_iter()
402     }
403
404     pub fn iter_enumerated<'a>(&'a self) -> EnumeratedItems<'a,T> {
405         EnumeratedItems::new(self)
406     }
407
408     pub fn as_slice(&self) -> &[T] {
409         self.content.as_slice()
410     }
411
412     pub fn into_vec(self) -> Vec<T> {
413         self.content
414     }
415
416     pub fn all_vecs<P>(&self, mut pred: P) -> bool where
417         P: FnMut(&[T]) -> bool,
418     {
419         let spaces = [TypeSpace, SelfSpace, FnSpace];
420         spaces.iter().all(|&space| { pred(self.get_slice(space)) })
421     }
422
423     pub fn all<P>(&self, pred: P) -> bool where P: FnMut(&T) -> bool {
424         self.iter().all(pred)
425     }
426
427     pub fn any<P>(&self, pred: P) -> bool where P: FnMut(&T) -> bool {
428         self.iter().any(pred)
429     }
430
431     pub fn is_empty(&self) -> bool {
432         self.all_vecs(|v| v.is_empty())
433     }
434
435     pub fn map<U, P>(&self, pred: P) -> VecPerParamSpace<U> where P: FnMut(&T) -> U {
436         let result = self.iter().map(pred).collect();
437         VecPerParamSpace::new_internal(result,
438                                        self.type_limit,
439                                        self.self_limit)
440     }
441
442     pub fn map_enumerated<U, P>(&self, pred: P) -> VecPerParamSpace<U> where
443         P: FnMut((ParamSpace, uint, &T)) -> U,
444     {
445         let result = self.iter_enumerated().map(pred).collect();
446         VecPerParamSpace::new_internal(result,
447                                        self.type_limit,
448                                        self.self_limit)
449     }
450
451     pub fn map_move<U, F>(self, mut pred: F) -> VecPerParamSpace<U> where
452         F: FnMut(T) -> U,
453     {
454         let SeparateVecsPerParamSpace {
455             types: t,
456             selfs: s,
457             fns: f
458         } = self.split();
459
460         VecPerParamSpace::new(t.into_iter().map(|p| pred(p)).collect(),
461                               s.into_iter().map(|p| pred(p)).collect(),
462                               f.into_iter().map(|p| pred(p)).collect())
463     }
464
465     pub fn split(self) -> SeparateVecsPerParamSpace<T> {
466         let VecPerParamSpace { type_limit, self_limit, content } = self;
467
468         let mut content_iter = content.into_iter();
469
470         SeparateVecsPerParamSpace {
471             types: content_iter.by_ref().take(type_limit).collect(),
472             selfs: content_iter.by_ref().take(self_limit - type_limit).collect(),
473             fns: content_iter.collect()
474         }
475     }
476
477     pub fn with_vec(mut self, space: ParamSpace, vec: Vec<T>)
478                     -> VecPerParamSpace<T>
479     {
480         assert!(self.is_empty_in(space));
481         self.replace(space, vec);
482         self
483     }
484 }
485
486 #[derive(Clone)]
487 pub struct EnumeratedItems<'a,T:'a> {
488     vec: &'a VecPerParamSpace<T>,
489     space_index: uint,
490     elem_index: uint
491 }
492
493 impl<'a,T> EnumeratedItems<'a,T> {
494     fn new(v: &'a VecPerParamSpace<T>) -> EnumeratedItems<'a,T> {
495         let mut result = EnumeratedItems { vec: v, space_index: 0, elem_index: 0 };
496         result.adjust_space();
497         result
498     }
499
500     fn adjust_space(&mut self) {
501         let spaces = ParamSpace::all();
502         while
503             self.space_index < spaces.len() &&
504             self.elem_index >= self.vec.len(spaces[self.space_index])
505         {
506             self.space_index += 1;
507             self.elem_index = 0;
508         }
509     }
510 }
511
512 impl<'a,T> Iterator for EnumeratedItems<'a,T> {
513     type Item = (ParamSpace, uint, &'a T);
514
515     fn next(&mut self) -> Option<(ParamSpace, uint, &'a T)> {
516         let spaces = ParamSpace::all();
517         if self.space_index < spaces.len() {
518             let space = spaces[self.space_index];
519             let index = self.elem_index;
520             let item = self.vec.get(space, index);
521
522             self.elem_index += 1;
523             self.adjust_space();
524
525             Some((space, index, item))
526         } else {
527             None
528         }
529     }
530 }
531
532 ///////////////////////////////////////////////////////////////////////////
533 // Public trait `Subst`
534 //
535 // Just call `foo.subst(tcx, substs)` to perform a substitution across
536 // `foo`. Or use `foo.subst_spanned(tcx, substs, Some(span))` when
537 // there is more information available (for better errors).
538
539 pub trait Subst<'tcx> : Sized {
540     fn subst(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>) -> Self {
541         self.subst_spanned(tcx, substs, None)
542     }
543
544     fn subst_spanned(&self, tcx: &ty::ctxt<'tcx>,
545                      substs: &Substs<'tcx>,
546                      span: Option<Span>)
547                      -> Self;
548 }
549
550 impl<'tcx, T:TypeFoldable<'tcx>> Subst<'tcx> for T {
551     fn subst_spanned(&self,
552                      tcx: &ty::ctxt<'tcx>,
553                      substs: &Substs<'tcx>,
554                      span: Option<Span>)
555                      -> T
556     {
557         let mut folder = SubstFolder { tcx: tcx,
558                                        substs: substs,
559                                        span: span,
560                                        root_ty: None,
561                                        ty_stack_depth: 0,
562                                        region_binders_passed: 0 };
563         (*self).fold_with(&mut folder)
564     }
565 }
566
567 ///////////////////////////////////////////////////////////////////////////
568 // The actual substitution engine itself is a type folder.
569
570 struct SubstFolder<'a, 'tcx: 'a> {
571     tcx: &'a ty::ctxt<'tcx>,
572     substs: &'a Substs<'tcx>,
573
574     // The location for which the substitution is performed, if available.
575     span: Option<Span>,
576
577     // The root type that is being substituted, if available.
578     root_ty: Option<Ty<'tcx>>,
579
580     // Depth of type stack
581     ty_stack_depth: uint,
582
583     // Number of region binders we have passed through while doing the substitution
584     region_binders_passed: u32,
585 }
586
587 impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
588     fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
589
590     fn enter_region_binder(&mut self) {
591         self.region_binders_passed += 1;
592     }
593
594     fn exit_region_binder(&mut self) {
595         self.region_binders_passed -= 1;
596     }
597
598     fn fold_region(&mut self, r: ty::Region) -> ty::Region {
599         // Note: This routine only handles regions that are bound on
600         // type declarations and other outer declarations, not those
601         // bound in *fn types*. Region substitution of the bound
602         // regions that appear in a function signature is done using
603         // the specialized routine `ty::replace_late_regions()`.
604         match r {
605             ty::ReEarlyBound(_, space, i, region_name) => {
606                 match self.substs.regions {
607                     ErasedRegions => ty::ReStatic,
608                     NonerasedRegions(ref regions) =>
609                         match regions.opt_get(space, i as uint) {
610                             Some(&r) => {
611                                 self.shift_region_through_binders(r)
612                             }
613                             None => {
614                                 let span = self.span.unwrap_or(DUMMY_SP);
615                                 self.tcx().sess.span_bug(
616                                     span,
617                                     &format!("Type parameter out of range \
618                                      when substituting in region {} (root type={}) \
619                                      (space={:?}, index={})",
620                                     region_name.as_str(),
621                                     self.root_ty.repr(self.tcx()),
622                                     space, i)[]);
623                             }
624                         }
625                 }
626             }
627             _ => r
628         }
629     }
630
631     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
632         if !ty::type_needs_subst(t) {
633             return t;
634         }
635
636         // track the root type we were asked to substitute
637         let depth = self.ty_stack_depth;
638         if depth == 0 {
639             self.root_ty = Some(t);
640         }
641         self.ty_stack_depth += 1;
642
643         let t1 = match t.sty {
644             ty::ty_param(p) => {
645                 self.ty_for_param(p, t)
646             }
647             _ => {
648                 ty_fold::super_fold_ty(self, t)
649             }
650         };
651
652         assert_eq!(depth + 1, self.ty_stack_depth);
653         self.ty_stack_depth -= 1;
654         if depth == 0 {
655             self.root_ty = None;
656         }
657
658         return t1;
659     }
660 }
661
662 impl<'a,'tcx> SubstFolder<'a,'tcx> {
663     fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> {
664         // Look up the type in the substitutions. It really should be in there.
665         let opt_ty = self.substs.types.opt_get(p.space, p.idx as uint);
666         let ty = match opt_ty {
667             Some(t) => *t,
668             None => {
669                 let span = self.span.unwrap_or(DUMMY_SP);
670                 self.tcx().sess.span_bug(
671                     span,
672                     &format!("Type parameter `{}` ({}/{:?}/{}) out of range \
673                                  when substituting (root type={}) substs={}",
674                             p.repr(self.tcx()),
675                             source_ty.repr(self.tcx()),
676                             p.space,
677                             p.idx,
678                             self.root_ty.repr(self.tcx()),
679                             self.substs.repr(self.tcx()))[]);
680             }
681         };
682
683         self.shift_regions_through_binders(ty)
684     }
685
686     /// It is sometimes necessary to adjust the debruijn indices during substitution. This occurs
687     /// when we are substituting a type with escaping regions into a context where we have passed
688     /// through region binders. That's quite a mouthful. Let's see an example:
689     ///
690     /// ```
691     /// type Func<A> = fn(A);
692     /// type MetaFunc = for<'a> fn(Func<&'a int>)
693     /// ```
694     ///
695     /// The type `MetaFunc`, when fully expanded, will be
696     ///
697     ///     for<'a> fn(fn(&'a int))
698     ///             ^~ ^~ ^~~
699     ///             |  |  |
700     ///             |  |  DebruijnIndex of 2
701     ///             Binders
702     ///
703     /// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the
704     /// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip
705     /// over the inner binder (remember that we count Debruijn indices from 1). However, in the
706     /// definition of `MetaFunc`, the binder is not visible, so the type `&'a int` will have a
707     /// debruijn index of 1. It's only during the substitution that we can see we must increase the
708     /// depth by 1 to account for the binder that we passed through.
709     ///
710     /// As a second example, consider this twist:
711     ///
712     /// ```
713     /// type FuncTuple<A> = (A,fn(A));
714     /// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a int>)
715     /// ```
716     ///
717     /// Here the final type will be:
718     ///
719     ///     for<'a> fn((&'a int, fn(&'a int)))
720     ///                 ^~~         ^~~
721     ///                 |           |
722     ///          DebruijnIndex of 1 |
723     ///                      DebruijnIndex of 2
724     ///
725     /// As indicated in the diagram, here the same type `&'a int` is substituted once, but in the
726     /// first case we do not increase the Debruijn index and in the second case we do. The reason
727     /// is that only in the second case have we passed through a fn binder.
728     fn shift_regions_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
729         debug!("shift_regions(ty={:?}, region_binders_passed={:?}, type_has_escaping_regions={:?})",
730                ty.repr(self.tcx()), self.region_binders_passed, ty::type_has_escaping_regions(ty));
731
732         if self.region_binders_passed == 0 || !ty::type_has_escaping_regions(ty) {
733             return ty;
734         }
735
736         let result = ty_fold::shift_regions(self.tcx(), self.region_binders_passed, &ty);
737         debug!("shift_regions: shifted result = {:?}", result.repr(self.tcx()));
738
739         result
740     }
741
742     fn shift_region_through_binders(&self, region: ty::Region) -> ty::Region {
743         ty_fold::shift_region(region, self.region_binders_passed)
744     }
745 }