]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/ty_fold.rs
doc: remove incomplete sentence
[rust.git] / src / librustc / middle / ty_fold.rs
1 // Copyright 2012-2013 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 //! Generalized type folding mechanism. The setup is a bit convoluted
12 //! but allows for convenient usage. Let T be an instance of some
13 //! "foldable type" (one which implements `TypeFoldable`) and F be an
14 //! instance of a "folder" (a type which implements `TypeFolder`). Then
15 //! the setup is intended to be:
16 //!
17 //!     T.fold_with(F) --calls--> F.fold_T(T) --calls--> super_fold_T(F, T)
18 //!
19 //! This way, when you define a new folder F, you can override
20 //! `fold_T()` to customize the behavior, and invoke `super_fold_T()`
21 //! to get the original behavior. Meanwhile, to actually fold
22 //! something, you can just write `T.fold_with(F)`, which is
23 //! convenient. (Note that `fold_with` will also transparently handle
24 //! things like a `Vec<T>` where T is foldable and so on.)
25 //!
26 //! In this ideal setup, the only function that actually *does*
27 //! anything is `super_fold_T`, which traverses the type `T`. Moreover,
28 //! `super_fold_T` should only ever call `T.fold_with()`.
29 //!
30 //! In some cases, we follow a degenerate pattern where we do not have
31 //! a `fold_T` nor `super_fold_T` method. Instead, `T.fold_with`
32 //! traverses the structure directly. This is suboptimal because the
33 //! behavior cannot be overriden, but it's much less work to implement.
34 //! If you ever *do* need an override that doesn't exist, it's not hard
35 //! to convert the degenerate pattern into the proper thing.
36
37 use middle::subst;
38 use middle::subst::VecPerParamSpace;
39 use middle::ty::{mod, Ty};
40 use middle::traits;
41 use std::rc::Rc;
42 use syntax::owned_slice::OwnedSlice;
43 use util::ppaux::Repr;
44
45 ///////////////////////////////////////////////////////////////////////////
46 // Two generic traits
47
48 /// The TypeFoldable trait is implemented for every type that can be folded.
49 /// Basically, every type that has a corresponding method in TypeFolder.
50 pub trait TypeFoldable<'tcx> {
51     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self;
52 }
53
54 /// The TypeFolder trait defines the actual *folding*. There is a
55 /// method defined for every foldable type. Each of these has a
56 /// default implementation that does an "identity" fold. Within each
57 /// identity fold, it should invoke `foo.fold_with(self)` to fold each
58 /// sub-item.
59 pub trait TypeFolder<'tcx> : Sized {
60     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
61
62     /// Invoked by the `super_*` routines when we enter a region
63     /// binding level (for example, when entering a function
64     /// signature). This is used by clients that want to track the
65     /// Debruijn index nesting level.
66     fn enter_region_binder(&mut self) { }
67
68     /// Invoked by the `super_*` routines when we exit a region
69     /// binding level. This is used by clients that want to
70     /// track the Debruijn index nesting level.
71     fn exit_region_binder(&mut self) { }
72
73     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
74         super_fold_ty(self, t)
75     }
76
77     fn fold_mt(&mut self, t: &ty::mt<'tcx>) -> ty::mt<'tcx> {
78         super_fold_mt(self, t)
79     }
80
81     fn fold_trait_ref(&mut self, t: &ty::TraitRef<'tcx>) -> ty::TraitRef<'tcx> {
82         super_fold_trait_ref(self, t)
83     }
84
85     fn fold_substs(&mut self,
86                    substs: &subst::Substs<'tcx>)
87                    -> subst::Substs<'tcx> {
88         super_fold_substs(self, substs)
89     }
90
91     fn fold_fn_sig(&mut self,
92                    sig: &ty::FnSig<'tcx>)
93                    -> ty::FnSig<'tcx> {
94         super_fold_fn_sig(self, sig)
95     }
96
97     fn fold_output(&mut self,
98                       output: &ty::FnOutput<'tcx>)
99                       -> ty::FnOutput<'tcx> {
100         super_fold_output(self, output)
101     }
102
103     fn fold_bare_fn_ty(&mut self,
104                        fty: &ty::BareFnTy<'tcx>)
105                        -> ty::BareFnTy<'tcx>
106     {
107         super_fold_bare_fn_ty(self, fty)
108     }
109
110     fn fold_closure_ty(&mut self,
111                        fty: &ty::ClosureTy<'tcx>)
112                        -> ty::ClosureTy<'tcx> {
113         super_fold_closure_ty(self, fty)
114     }
115
116     fn fold_region(&mut self, r: ty::Region) -> ty::Region {
117         r
118     }
119
120     fn fold_trait_store(&mut self, s: ty::TraitStore) -> ty::TraitStore {
121         super_fold_trait_store(self, s)
122     }
123
124     fn fold_existential_bounds(&mut self, s: &ty::ExistentialBounds<'tcx>)
125                                -> ty::ExistentialBounds<'tcx> {
126         super_fold_existential_bounds(self, s)
127     }
128
129     fn fold_autoref(&mut self, ar: &ty::AutoRef<'tcx>) -> ty::AutoRef<'tcx> {
130         super_fold_autoref(self, ar)
131     }
132
133     fn fold_item_substs(&mut self, i: ty::ItemSubsts<'tcx>) -> ty::ItemSubsts<'tcx> {
134         super_fold_item_substs(self, i)
135     }
136 }
137
138 ///////////////////////////////////////////////////////////////////////////
139 // TypeFoldable implementations.
140 //
141 // Ideally, each type should invoke `folder.fold_foo(self)` and
142 // nothing else. In some cases, though, we haven't gotten around to
143 // adding methods on the `folder` yet, and thus the folding is
144 // hard-coded here. This is less-flexible, because folders cannot
145 // override the behavior, but there are a lot of random types and one
146 // can easily refactor the folding into the TypeFolder trait as
147 // needed.
148
149 impl<'tcx> TypeFoldable<'tcx> for () {
150     fn fold_with<F:TypeFolder<'tcx>>(&self, _: &mut F) -> () {
151         ()
152     }
153 }
154
155 impl<'tcx, T:TypeFoldable<'tcx>, U:TypeFoldable<'tcx>> TypeFoldable<'tcx> for (T, U) {
156     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> (T, U) {
157         (self.0.fold_with(folder), self.1.fold_with(folder))
158     }
159 }
160
161 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Option<T> {
162     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Option<T> {
163         self.as_ref().map(|t| t.fold_with(folder))
164     }
165 }
166
167 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Rc<T> {
168     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Rc<T> {
169         Rc::new((**self).fold_with(folder))
170     }
171 }
172
173 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Box<T> {
174     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Box<T> {
175         let content: T = (**self).fold_with(folder);
176         box content
177     }
178 }
179
180 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for Vec<T> {
181     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Vec<T> {
182         self.iter().map(|t| t.fold_with(folder)).collect()
183     }
184 }
185
186 impl<'tcx, T:TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::Binder<T> {
187     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Binder<T> {
188         folder.enter_region_binder();
189         let result = ty::Binder(self.0.fold_with(folder));
190         folder.exit_region_binder();
191         result
192     }
193 }
194
195 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for OwnedSlice<T> {
196     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> OwnedSlice<T> {
197         self.iter().map(|t| t.fold_with(folder)).collect()
198     }
199 }
200
201 impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for VecPerParamSpace<T> {
202     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> VecPerParamSpace<T> {
203
204         // Things in the Fn space take place under an additional level
205         // of region binding relative to the other spaces. This is
206         // because those entries are attached to a method, and methods
207         // always introduce a level of region binding.
208
209         let result = self.map_enumerated(|(space, index, elem)| {
210             if space == subst::FnSpace && index == 0 {
211                 // enter new level when/if we reach the first thing in fn space
212                 folder.enter_region_binder();
213             }
214             elem.fold_with(folder)
215         });
216         if result.len(subst::FnSpace) > 0 {
217             // if there was anything in fn space, exit the region binding level
218             folder.exit_region_binder();
219         }
220         result
221     }
222 }
223
224 impl<'tcx> TypeFoldable<'tcx> for ty::TraitStore {
225     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TraitStore {
226         folder.fold_trait_store(*self)
227     }
228 }
229
230 impl<'tcx> TypeFoldable<'tcx> for Ty<'tcx> {
231     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Ty<'tcx> {
232         folder.fold_ty(*self)
233     }
234 }
235
236 impl<'tcx> TypeFoldable<'tcx> for ty::BareFnTy<'tcx> {
237     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::BareFnTy<'tcx> {
238         folder.fold_bare_fn_ty(self)
239     }
240 }
241
242 impl<'tcx> TypeFoldable<'tcx> for ty::ClosureTy<'tcx> {
243     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ClosureTy<'tcx> {
244         folder.fold_closure_ty(self)
245     }
246 }
247
248 impl<'tcx> TypeFoldable<'tcx> for ty::mt<'tcx> {
249     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::mt<'tcx> {
250         folder.fold_mt(self)
251     }
252 }
253
254 impl<'tcx> TypeFoldable<'tcx> for ty::FnOutput<'tcx> {
255     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnOutput<'tcx> {
256         folder.fold_output(self)
257     }
258 }
259
260 impl<'tcx> TypeFoldable<'tcx> for ty::FnSig<'tcx> {
261     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnSig<'tcx> {
262         folder.fold_fn_sig(self)
263     }
264 }
265
266 impl<'tcx> TypeFoldable<'tcx> for ty::TraitRef<'tcx> {
267     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TraitRef<'tcx> {
268         folder.fold_trait_ref(self)
269     }
270 }
271
272 impl<'tcx> TypeFoldable<'tcx> for ty::Region {
273     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Region {
274         folder.fold_region(*self)
275     }
276 }
277
278 impl<'tcx> TypeFoldable<'tcx> for subst::Substs<'tcx> {
279     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> subst::Substs<'tcx> {
280         folder.fold_substs(self)
281     }
282 }
283
284 impl<'tcx> TypeFoldable<'tcx> for ty::ItemSubsts<'tcx> {
285     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ItemSubsts<'tcx> {
286         ty::ItemSubsts {
287             substs: self.substs.fold_with(folder),
288         }
289     }
290 }
291
292 impl<'tcx> TypeFoldable<'tcx> for ty::AutoRef<'tcx> {
293     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::AutoRef<'tcx> {
294         folder.fold_autoref(self)
295     }
296 }
297
298 impl<'tcx> TypeFoldable<'tcx> for ty::MethodOrigin<'tcx> {
299     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::MethodOrigin<'tcx> {
300         match *self {
301             ty::MethodStatic(def_id) => {
302                 ty::MethodStatic(def_id)
303             }
304             ty::MethodStaticUnboxedClosure(def_id) => {
305                 ty::MethodStaticUnboxedClosure(def_id)
306             }
307             ty::MethodTypeParam(ref param) => {
308                 ty::MethodTypeParam(ty::MethodParam {
309                     trait_ref: param.trait_ref.fold_with(folder),
310                     method_num: param.method_num
311                 })
312             }
313             ty::MethodTraitObject(ref object) => {
314                 ty::MethodTraitObject(ty::MethodObject {
315                     trait_ref: object.trait_ref.fold_with(folder),
316                     object_trait_id: object.object_trait_id,
317                     method_num: object.method_num,
318                     real_index: object.real_index
319                 })
320             }
321         }
322     }
323 }
324
325 impl<'tcx> TypeFoldable<'tcx> for ty::vtable_origin<'tcx> {
326     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::vtable_origin<'tcx> {
327         match *self {
328             ty::vtable_static(def_id, ref substs, ref origins) => {
329                 let r_substs = substs.fold_with(folder);
330                 let r_origins = origins.fold_with(folder);
331                 ty::vtable_static(def_id, r_substs, r_origins)
332             }
333             ty::vtable_param(n, b) => {
334                 ty::vtable_param(n, b)
335             }
336             ty::vtable_unboxed_closure(def_id) => {
337                 ty::vtable_unboxed_closure(def_id)
338             }
339             ty::vtable_error => {
340                 ty::vtable_error
341             }
342         }
343     }
344 }
345
346 impl<'tcx> TypeFoldable<'tcx> for ty::BuiltinBounds {
347     fn fold_with<F: TypeFolder<'tcx>>(&self, _folder: &mut F) -> ty::BuiltinBounds {
348         *self
349     }
350 }
351
352 impl<'tcx> TypeFoldable<'tcx> for ty::ExistentialBounds<'tcx> {
353     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ExistentialBounds<'tcx> {
354         folder.fold_existential_bounds(self)
355     }
356 }
357
358 impl<'tcx> TypeFoldable<'tcx> for ty::ParamBounds<'tcx> {
359     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ParamBounds<'tcx> {
360         ty::ParamBounds {
361             region_bounds: self.region_bounds.fold_with(folder),
362             builtin_bounds: self.builtin_bounds.fold_with(folder),
363             trait_bounds: self.trait_bounds.fold_with(folder),
364             projection_bounds: self.projection_bounds.fold_with(folder),
365         }
366     }
367 }
368
369 impl<'tcx> TypeFoldable<'tcx> for ty::TypeParameterDef<'tcx> {
370     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TypeParameterDef<'tcx> {
371         ty::TypeParameterDef {
372             name: self.name,
373             def_id: self.def_id,
374             space: self.space,
375             index: self.index,
376             bounds: self.bounds.fold_with(folder),
377             default: self.default.fold_with(folder),
378         }
379     }
380 }
381
382 impl<'tcx> TypeFoldable<'tcx> for ty::RegionParameterDef {
383     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::RegionParameterDef {
384         ty::RegionParameterDef {
385             name: self.name,
386             def_id: self.def_id,
387             space: self.space,
388             index: self.index,
389             bounds: self.bounds.fold_with(folder)
390         }
391     }
392 }
393
394 impl<'tcx> TypeFoldable<'tcx> for ty::Generics<'tcx> {
395     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Generics<'tcx> {
396         ty::Generics {
397             types: self.types.fold_with(folder),
398             regions: self.regions.fold_with(folder),
399             predicates: self.predicates.fold_with(folder),
400         }
401     }
402 }
403
404 impl<'tcx> TypeFoldable<'tcx> for ty::Predicate<'tcx> {
405     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::Predicate<'tcx> {
406         match *self {
407             ty::Predicate::Trait(ref a) =>
408                 ty::Predicate::Trait(a.fold_with(folder)),
409             ty::Predicate::Equate(ref binder) =>
410                 ty::Predicate::Equate(binder.fold_with(folder)),
411             ty::Predicate::RegionOutlives(ref binder) =>
412                 ty::Predicate::RegionOutlives(binder.fold_with(folder)),
413             ty::Predicate::TypeOutlives(ref binder) =>
414                 ty::Predicate::TypeOutlives(binder.fold_with(folder)),
415             ty::Predicate::Projection(ref binder) =>
416                 ty::Predicate::Projection(binder.fold_with(folder)),
417         }
418     }
419 }
420
421 impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionPredicate<'tcx> {
422     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ProjectionPredicate<'tcx> {
423         ty::ProjectionPredicate {
424             projection_ty: self.projection_ty.fold_with(folder),
425             ty: self.ty.fold_with(folder),
426         }
427     }
428 }
429
430 impl<'tcx> TypeFoldable<'tcx> for ty::ProjectionTy<'tcx> {
431     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ProjectionTy<'tcx> {
432         ty::ProjectionTy {
433             trait_ref: self.trait_ref.fold_with(folder),
434             item_name: self.item_name,
435         }
436     }
437 }
438
439 impl<'tcx> TypeFoldable<'tcx> for ty::GenericBounds<'tcx> {
440     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::GenericBounds<'tcx> {
441         ty::GenericBounds {
442             predicates: self.predicates.fold_with(folder),
443         }
444     }
445 }
446
447 impl<'tcx> TypeFoldable<'tcx> for ty::UnsizeKind<'tcx> {
448     fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::UnsizeKind<'tcx> {
449         match *self {
450             ty::UnsizeLength(len) => ty::UnsizeLength(len),
451             ty::UnsizeStruct(box ref k, n) => ty::UnsizeStruct(box k.fold_with(folder), n),
452             ty::UnsizeVtable(ty::TyTrait{ref principal, ref bounds}, self_ty) => {
453                 ty::UnsizeVtable(
454                     ty::TyTrait {
455                         principal: principal.fold_with(folder),
456                         bounds: bounds.fold_with(folder),
457                     },
458                     self_ty.fold_with(folder))
459             }
460         }
461     }
462 }
463
464 impl<'tcx,O> TypeFoldable<'tcx> for traits::Obligation<'tcx,O>
465     where O : TypeFoldable<'tcx>
466 {
467     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Obligation<'tcx, O> {
468         traits::Obligation {
469             cause: self.cause.clone(),
470             recursion_depth: self.recursion_depth,
471             predicate: self.predicate.fold_with(folder),
472         }
473     }
474 }
475
476 impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableImplData<'tcx, N> {
477     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableImplData<'tcx, N> {
478         traits::VtableImplData {
479             impl_def_id: self.impl_def_id,
480             substs: self.substs.fold_with(folder),
481             nested: self.nested.fold_with(folder),
482         }
483     }
484 }
485
486 impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::VtableBuiltinData<N> {
487     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableBuiltinData<N> {
488         traits::VtableBuiltinData {
489             nested: self.nested.fold_with(folder),
490         }
491     }
492 }
493
494 impl<'tcx, N: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Vtable<'tcx, N> {
495     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Vtable<'tcx, N> {
496         match *self {
497             traits::VtableImpl(ref v) => traits::VtableImpl(v.fold_with(folder)),
498             traits::VtableUnboxedClosure(d, ref s) => {
499                 traits::VtableUnboxedClosure(d, s.fold_with(folder))
500             }
501             traits::VtableFnPointer(ref d) => {
502                 traits::VtableFnPointer(d.fold_with(folder))
503             }
504             traits::VtableParam => traits::VtableParam,
505             traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)),
506             traits::VtableObject(ref d) => traits::VtableObject(d.fold_with(folder)),
507         }
508     }
509 }
510
511 impl<'tcx> TypeFoldable<'tcx> for traits::VtableObjectData<'tcx> {
512     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::VtableObjectData<'tcx> {
513         traits::VtableObjectData {
514             object_ty: self.object_ty.fold_with(folder)
515         }
516     }
517 }
518
519 impl<'tcx> TypeFoldable<'tcx> for ty::EquatePredicate<'tcx> {
520     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::EquatePredicate<'tcx> {
521         ty::EquatePredicate(self.0.fold_with(folder),
522                             self.1.fold_with(folder))
523     }
524 }
525
526 impl<'tcx> TypeFoldable<'tcx> for ty::TraitPredicate<'tcx> {
527     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TraitPredicate<'tcx> {
528         ty::TraitPredicate {
529             trait_ref: self.trait_ref.fold_with(folder)
530         }
531     }
532 }
533
534 impl<'tcx,T,U> TypeFoldable<'tcx> for ty::OutlivesPredicate<T,U>
535     where T : TypeFoldable<'tcx>,
536           U : TypeFoldable<'tcx>,
537 {
538     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::OutlivesPredicate<T,U> {
539         ty::OutlivesPredicate(self.0.fold_with(folder),
540                               self.1.fold_with(folder))
541     }
542 }
543
544 impl<'tcx> TypeFoldable<'tcx> for ty::UnboxedClosureUpvar<'tcx> {
545     fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::UnboxedClosureUpvar<'tcx> {
546         ty::UnboxedClosureUpvar {
547             def: self.def,
548             span: self.span,
549             ty: self.ty.fold_with(folder),
550         }
551     }
552 }
553
554 ///////////////////////////////////////////////////////////////////////////
555 // "super" routines: these are the default implementations for TypeFolder.
556 //
557 // They should invoke `foo.fold_with()` to do recursive folding.
558
559 pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
560                                                 ty: Ty<'tcx>)
561                                                 -> Ty<'tcx> {
562     let sty = match ty.sty {
563         ty::ty_uniq(typ) => {
564             ty::ty_uniq(typ.fold_with(this))
565         }
566         ty::ty_ptr(ref tm) => {
567             ty::ty_ptr(tm.fold_with(this))
568         }
569         ty::ty_vec(typ, sz) => {
570             ty::ty_vec(typ.fold_with(this), sz)
571         }
572         ty::ty_open(typ) => {
573             ty::ty_open(typ.fold_with(this))
574         }
575         ty::ty_enum(tid, ref substs) => {
576             let substs = substs.fold_with(this);
577             ty::ty_enum(tid, this.tcx().mk_substs(substs))
578         }
579         ty::ty_trait(box ty::TyTrait { ref principal, ref bounds }) => {
580             ty::ty_trait(box ty::TyTrait {
581                 principal: principal.fold_with(this),
582                 bounds: bounds.fold_with(this),
583             })
584         }
585         ty::ty_tup(ref ts) => {
586             ty::ty_tup(ts.fold_with(this))
587         }
588         ty::ty_bare_fn(opt_def_id, ref f) => {
589             let bfn = f.fold_with(this);
590             ty::ty_bare_fn(opt_def_id, this.tcx().mk_bare_fn(bfn))
591         }
592         ty::ty_closure(ref f) => {
593             ty::ty_closure(f.fold_with(this))
594         }
595         ty::ty_rptr(r, ref tm) => {
596             let r = r.fold_with(this);
597             ty::ty_rptr(this.tcx().mk_region(r), tm.fold_with(this))
598         }
599         ty::ty_struct(did, ref substs) => {
600             let substs = substs.fold_with(this);
601             ty::ty_struct(did, this.tcx().mk_substs(substs))
602         }
603         ty::ty_unboxed_closure(did, ref region, ref substs) => {
604             let r = region.fold_with(this);
605             let s = substs.fold_with(this);
606             ty::ty_unboxed_closure(did, this.tcx().mk_region(r), this.tcx().mk_substs(s))
607         }
608         ty::ty_projection(ref data) => {
609             ty::ty_projection(data.fold_with(this))
610         }
611         ty::ty_bool | ty::ty_char | ty::ty_str |
612         ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
613         ty::ty_err | ty::ty_infer(_) |
614         ty::ty_param(..) => {
615             ty.sty.clone()
616         }
617     };
618     ty::mk_t(this.tcx(), sty)
619 }
620
621 pub fn super_fold_substs<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
622                                                     substs: &subst::Substs<'tcx>)
623                                                     -> subst::Substs<'tcx> {
624     let regions = match substs.regions {
625         subst::ErasedRegions => {
626             subst::ErasedRegions
627         }
628         subst::NonerasedRegions(ref regions) => {
629             subst::NonerasedRegions(regions.fold_with(this))
630         }
631     };
632
633     subst::Substs { regions: regions,
634                     types: substs.types.fold_with(this) }
635 }
636
637 pub fn super_fold_fn_sig<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
638                                                     sig: &ty::FnSig<'tcx>)
639                                                     -> ty::FnSig<'tcx>
640 {
641     ty::FnSig { inputs: sig.inputs.fold_with(this),
642                 output: sig.output.fold_with(this),
643                 variadic: sig.variadic }
644 }
645
646 pub fn super_fold_output<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
647                                                     output: &ty::FnOutput<'tcx>)
648                                                     -> ty::FnOutput<'tcx> {
649     match *output {
650         ty::FnConverging(ref ty) => ty::FnConverging(ty.fold_with(this)),
651         ty::FnDiverging => ty::FnDiverging
652     }
653 }
654
655 pub fn super_fold_bare_fn_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
656                                                         fty: &ty::BareFnTy<'tcx>)
657                                                         -> ty::BareFnTy<'tcx>
658 {
659     ty::BareFnTy { sig: fty.sig.fold_with(this),
660                    abi: fty.abi,
661                    unsafety: fty.unsafety }
662 }
663
664 pub fn super_fold_closure_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
665                                                         fty: &ty::ClosureTy<'tcx>)
666                                                         -> ty::ClosureTy<'tcx>
667 {
668     ty::ClosureTy {
669         store: fty.store.fold_with(this),
670         sig: fty.sig.fold_with(this),
671         unsafety: fty.unsafety,
672         onceness: fty.onceness,
673         bounds: fty.bounds.fold_with(this),
674         abi: fty.abi,
675     }
676 }
677
678 pub fn super_fold_trait_ref<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
679                                                        t: &ty::TraitRef<'tcx>)
680                                                        -> ty::TraitRef<'tcx>
681 {
682     let substs = t.substs.fold_with(this);
683     ty::TraitRef {
684         def_id: t.def_id,
685         substs: this.tcx().mk_substs(substs),
686     }
687 }
688
689 pub fn super_fold_mt<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
690                                                 mt: &ty::mt<'tcx>)
691                                                 -> ty::mt<'tcx> {
692     ty::mt {ty: mt.ty.fold_with(this),
693             mutbl: mt.mutbl}
694 }
695
696 pub fn super_fold_trait_store<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
697                                                          trait_store: ty::TraitStore)
698                                                          -> ty::TraitStore {
699     match trait_store {
700         ty::UniqTraitStore => ty::UniqTraitStore,
701         ty::RegionTraitStore(r, m) => {
702             ty::RegionTraitStore(r.fold_with(this), m)
703         }
704     }
705 }
706
707 pub fn super_fold_existential_bounds<'tcx, T: TypeFolder<'tcx>>(
708     this: &mut T,
709     bounds: &ty::ExistentialBounds<'tcx>)
710     -> ty::ExistentialBounds<'tcx>
711 {
712     ty::ExistentialBounds {
713         region_bound: bounds.region_bound.fold_with(this),
714         builtin_bounds: bounds.builtin_bounds,
715         projection_bounds: bounds.projection_bounds.fold_with(this),
716     }
717 }
718
719 pub fn super_fold_autoref<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
720                                                      autoref: &ty::AutoRef<'tcx>)
721                                                      -> ty::AutoRef<'tcx>
722 {
723     match *autoref {
724         ty::AutoPtr(r, m, None) => ty::AutoPtr(this.fold_region(r), m, None),
725         ty::AutoPtr(r, m, Some(ref a)) => {
726             ty::AutoPtr(this.fold_region(r), m, Some(box super_fold_autoref(this, &**a)))
727         }
728         ty::AutoUnsafe(m, None) => ty::AutoUnsafe(m, None),
729         ty::AutoUnsafe(m, Some(ref a)) => {
730             ty::AutoUnsafe(m, Some(box super_fold_autoref(this, &**a)))
731         }
732         ty::AutoUnsize(ref k) => ty::AutoUnsize(k.fold_with(this)),
733         ty::AutoUnsizeUniq(ref k) => ty::AutoUnsizeUniq(k.fold_with(this)),
734     }
735 }
736
737 pub fn super_fold_item_substs<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
738                                                          substs: ty::ItemSubsts<'tcx>)
739                                                          -> ty::ItemSubsts<'tcx>
740 {
741     ty::ItemSubsts {
742         substs: substs.substs.fold_with(this),
743     }
744 }
745
746 ///////////////////////////////////////////////////////////////////////////
747 // Some sample folders
748
749 pub struct BottomUpFolder<'a, 'tcx: 'a, F> where F: FnMut(Ty<'tcx>) -> Ty<'tcx> {
750     pub tcx: &'a ty::ctxt<'tcx>,
751     pub fldop: F,
752 }
753
754 impl<'a, 'tcx, F> TypeFolder<'tcx> for BottomUpFolder<'a, 'tcx, F> where
755     F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
756 {
757     fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
758
759     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
760         let t1 = super_fold_ty(self, ty);
761         (self.fldop)(t1)
762     }
763 }
764
765 ///////////////////////////////////////////////////////////////////////////
766 // Region folder
767
768 /// Folds over the substructure of a type, visiting its component
769 /// types and all regions that occur *free* within it.
770 ///
771 /// That is, `Ty` can contain function or method types that bind
772 /// regions at the call site (`ReLateBound`), and occurrences of
773 /// regions (aka "lifetimes") that are bound within a type are not
774 /// visited by this folder; only regions that occur free will be
775 /// visited by `fld_r`.
776
777 pub struct RegionFolder<'a, 'tcx: 'a> {
778     tcx: &'a ty::ctxt<'tcx>,
779     current_depth: u32,
780     fld_r: &'a mut (FnMut(ty::Region, u32) -> ty::Region + 'a),
781 }
782
783 impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
784     pub fn new<F>(tcx: &'a ty::ctxt<'tcx>, fld_r: &'a mut F) -> RegionFolder<'a, 'tcx>
785         where F : FnMut(ty::Region, u32) -> ty::Region
786     {
787         RegionFolder {
788             tcx: tcx,
789             current_depth: 1,
790             fld_r: fld_r,
791         }
792     }
793 }
794
795 pub fn collect_regions<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> Vec<ty::Region>
796     where T : TypeFoldable<'tcx>
797 {
798     let mut vec = Vec::new();
799     fold_regions(tcx, value, |r, _| { vec.push(r); r });
800     vec
801 }
802
803 pub fn fold_regions<'tcx,T,F>(tcx: &ty::ctxt<'tcx>,
804                               value: &T,
805                               mut f: F)
806                               -> T
807     where F : FnMut(ty::Region, u32) -> ty::Region,
808           T : TypeFoldable<'tcx>,
809 {
810     value.fold_with(&mut RegionFolder::new(tcx, &mut f))
811 }
812
813 impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx>
814 {
815     fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
816
817     fn enter_region_binder(&mut self) {
818         self.current_depth += 1;
819     }
820
821     fn exit_region_binder(&mut self) {
822         self.current_depth -= 1;
823     }
824
825     fn fold_region(&mut self, r: ty::Region) -> ty::Region {
826         match r {
827             ty::ReLateBound(debruijn, _) if debruijn.depth < self.current_depth => {
828                 debug!("RegionFolder.fold_region({}) skipped bound region (current depth={})",
829                        r.repr(self.tcx()), self.current_depth);
830                 r
831             }
832             _ => {
833                 debug!("RegionFolder.fold_region({}) folding free region (current_depth={})",
834                        r.repr(self.tcx()), self.current_depth);
835                 self.fld_r.call_mut((r, self.current_depth))
836             }
837         }
838     }
839 }
840
841 ///////////////////////////////////////////////////////////////////////////
842 // Region eraser
843 //
844 // Replaces all free regions with 'static. Useful in trans.
845
846 pub struct RegionEraser<'a, 'tcx: 'a> {
847     tcx: &'a ty::ctxt<'tcx>,
848 }
849
850 pub fn erase_regions<'tcx, T: TypeFoldable<'tcx>>(tcx: &ty::ctxt<'tcx>, t: T) -> T {
851     let mut eraser = RegionEraser { tcx: tcx };
852     t.fold_with(&mut eraser)
853 }
854
855 impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
856     fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
857
858     fn fold_region(&mut self, r: ty::Region) -> ty::Region {
859         match r {
860             ty::ReLateBound(..) | ty::ReEarlyBound(..) => r,
861             _ => ty::ReStatic
862         }
863     }
864 }
865
866 ///////////////////////////////////////////////////////////////////////////
867 // Region shifter
868 //
869 // Shifts the De Bruijn indices on all escaping bound regions by a
870 // fixed amount. Useful in substitution or when otherwise introducing
871 // a binding level that is not intended to capture the existing bound
872 // regions. See comment on `shift_regions_through_binders` method in
873 // `subst.rs` for more details.
874
875 pub fn shift_region(region: ty::Region, amount: u32) -> ty::Region {
876     match region {
877         ty::ReLateBound(debruijn, br) => {
878             ty::ReLateBound(debruijn.shifted(amount), br)
879         }
880         _ => {
881             region
882         }
883     }
884 }
885
886 pub fn shift_regions<'tcx, T:TypeFoldable<'tcx>+Repr<'tcx>>(tcx: &ty::ctxt<'tcx>,
887                                                             amount: u32, value: &T) -> T {
888     debug!("shift_regions(value={}, amount={})",
889            value.repr(tcx), amount);
890
891     value.fold_with(&mut RegionFolder::new(tcx, &mut |region, _current_depth| {
892         shift_region(region, amount)
893     }))
894 }