]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/rscope.rs
Auto merge of #27338 - alexcrichton:remove-morestack, r=brson
[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 syntax::codemap::Span;
17
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
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,
40                     count: usize)
41                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>;
42
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>;
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;
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.
58 #[derive(Copy, Clone)]
59 pub struct ExplicitRscope;
60
61 impl RegionScope for ExplicitRscope {
62     fn anon_regions(&self,
63                     _span: Span,
64                     _count: usize)
65                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
66         Err(None)
67     }
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     }
76 }
77
78 // Same as `ExplicitRscope`, but provides some extra information for diagnostics
79 pub struct UnelidableRscope(Option<Vec<ElisionFailureInfo>>);
80
81 impl UnelidableRscope {
82     pub fn new(v: Option<Vec<ElisionFailureInfo>>) -> UnelidableRscope {
83         UnelidableRscope(v)
84     }
85 }
86
87 impl RegionScope for UnelidableRscope {
88     fn anon_regions(&self,
89                     _span: Span,
90                     _count: usize)
91                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
92         let UnelidableRscope(ref v) = *self;
93         Err(v.clone())
94     }
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     }
103 }
104
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,
111 }
112
113 impl ElidableRscope {
114     pub fn new(r: ty::Region) -> ElidableRscope {
115         ElidableRscope { default: r }
116     }
117 }
118
119 impl RegionScope for ElidableRscope {
120     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
121         // Per RFC #599, object-lifetimes default to 'static unless
122         // overridden by context, and this takes precedence over
123         // lifetime elision.
124         Some(self.base_object_lifetime_default(span))
125     }
126
127     fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
128         ty::ReStatic
129     }
130
131     fn anon_regions(&self,
132                     _span: Span,
133                     count: usize)
134                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
135     {
136         Ok(vec![self.default; count])
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 {
161     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
162         // Per RFC #599, object-lifetimes default to 'static unless
163         // overridden by context, and this takes precedence over the
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
170     }
171
172     fn anon_regions(&self,
173                     _: Span,
174                     count: usize)
175                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
176     {
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),
184     default: ty::ObjectLifetimeDefault,
185 }
186
187 impl<'r> ObjectLifetimeDefaultRscope<'r> {
188     pub fn new(base_scope: &'r (RegionScope+'r),
189                default: ty::ObjectLifetimeDefault)
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 {
202             ty::ObjectLifetimeDefault::Ambiguous =>
203                 None,
204
205             ty::ObjectLifetimeDefault::BaseDefault =>
206                 // NB: This behavior changed in Rust 1.3.
207                 Some(self.base_object_lifetime_default(span)),
208
209             ty::ObjectLifetimeDefault::Specific(r) =>
210                 Some(r),
211         }
212     }
213
214     fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
215         self.base_scope.base_object_lifetime_default(span)
216     }
217
218     fn anon_regions(&self,
219                     span: Span,
220                     count: usize)
221                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
222     {
223         self.base_scope.anon_regions(span, count)
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> {
240     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
241         self.base_scope.object_lifetime_default(span)
242             .map(|r| ty_fold::shift_region(r, 1))
243     }
244
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
249     fn anon_regions(&self,
250                     span: Span,
251                     count: usize)
252                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
253     {
254         match self.base_scope.anon_regions(span, count) {
255             Ok(mut v) => {
256                 for r in &mut v {
257                     *r = ty_fold::shift_region(*r, 1);
258                 }
259                 Ok(v)
260             }
261             Err(errs) => {
262                 Err(errs)
263             }
264         }
265     }
266 }