]> git.proxmox.com Git - rustc.git/blob - src/librustc_typeck/rscope.rs
Imported Upstream version 1.2.0+dfsg1
[rustc.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: usize)
33 -> Result<Vec<ty::Region>, Option<Vec<(String, usize)>>>;
34
35 /// If an object omits any explicit lifetime bound, and none can
36 /// be derived from the object traits, what should we use? If
37 /// `None` is returned, an explicit annotation is required.
38 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region>;
39
40 /// The "base" default is the initial default for a scope. This is
41 /// 'static except for in fn bodies, where it is a fresh inference
42 /// variable. You shouldn't call this except for as part of
43 /// computing `object_lifetime_default` (in particular, in legacy
44 /// modes, it may not be relevant).
45 fn base_object_lifetime_default(&self, span: Span) -> ty::Region;
46
47 /// Used to issue warnings in Rust 1.2, not needed after that.
48 /// True if the result of `object_lifetime_default` will change in 1.3.
49 fn object_lifetime_default_will_change_in_1_3(&self) -> bool {
50 false
51 }
52
53 /// Used to issue warnings in Rust 1.2, not needed after that.
54 /// True if the result of `base_object_lifetime_default` differs
55 /// from the result of `object_lifetime_default`.
56 fn base_object_lifetime_default_differs(&self) -> bool {
57 false
58 }
59 }
60
61 // A scope in which all regions must be explicitly named. This is used
62 // for types that appear in structs and so on.
63 #[derive(Copy, Clone)]
64 pub struct ExplicitRscope;
65
66 impl RegionScope for ExplicitRscope {
67 fn anon_regions(&self,
68 _span: Span,
69 _count: usize)
70 -> Result<Vec<ty::Region>, Option<Vec<(String, usize)>>> {
71 Err(None)
72 }
73
74 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
75 Some(self.base_object_lifetime_default(span))
76 }
77
78 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
79 ty::ReStatic
80 }
81 }
82
83 // Same as `ExplicitRscope`, but provides some extra information for diagnostics
84 pub struct UnelidableRscope(Vec<(String, usize)>);
85
86 impl UnelidableRscope {
87 pub fn new(v: Vec<(String, usize)>) -> UnelidableRscope {
88 UnelidableRscope(v)
89 }
90 }
91
92 impl RegionScope for UnelidableRscope {
93 fn anon_regions(&self,
94 _span: Span,
95 _count: usize)
96 -> Result<Vec<ty::Region>, Option<Vec<(String, usize)>>> {
97 let UnelidableRscope(ref v) = *self;
98 Err(Some(v.clone()))
99 }
100
101 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
102 Some(self.base_object_lifetime_default(span))
103 }
104
105 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
106 ty::ReStatic
107 }
108 }
109
110 // A scope in which omitted anonymous region defaults to
111 // `default`. This is used after the `->` in function signatures. The
112 // latter use may go away. Note that object-lifetime defaults work a
113 // bit differently, as specified in RFC #599.
114 pub struct ElidableRscope {
115 default: ty::Region,
116 }
117
118 impl ElidableRscope {
119 pub fn new(r: ty::Region) -> ElidableRscope {
120 ElidableRscope { default: r }
121 }
122 }
123
124 impl RegionScope for ElidableRscope {
125 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
126 // Per RFC #599, object-lifetimes default to 'static unless
127 // overridden by context, and this takes precedence over
128 // lifetime elision.
129 Some(self.base_object_lifetime_default(span))
130 }
131
132 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
133 ty::ReStatic
134 }
135
136 fn anon_regions(&self,
137 _span: Span,
138 count: usize)
139 -> Result<Vec<ty::Region>, Option<Vec<(String, usize)>>>
140 {
141 Ok(repeat(self.default).take(count).collect())
142 }
143 }
144
145 /// A scope in which we generate anonymous, late-bound regions for
146 /// omitted regions. This occurs in function signatures.
147 pub struct BindingRscope {
148 anon_bindings: Cell<u32>,
149 }
150
151 impl BindingRscope {
152 pub fn new() -> BindingRscope {
153 BindingRscope {
154 anon_bindings: Cell::new(0),
155 }
156 }
157
158 fn next_region(&self) -> ty::Region {
159 let idx = self.anon_bindings.get();
160 self.anon_bindings.set(idx + 1);
161 ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(idx))
162 }
163 }
164
165 impl RegionScope for BindingRscope {
166 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
167 // Per RFC #599, object-lifetimes default to 'static unless
168 // overridden by context, and this takes precedence over the
169 // binding defaults in a fn signature.
170 Some(self.base_object_lifetime_default(span))
171 }
172
173 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
174 ty::ReStatic
175 }
176
177 fn anon_regions(&self,
178 _: Span,
179 count: usize)
180 -> Result<Vec<ty::Region>, Option<Vec<(String, usize)>>>
181 {
182 Ok((0..count).map(|_| self.next_region()).collect())
183 }
184 }
185
186 /// A scope which overrides the default object lifetime but has no other effect.
187 pub struct ObjectLifetimeDefaultRscope<'r> {
188 base_scope: &'r (RegionScope+'r),
189 default: ty::ObjectLifetimeDefault,
190 }
191
192 impl<'r> ObjectLifetimeDefaultRscope<'r> {
193 pub fn new(base_scope: &'r (RegionScope+'r),
194 default: ty::ObjectLifetimeDefault)
195 -> ObjectLifetimeDefaultRscope<'r>
196 {
197 ObjectLifetimeDefaultRscope {
198 base_scope: base_scope,
199 default: default,
200 }
201 }
202 }
203
204 impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
205 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
206 match self.default {
207 ty::ObjectLifetimeDefault::Ambiguous =>
208 None,
209
210 ty::ObjectLifetimeDefault::BaseDefault =>
211 if false { // this will become the behavior in Rust 1.3
212 Some(self.base_object_lifetime_default(span))
213 } else {
214 self.base_scope.object_lifetime_default(span)
215 },
216
217 ty::ObjectLifetimeDefault::Specific(r) =>
218 Some(r),
219 }
220 }
221
222 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
223 assert!(false, "this code should not execute until Rust 1.3");
224 self.base_scope.base_object_lifetime_default(span)
225 }
226
227 fn object_lifetime_default_will_change_in_1_3(&self) -> bool {
228 debug!("object_lifetime_default_will_change_in_1_3: {:?}", self.default);
229
230 match self.default {
231 ty::ObjectLifetimeDefault::Ambiguous |
232 ty::ObjectLifetimeDefault::Specific(_) =>
233 false,
234
235 ty::ObjectLifetimeDefault::BaseDefault =>
236 self.base_scope.base_object_lifetime_default_differs()
237 }
238 }
239
240 fn base_object_lifetime_default_differs(&self) -> bool {
241 debug!("base_object_lifetime_default_differs: {:?}", self.default);
242
243 match self.default {
244 ty::ObjectLifetimeDefault::Ambiguous |
245 ty::ObjectLifetimeDefault::Specific(_) =>
246 true,
247
248 ty::ObjectLifetimeDefault::BaseDefault =>
249 self.base_scope.base_object_lifetime_default_differs(),
250 }
251 }
252
253 fn anon_regions(&self,
254 span: Span,
255 count: usize)
256 -> Result<Vec<ty::Region>, Option<Vec<(String, usize)>>>
257 {
258 self.base_scope.anon_regions(span, count)
259 }
260 }
261
262 /// A scope which simply shifts the Debruijn index of other scopes
263 /// to account for binding levels.
264 pub struct ShiftedRscope<'r> {
265 base_scope: &'r (RegionScope+'r)
266 }
267
268 impl<'r> ShiftedRscope<'r> {
269 pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> {
270 ShiftedRscope { base_scope: base_scope }
271 }
272 }
273
274 impl<'r> RegionScope for ShiftedRscope<'r> {
275 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
276 self.base_scope.object_lifetime_default(span)
277 .map(|r| ty_fold::shift_region(r, 1))
278 }
279
280 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
281 ty_fold::shift_region(self.base_scope.base_object_lifetime_default(span), 1)
282 }
283
284 fn anon_regions(&self,
285 span: Span,
286 count: usize)
287 -> Result<Vec<ty::Region>, Option<Vec<(String, usize)>>>
288 {
289 match self.base_scope.anon_regions(span, count) {
290 Ok(mut v) => {
291 for r in &mut v {
292 *r = ty_fold::shift_region(*r, 1);
293 }
294 Ok(v)
295 }
296 Err(errs) => {
297 Err(errs)
298 }
299 }
300 }
301 }