]>
Commit | Line | Data |
---|---|---|
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 | ||
12 | use middle::ty; | |
13 | use middle::ty_fold; | |
14 | ||
15 | use std::cell::Cell; | |
1a4d82fc JJ |
16 | use syntax::codemap::Span; |
17 | ||
c1a9b12d SL |
18 | #[derive(Clone)] |
19 | pub struct ElisionFailureInfo { | |
20 | pub name: String, | |
21 | pub lifetime_count: usize, | |
22 | pub have_bound_regions: bool | |
23 | } | |
24 | ||
25 | pub 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. | |
37 | pub 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 |
59 | pub struct ExplicitRscope; |
60 | ||
61 | impl 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 | 79 | pub struct UnelidableRscope(Option<Vec<ElisionFailureInfo>>); |
1a4d82fc JJ |
80 | |
81 | impl UnelidableRscope { | |
c1a9b12d | 82 | pub fn new(v: Option<Vec<ElisionFailureInfo>>) -> UnelidableRscope { |
1a4d82fc JJ |
83 | UnelidableRscope(v) |
84 | } | |
85 | } | |
86 | ||
87 | impl 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. | |
109 | pub struct ElidableRscope { | |
110 | default: ty::Region, | |
1a4d82fc JJ |
111 | } |
112 | ||
85aaf69f SL |
113 | impl ElidableRscope { |
114 | pub fn new(r: ty::Region) -> ElidableRscope { | |
115 | ElidableRscope { default: r } | |
1a4d82fc JJ |
116 | } |
117 | } | |
118 | ||
85aaf69f | 119 | impl 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. | |
142 | pub struct BindingRscope { | |
143 | anon_bindings: Cell<u32>, | |
144 | } | |
145 | ||
146 | impl 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 | ||
160 | impl 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. | |
182 | pub struct ObjectLifetimeDefaultRscope<'r> { | |
183 | base_scope: &'r (RegionScope+'r), | |
62682a34 | 184 | default: ty::ObjectLifetimeDefault, |
85aaf69f SL |
185 | } |
186 | ||
187 | impl<'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 | ||
199 | impl<'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. | |
229 | pub struct ShiftedRscope<'r> { | |
230 | base_scope: &'r (RegionScope+'r) | |
231 | } | |
232 | ||
233 | impl<'r> ShiftedRscope<'r> { | |
234 | pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> { | |
235 | ShiftedRscope { base_scope: base_scope } | |
236 | } | |
237 | } | |
238 | ||
239 | impl<'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 | } |