]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/rscope.rs
Merge pull request #20510 from tshepang/patch-6
[rust.git] / src / librustc_typeck / rscope.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
12 use middle::ty;
13 use middle::ty_fold;
14
15 use std::cell::Cell;
16 use std::iter::repeat;
17 use syntax::codemap::Span;
18
19 /// Defines strategies for handling regions that are omitted.  For
20 /// example, if one writes the type `&Foo`, then the lifetime of
21 /// this reference has been omitted. When converting this
22 /// type, the generic functions in astconv will invoke `anon_regions`
23 /// on the provided region-scope to decide how to translate this
24 /// omitted region.
25 ///
26 /// It is not always legal to omit regions, therefore `anon_regions`
27 /// can return `Err(())` to indicate that this is not a scope in which
28 /// regions can legally be omitted.
29 pub trait RegionScope {
30     fn anon_regions(&self,
31                     span: Span,
32                     count: uint)
33                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>;
34
35     fn default_region_bound(&self, span: Span) -> Option<ty::Region>;
36 }
37
38 // A scope in which all regions must be explicitly named. This is used
39 // for types that appear in structs and so on.
40 #[derive(Copy)]
41 pub struct ExplicitRscope;
42
43 impl RegionScope for ExplicitRscope {
44     fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
45         None
46     }
47
48     fn anon_regions(&self,
49                     _span: Span,
50                     _count: uint)
51                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
52         Err(None)
53     }
54 }
55
56 // Same as `ExplicitRscope`, but provides some extra information for diagnostics
57 pub struct UnelidableRscope(Vec<(String, uint)>);
58
59 impl UnelidableRscope {
60     pub fn new(v: Vec<(String, uint)>) -> UnelidableRscope {
61         UnelidableRscope(v)
62     }
63 }
64
65 impl RegionScope for UnelidableRscope {
66     fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
67         None
68     }
69
70     fn anon_regions(&self,
71                     _span: Span,
72                     _count: uint)
73                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
74         let UnelidableRscope(ref v) = *self;
75         Err(Some(v.clone()))
76     }
77 }
78
79 // A scope in which any omitted region defaults to `default`. This is
80 // used after the `->` in function signatures, but also for backwards
81 // compatibility with object types. The latter use may go away.
82 #[allow(missing_copy_implementations)]
83 pub struct SpecificRscope {
84     default: ty::Region
85 }
86
87 impl SpecificRscope {
88     pub fn new(r: ty::Region) -> SpecificRscope {
89         SpecificRscope { default: r }
90     }
91 }
92
93 impl RegionScope for SpecificRscope {
94     fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
95         Some(self.default)
96     }
97
98     fn anon_regions(&self,
99                     _span: Span,
100                     count: uint)
101                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
102     {
103         Ok(repeat(self.default).take(count).collect())
104     }
105 }
106
107 /// A scope in which we generate anonymous, late-bound regions for
108 /// omitted regions. This occurs in function signatures.
109 pub struct BindingRscope {
110     anon_bindings: Cell<u32>,
111 }
112
113 impl BindingRscope {
114     pub fn new() -> BindingRscope {
115         BindingRscope {
116             anon_bindings: Cell::new(0),
117         }
118     }
119
120     fn next_region(&self) -> ty::Region {
121         let idx = self.anon_bindings.get();
122         self.anon_bindings.set(idx + 1);
123         ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(idx))
124     }
125 }
126
127 impl RegionScope for BindingRscope {
128     fn default_region_bound(&self, _span: Span) -> Option<ty::Region>
129     {
130         Some(self.next_region())
131     }
132
133     fn anon_regions(&self,
134                     _: Span,
135                     count: uint)
136                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
137     {
138         Ok(range(0, count).map(|_| self.next_region()).collect())
139     }
140 }
141
142 /// A scope which simply shifts the Debruijn index of other scopes
143 /// to account for binding levels.
144 pub struct ShiftedRscope<'r> {
145     base_scope: &'r (RegionScope+'r)
146 }
147
148 impl<'r> ShiftedRscope<'r> {
149     pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> {
150         ShiftedRscope { base_scope: base_scope }
151     }
152 }
153
154 impl<'r> RegionScope for ShiftedRscope<'r> {
155     fn default_region_bound(&self, span: Span) -> Option<ty::Region>
156     {
157         self.base_scope.default_region_bound(span)
158             .map(|r| ty_fold::shift_region(r, 1))
159     }
160
161     fn anon_regions(&self,
162                     span: Span,
163                     count: uint)
164                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
165     {
166         match self.base_scope.anon_regions(span, count) {
167             Ok(mut v) => {
168                 for r in v.iter_mut() {
169                     *r = ty_fold::shift_region(*r, 1);
170                 }
171                 Ok(v)
172             }
173             Err(errs) => {
174                 Err(errs)
175             }
176         }
177     }
178 }