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