]> git.proxmox.com Git - rustc.git/blame - src/librustc_typeck/rscope.rs
Imported Upstream version 1.3.0+dfsg1
[rustc.git] / src / librustc_typeck / rscope.rs
CommitLineData
1a4d82fc
JJ
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
12use middle::ty;
13use middle::ty_fold;
14
15use std::cell::Cell;
1a4d82fc
JJ
16use syntax::codemap::Span;
17
c1a9b12d
SL
18#[derive(Clone)]
19pub struct ElisionFailureInfo {
20 pub name: String,
21 pub lifetime_count: usize,
22 pub have_bound_regions: bool
23}
24
25pub type ElidedLifetime = Result<ty::Region, Option<Vec<ElisionFailureInfo>>>;
26
1a4d82fc
JJ
27/// Defines strategies for handling regions that are omitted. For
28/// example, if one writes the type `&Foo`, then the lifetime of
29/// this reference has been omitted. When converting this
30/// type, the generic functions in astconv will invoke `anon_regions`
31/// on the provided region-scope to decide how to translate this
32/// omitted region.
33///
34/// It is not always legal to omit regions, therefore `anon_regions`
35/// can return `Err(())` to indicate that this is not a scope in which
36/// regions can legally be omitted.
37pub trait RegionScope {
38 fn anon_regions(&self,
39 span: Span,
c34b1796 40 count: usize)
c1a9b12d 41 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>;
1a4d82fc 42
85aaf69f
SL
43 /// If an object omits any explicit lifetime bound, and none can
44 /// be derived from the object traits, what should we use? If
45 /// `None` is returned, an explicit annotation is required.
46 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region>;
62682a34
SL
47
48 /// The "base" default is the initial default for a scope. This is
49 /// 'static except for in fn bodies, where it is a fresh inference
50 /// variable. You shouldn't call this except for as part of
51 /// computing `object_lifetime_default` (in particular, in legacy
52 /// modes, it may not be relevant).
53 fn base_object_lifetime_default(&self, span: Span) -> ty::Region;
1a4d82fc
JJ
54}
55
56// A scope in which all regions must be explicitly named. This is used
57// for types that appear in structs and so on.
c34b1796 58#[derive(Copy, Clone)]
1a4d82fc
JJ
59pub struct ExplicitRscope;
60
61impl RegionScope for ExplicitRscope {
1a4d82fc
JJ
62 fn anon_regions(&self,
63 _span: Span,
c34b1796 64 _count: usize)
c1a9b12d 65 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
1a4d82fc
JJ
66 Err(None)
67 }
62682a34
SL
68
69 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
70 Some(self.base_object_lifetime_default(span))
71 }
72
73 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
74 ty::ReStatic
75 }
1a4d82fc
JJ
76}
77
78// Same as `ExplicitRscope`, but provides some extra information for diagnostics
c1a9b12d 79pub struct UnelidableRscope(Option<Vec<ElisionFailureInfo>>);
1a4d82fc
JJ
80
81impl UnelidableRscope {
c1a9b12d 82 pub fn new(v: Option<Vec<ElisionFailureInfo>>) -> UnelidableRscope {
1a4d82fc
JJ
83 UnelidableRscope(v)
84 }
85}
86
87impl RegionScope for UnelidableRscope {
1a4d82fc
JJ
88 fn anon_regions(&self,
89 _span: Span,
c34b1796 90 _count: usize)
c1a9b12d 91 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
1a4d82fc 92 let UnelidableRscope(ref v) = *self;
c1a9b12d 93 Err(v.clone())
1a4d82fc 94 }
62682a34
SL
95
96 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
97 Some(self.base_object_lifetime_default(span))
98 }
99
100 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
101 ty::ReStatic
102 }
1a4d82fc
JJ
103}
104
85aaf69f
SL
105// A scope in which omitted anonymous region defaults to
106// `default`. This is used after the `->` in function signatures. The
107// latter use may go away. Note that object-lifetime defaults work a
108// bit differently, as specified in RFC #599.
109pub struct ElidableRscope {
110 default: ty::Region,
1a4d82fc
JJ
111}
112
85aaf69f
SL
113impl ElidableRscope {
114 pub fn new(r: ty::Region) -> ElidableRscope {
115 ElidableRscope { default: r }
1a4d82fc
JJ
116 }
117}
118
85aaf69f 119impl RegionScope for ElidableRscope {
62682a34 120 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
85aaf69f
SL
121 // Per RFC #599, object-lifetimes default to 'static unless
122 // overridden by context, and this takes precedence over
123 // lifetime elision.
62682a34
SL
124 Some(self.base_object_lifetime_default(span))
125 }
126
127 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
128 ty::ReStatic
1a4d82fc
JJ
129 }
130
131 fn anon_regions(&self,
132 _span: Span,
c34b1796 133 count: usize)
c1a9b12d 134 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
1a4d82fc 135 {
c1a9b12d 136 Ok(vec![self.default; count])
1a4d82fc
JJ
137 }
138}
139
140/// A scope in which we generate anonymous, late-bound regions for
141/// omitted regions. This occurs in function signatures.
142pub struct BindingRscope {
143 anon_bindings: Cell<u32>,
144}
145
146impl BindingRscope {
147 pub fn new() -> BindingRscope {
148 BindingRscope {
149 anon_bindings: Cell::new(0),
150 }
151 }
152
153 fn next_region(&self) -> ty::Region {
154 let idx = self.anon_bindings.get();
155 self.anon_bindings.set(idx + 1);
156 ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(idx))
157 }
158}
159
160impl RegionScope for BindingRscope {
62682a34 161 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
85aaf69f
SL
162 // Per RFC #599, object-lifetimes default to 'static unless
163 // overridden by context, and this takes precedence over the
62682a34
SL
164 // binding defaults in a fn signature.
165 Some(self.base_object_lifetime_default(span))
166 }
167
168 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
169 ty::ReStatic
1a4d82fc
JJ
170 }
171
172 fn anon_regions(&self,
173 _: Span,
c34b1796 174 count: usize)
c1a9b12d 175 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
1a4d82fc 176 {
85aaf69f
SL
177 Ok((0..count).map(|_| self.next_region()).collect())
178 }
179}
180
181/// A scope which overrides the default object lifetime but has no other effect.
182pub struct ObjectLifetimeDefaultRscope<'r> {
183 base_scope: &'r (RegionScope+'r),
62682a34 184 default: ty::ObjectLifetimeDefault,
85aaf69f
SL
185}
186
187impl<'r> ObjectLifetimeDefaultRscope<'r> {
188 pub fn new(base_scope: &'r (RegionScope+'r),
62682a34 189 default: ty::ObjectLifetimeDefault)
85aaf69f
SL
190 -> ObjectLifetimeDefaultRscope<'r>
191 {
192 ObjectLifetimeDefaultRscope {
193 base_scope: base_scope,
194 default: default,
195 }
196 }
197}
198
199impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
200 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
201 match self.default {
62682a34
SL
202 ty::ObjectLifetimeDefault::Ambiguous =>
203 None,
204
205 ty::ObjectLifetimeDefault::BaseDefault =>
c1a9b12d
SL
206 // NB: This behavior changed in Rust 1.3.
207 Some(self.base_object_lifetime_default(span)),
62682a34
SL
208
209 ty::ObjectLifetimeDefault::Specific(r) =>
210 Some(r),
211 }
212 }
213
214 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
62682a34
SL
215 self.base_scope.base_object_lifetime_default(span)
216 }
217
85aaf69f
SL
218 fn anon_regions(&self,
219 span: Span,
c34b1796 220 count: usize)
c1a9b12d 221 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
85aaf69f
SL
222 {
223 self.base_scope.anon_regions(span, count)
1a4d82fc
JJ
224 }
225}
226
227/// A scope which simply shifts the Debruijn index of other scopes
228/// to account for binding levels.
229pub struct ShiftedRscope<'r> {
230 base_scope: &'r (RegionScope+'r)
231}
232
233impl<'r> ShiftedRscope<'r> {
234 pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> {
235 ShiftedRscope { base_scope: base_scope }
236 }
237}
238
239impl<'r> RegionScope for ShiftedRscope<'r> {
85aaf69f
SL
240 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
241 self.base_scope.object_lifetime_default(span)
1a4d82fc
JJ
242 .map(|r| ty_fold::shift_region(r, 1))
243 }
244
62682a34
SL
245 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
246 ty_fold::shift_region(self.base_scope.base_object_lifetime_default(span), 1)
247 }
248
1a4d82fc
JJ
249 fn anon_regions(&self,
250 span: Span,
c34b1796 251 count: usize)
c1a9b12d 252 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
1a4d82fc
JJ
253 {
254 match self.base_scope.anon_regions(span, count) {
255 Ok(mut v) => {
85aaf69f 256 for r in &mut v {
1a4d82fc
JJ
257 *r = ty_fold::shift_region(*r, 1);
258 }
259 Ok(v)
260 }
261 Err(errs) => {
262 Err(errs)
263 }
264 }
265 }
266}