]> git.lizzy.rs Git - rust.git/blob - src/librustc/middle/subst.rs
5e7284dbfd1def1a5545c8ac173506d2e153c93c
[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 use middle::ty;
14 use middle::ty_fold;
15 use middle::ty_fold::{TypeFoldable, TypeFolder};
16 use util::ppaux::Repr;
17
18 use std::iter::Chain;
19 use std::mem;
20 use std::raw;
21 use std::slice::{Items, MutItems};
22 use std::vec::Vec;
23 use syntax::codemap::{Span, DUMMY_SP};
24
25 ///////////////////////////////////////////////////////////////////////////
26 // HomogeneousTuple3 trait
27 //
28 // This could be moved into standard library at some point.
29
30 trait HomogeneousTuple3<T> {
31     fn len(&self) -> uint;
32     fn as_slice<'a>(&'a self) -> &'a [T];
33     fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T];
34     fn iter<'a>(&'a self) -> Items<'a, T>;
35     fn mut_iter<'a>(&'a mut self) -> MutItems<'a, T>;
36     fn get<'a>(&'a self, index: uint) -> Option<&'a T>;
37     fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T>;
38 }
39
40 impl<T> HomogeneousTuple3<T> for (T, T, T) {
41     fn len(&self) -> uint {
42         3
43     }
44
45     fn as_slice<'a>(&'a self) -> &'a [T] {
46         unsafe {
47             let ptr: *T = mem::transmute(self);
48             let slice = raw::Slice { data: ptr, len: 3 };
49             mem::transmute(slice)
50         }
51     }
52
53     fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
54         unsafe {
55             let ptr: *T = mem::transmute(self);
56             let slice = raw::Slice { data: ptr, len: 3 };
57             mem::transmute(slice)
58         }
59     }
60
61     fn iter<'a>(&'a self) -> Items<'a, T> {
62         let slice: &'a [T] = self.as_slice();
63         slice.iter()
64     }
65
66     fn mut_iter<'a>(&'a mut self) -> MutItems<'a, T> {
67         self.as_mut_slice().mut_iter()
68     }
69
70     fn get<'a>(&'a self, index: uint) -> Option<&'a T> {
71         self.as_slice().get(index)
72     }
73
74     fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T> {
75         Some(&mut self.as_mut_slice()[index]) // wrong: fallible
76     }
77 }
78
79 ///////////////////////////////////////////////////////////////////////////
80
81 /**
82  * A substitution mapping type/region parameters to new values. We
83  * identify each in-scope parameter by an *index* and a *parameter
84  * space* (which indices where the parameter is defined; see
85  * `ParamSpace`).
86  */
87 #[deriving(Clone, PartialEq, Eq, Hash)]
88 pub struct Substs {
89     pub types: VecPerParamSpace<ty::t>,
90     pub regions: RegionSubsts,
91 }
92
93 /**
94  * Represents the values to use when substituting lifetime parameters.
95  * If the value is `ErasedRegions`, then this subst is occurring during
96  * trans, and all region parameters will be replaced with `ty::ReStatic`. */
97 #[deriving(Clone, PartialEq, Eq, Hash)]
98 pub enum RegionSubsts {
99     ErasedRegions,
100     NonerasedRegions(VecPerParamSpace<ty::Region>)
101 }
102
103 impl Substs {
104     pub fn new(t: VecPerParamSpace<ty::t>,
105                r: VecPerParamSpace<ty::Region>)
106                -> Substs
107     {
108         Substs { types: t, regions: NonerasedRegions(r) }
109     }
110
111     pub fn new_type(t: Vec<ty::t>,
112                     r: Vec<ty::Region>)
113                     -> Substs
114     {
115         Substs::new(VecPerParamSpace::new(t, Vec::new(), Vec::new()),
116                     VecPerParamSpace::new(r, Vec::new(), Vec::new()))
117     }
118
119     pub fn new_trait(t: Vec<ty::t>,
120                      r: Vec<ty::Region>,
121                      s: ty::t)
122                     -> Substs
123     {
124         Substs::new(VecPerParamSpace::new(t, vec!(s), Vec::new()),
125                     VecPerParamSpace::new(r, Vec::new(), Vec::new()))
126     }
127
128     pub fn erased(t: VecPerParamSpace<ty::t>) -> Substs
129     {
130         Substs { types: t, regions: ErasedRegions }
131     }
132
133     pub fn empty() -> Substs {
134         Substs {
135             types: VecPerParamSpace::empty(),
136             regions: NonerasedRegions(VecPerParamSpace::empty()),
137         }
138     }
139
140     pub fn trans_empty() -> Substs {
141         Substs {
142             types: VecPerParamSpace::empty(),
143             regions: ErasedRegions
144         }
145     }
146
147     pub fn is_noop(&self) -> bool {
148         let regions_is_noop = match self.regions {
149             ErasedRegions => false, // may be used to canonicalize
150             NonerasedRegions(ref regions) => regions.is_empty(),
151         };
152
153         regions_is_noop && self.types.is_empty()
154     }
155
156     pub fn self_ty(&self) -> Option<ty::t> {
157         self.types.get_self().map(|&t| t)
158     }
159
160     pub fn with_self_ty(&self, self_ty: ty::t) -> Substs {
161         assert!(self.self_ty().is_none());
162         let mut s = (*self).clone();
163         s.types.push(SelfSpace, self_ty);
164         s
165     }
166
167     pub fn regions<'a>(&'a self) -> &'a VecPerParamSpace<ty::Region> {
168         /*!
169          * Since ErasedRegions are only to be used in trans, most of
170          * the compiler can use this method to easily access the set
171          * of region substitutions.
172          */
173
174         match self.regions {
175             ErasedRegions => fail!("Erased regions only expected in trans"),
176             NonerasedRegions(ref r) => r
177         }
178     }
179
180     pub fn mut_regions<'a>(&'a mut self) -> &'a mut VecPerParamSpace<ty::Region> {
181         /*!
182          * Since ErasedRegions are only to be used in trans, most of
183          * the compiler can use this method to easily access the set
184          * of region substitutions.
185          */
186
187         match self.regions {
188             ErasedRegions => fail!("Erased regions only expected in trans"),
189             NonerasedRegions(ref mut r) => r
190         }
191     }
192
193     pub fn with_method_from(self, substs: &Substs) -> Substs {
194         self.with_method((*substs.types.get_vec(FnSpace)).clone(),
195                          (*substs.regions().get_vec(FnSpace)).clone())
196     }
197
198     pub fn with_method(self,
199                        m_types: Vec<ty::t>,
200                        m_regions: Vec<ty::Region>)
201                        -> Substs
202     {
203         let Substs { types, regions } = self;
204         let types = types.with_vec(FnSpace, m_types);
205         let regions = regions.map(m_regions,
206                                   |r, m_regions| r.with_vec(FnSpace, m_regions));
207         Substs { types: types, regions: regions }
208     }
209 }
210
211 impl RegionSubsts {
212     fn map<A>(self,
213               a: A,
214               op: |VecPerParamSpace<ty::Region>, A| -> VecPerParamSpace<ty::Region>)
215               -> RegionSubsts {
216         match self {
217             ErasedRegions => ErasedRegions,
218             NonerasedRegions(r) => NonerasedRegions(op(r, a))
219         }
220     }
221 }
222
223 ///////////////////////////////////////////////////////////////////////////
224 // ParamSpace
225
226 #[deriving(PartialOrd, Ord, PartialEq, Eq,
227            Clone, Hash, Encodable, Decodable, Show)]
228 pub enum ParamSpace {
229     TypeSpace, // Type parameters attached to a type definition, trait, or impl
230     SelfSpace, // Self parameter on a trait
231     FnSpace,   // Type parameters attached to a method or fn
232 }
233
234 impl ParamSpace {
235     pub fn all() -> [ParamSpace, ..3] {
236         [TypeSpace, SelfSpace, FnSpace]
237     }
238
239     pub fn to_uint(self) -> uint {
240         match self {
241             TypeSpace => 0,
242             SelfSpace => 1,
243             FnSpace => 2,
244         }
245     }
246
247     pub fn from_uint(u: uint) -> ParamSpace {
248         match u {
249             0 => TypeSpace,
250             1 => SelfSpace,
251             2 => FnSpace,
252             _ => fail!("Invalid ParamSpace: {}", u)
253         }
254     }
255 }
256
257 /**
258  * Vector of things sorted by param space. Used to keep
259  * the set of things declared on the type, self, or method
260  * distinct.
261  */
262 #[deriving(PartialEq, Eq, Clone, Hash, Encodable, Decodable)]
263 pub struct VecPerParamSpace<T> {
264     vecs: (Vec<T>, Vec<T>, Vec<T>)
265 }
266
267 impl<T> VecPerParamSpace<T> {
268     pub fn empty() -> VecPerParamSpace<T> {
269         VecPerParamSpace {
270             vecs: (Vec::new(), Vec::new(), Vec::new())
271         }
272     }
273
274     pub fn params_from_type(types: Vec<T>) -> VecPerParamSpace<T> {
275         VecPerParamSpace::empty().with_vec(TypeSpace, types)
276     }
277
278     pub fn new(t: Vec<T>, s: Vec<T>, f: Vec<T>) -> VecPerParamSpace<T> {
279         VecPerParamSpace {
280             vecs: (t, s, f)
281         }
282     }
283
284     pub fn sort(t: Vec<T>, space: |&T| -> ParamSpace) -> VecPerParamSpace<T> {
285         let mut result = VecPerParamSpace::empty();
286         for t in t.move_iter() {
287             result.push(space(&t), t);
288         }
289         result
290     }
291
292     pub fn push(&mut self, space: ParamSpace, value: T) {
293         self.get_mut_vec(space).push(value);
294     }
295
296     pub fn get_self<'a>(&'a self) -> Option<&'a T> {
297         let v = self.get_vec(SelfSpace);
298         assert!(v.len() <= 1);
299         if v.len() == 0 { None } else { Some(v.get(0)) }
300     }
301
302     pub fn len(&self, space: ParamSpace) -> uint {
303         self.get_vec(space).len()
304     }
305
306     pub fn get_vec<'a>(&'a self, space: ParamSpace) -> &'a Vec<T> {
307         self.vecs.get(space as uint).unwrap()
308     }
309
310     pub fn get_mut_vec<'a>(&'a mut self, space: ParamSpace) -> &'a mut Vec<T> {
311         self.vecs.get_mut(space as uint).unwrap()
312     }
313
314     pub fn opt_get<'a>(&'a self,
315                        space: ParamSpace,
316                        index: uint)
317                        -> Option<&'a T> {
318         let v = self.get_vec(space);
319         if index < v.len() { Some(v.get(index)) } else { None }
320     }
321
322     pub fn get<'a>(&'a self, space: ParamSpace, index: uint) -> &'a T {
323         self.get_vec(space).get(index)
324     }
325
326     pub fn get_mut<'a>(&'a mut self,
327                        space: ParamSpace,
328                        index: uint) -> &'a mut T {
329         self.get_mut_vec(space).get_mut(index)
330     }
331
332     pub fn iter<'a>(&'a self) -> Chain<Items<'a,T>,
333                                        Chain<Items<'a,T>,
334                                              Items<'a,T>>> {
335         let (ref r, ref s, ref f) = self.vecs;
336         r.iter().chain(s.iter().chain(f.iter()))
337     }
338
339     pub fn all_vecs(&self, pred: |&Vec<T>| -> bool) -> bool {
340         self.vecs.iter().all(pred)
341     }
342
343     pub fn all(&self, pred: |&T| -> bool) -> bool {
344         self.iter().all(pred)
345     }
346
347     pub fn any(&self, pred: |&T| -> bool) -> bool {
348         self.iter().any(pred)
349     }
350
351     pub fn is_empty(&self) -> bool {
352         self.all_vecs(|v| v.is_empty())
353     }
354
355     pub fn map<U>(&self, pred: |&T| -> U) -> VecPerParamSpace<U> {
356         VecPerParamSpace::new(self.vecs.ref0().iter().map(|p| pred(p)).collect(),
357                               self.vecs.ref1().iter().map(|p| pred(p)).collect(),
358                               self.vecs.ref2().iter().map(|p| pred(p)).collect())
359     }
360
361     pub fn map_rev<U>(&self, pred: |&T| -> U) -> VecPerParamSpace<U> {
362         /*!
363          * Executes the map but in reverse order. For hacky reasons, we rely
364          * on this in table.
365          *
366          * FIXME(#5527) -- order of eval becomes irrelevant with newer
367          * trait reform, which features an idempotent algorithm that
368          * can be run to a fixed point
369          */
370
371         let mut fns: Vec<U> = self.vecs.ref2().iter().rev().map(|p| pred(p)).collect();
372
373         // NB: Calling foo.rev().map().rev() causes the calls to map
374         // to occur in the wrong order. This was somewhat surprising
375         // to me, though it makes total sense.
376         fns.reverse();
377
378         let mut selfs: Vec<U> = self.vecs.ref1().iter().rev().map(|p| pred(p)).collect();
379         selfs.reverse();
380         let mut tys: Vec<U> = self.vecs.ref0().iter().rev().map(|p| pred(p)).collect();
381         tys.reverse();
382         VecPerParamSpace::new(tys, selfs, fns)
383     }
384
385     pub fn split(self) -> (Vec<T>, Vec<T>, Vec<T>) {
386         self.vecs
387     }
388
389     pub fn with_vec(mut self, space: ParamSpace, vec: Vec<T>)
390                     -> VecPerParamSpace<T>
391     {
392         assert!(self.get_vec(space).is_empty());
393         *self.get_mut_vec(space) = vec;
394         self
395     }
396 }
397
398 ///////////////////////////////////////////////////////////////////////////
399 // Public trait `Subst`
400 //
401 // Just call `foo.subst(tcx, substs)` to perform a substitution across
402 // `foo`. Or use `foo.subst_spanned(tcx, substs, Some(span))` when
403 // there is more information available (for better errors).
404
405 pub trait Subst {
406     fn subst(&self, tcx: &ty::ctxt, substs: &Substs) -> Self {
407         self.subst_spanned(tcx, substs, None)
408     }
409
410     fn subst_spanned(&self, tcx: &ty::ctxt,
411                      substs: &Substs,
412                      span: Option<Span>)
413                      -> Self;
414 }
415
416 impl<T:TypeFoldable> Subst for T {
417     fn subst_spanned(&self,
418                      tcx: &ty::ctxt,
419                      substs: &Substs,
420                      span: Option<Span>)
421                      -> T
422     {
423         let mut folder = SubstFolder { tcx: tcx,
424                                        substs: substs,
425                                        span: span,
426                                        root_ty: None,
427                                        ty_stack_depth: 0 };
428         (*self).fold_with(&mut folder)
429     }
430 }
431
432 ///////////////////////////////////////////////////////////////////////////
433 // The actual substitution engine itself is a type folder.
434
435 struct SubstFolder<'a> {
436     tcx: &'a ty::ctxt,
437     substs: &'a Substs,
438
439     // The location for which the substitution is performed, if available.
440     span: Option<Span>,
441
442     // The root type that is being substituted, if available.
443     root_ty: Option<ty::t>,
444
445     // Depth of type stack
446     ty_stack_depth: uint,
447 }
448
449 impl<'a> TypeFolder for SubstFolder<'a> {
450     fn tcx<'a>(&'a self) -> &'a ty::ctxt { self.tcx }
451
452     fn fold_region(&mut self, r: ty::Region) -> ty::Region {
453         // Note: This routine only handles regions that are bound on
454         // type declarations and other outer declarations, not those
455         // bound in *fn types*. Region substitution of the bound
456         // regions that appear in a function signature is done using
457         // the specialized routine
458         // `middle::typeck::check::regionmanip::replace_late_regions_in_fn_sig()`.
459         match r {
460             ty::ReEarlyBound(_, space, i, _) => {
461                 match self.substs.regions {
462                     ErasedRegions => ty::ReStatic,
463                     NonerasedRegions(ref regions) => *regions.get(space, i),
464                 }
465             }
466             _ => r
467         }
468     }
469
470     fn fold_ty(&mut self, t: ty::t) -> ty::t {
471         if !ty::type_needs_subst(t) {
472             return t;
473         }
474
475         // track the root type we were asked to substitute
476         let depth = self.ty_stack_depth;
477         if depth == 0 {
478             self.root_ty = Some(t);
479         }
480         self.ty_stack_depth += 1;
481
482         let t1 = match ty::get(t).sty {
483             ty::ty_param(p) => {
484                 check(self, t, self.substs.types.opt_get(p.space, p.idx))
485             }
486             _ => {
487                 ty_fold::super_fold_ty(self, t)
488             }
489         };
490
491         assert_eq!(depth + 1, self.ty_stack_depth);
492         self.ty_stack_depth -= 1;
493         if depth == 0 {
494             self.root_ty = None;
495         }
496
497         return t1;
498
499         fn check(this: &SubstFolder,
500                  source_ty: ty::t,
501                  opt_ty: Option<&ty::t>)
502                  -> ty::t {
503             match opt_ty {
504                 Some(t) => *t,
505                 None => {
506                     let span = this.span.unwrap_or(DUMMY_SP);
507                     this.tcx().sess.span_bug(
508                         span,
509                         format!("Type parameter {} out of range \
510                                  when substituting (root type={})",
511                                 source_ty.repr(this.tcx()),
512                                 this.root_ty.repr(this.tcx())).as_slice());
513                 }
514             }
515         }
516     }
517 }