]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/rscope.rs
Auto merge of #38645 - nikomatsakis:incr-comp-fix-time-depth, r=nrc
[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 use rustc::hir;
12 use rustc::hir::def_id::DefId;
13 use rustc::ty;
14 use rustc::ty::subst::Substs;
15
16 use astconv::AstConv;
17
18 use std::cell::Cell;
19 use syntax_pos::Span;
20
21 #[derive(Clone)]
22 pub struct ElisionFailureInfo {
23     /// Where we can find the argument pattern.
24     pub parent: Option<hir::BodyId>,
25     /// The index of the argument in the original definition.
26     pub index: usize,
27     pub lifetime_count: usize,
28     pub have_bound_regions: bool
29 }
30
31 pub type ElidedLifetime = Result<ty::Region, Option<Vec<ElisionFailureInfo>>>;
32
33 /// Defines strategies for handling regions that are omitted.  For
34 /// example, if one writes the type `&Foo`, then the lifetime of
35 /// this reference has been omitted. When converting this
36 /// type, the generic functions in astconv will invoke `anon_regions`
37 /// on the provided region-scope to decide how to translate this
38 /// omitted region.
39 ///
40 /// It is not always legal to omit regions, therefore `anon_regions`
41 /// can return `Err(())` to indicate that this is not a scope in which
42 /// regions can legally be omitted.
43 pub trait RegionScope {
44     fn anon_regions(&self,
45                     span: Span,
46                     count: usize)
47                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>;
48
49     /// If an object omits any explicit lifetime bound, and none can
50     /// be derived from the object traits, what should we use? If
51     /// `None` is returned, an explicit annotation is required.
52     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region>;
53
54     /// The "base" default is the initial default for a scope. This is
55     /// 'static except for in fn bodies, where it is a fresh inference
56     /// variable. You shouldn't call this except for as part of
57     /// computing `object_lifetime_default` (in particular, in legacy
58     /// modes, it may not be relevant).
59     fn base_object_lifetime_default(&self, span: Span) -> ty::Region;
60
61     /// If this scope allows anonymized types, return the generics in
62     /// scope, that anonymized types will close over. For example,
63     /// if you have a function like:
64     ///
65     ///     fn foo<'a, T>() -> impl Trait { ... }
66     ///
67     /// then, for the rscope that is used when handling the return type,
68     /// `anon_type_scope()` would return a `Some(AnonTypeScope {...})`,
69     /// on which `.fresh_substs(...)` can be used to obtain identity
70     /// Substs for `'a` and `T`, to track them in `TyAnon`. This property
71     /// is controlled by the region scope because it's fine-grained enough
72     /// to allow restriction of anonymized types to the syntactical extent
73     /// of a function's return type.
74     fn anon_type_scope(&self) -> Option<AnonTypeScope> {
75         None
76     }
77 }
78
79 #[derive(Copy, Clone)]
80 pub struct AnonTypeScope {
81     enclosing_item: DefId
82 }
83
84 impl<'gcx: 'tcx, 'tcx> AnonTypeScope {
85     pub fn new(enclosing_item: DefId) -> AnonTypeScope {
86         AnonTypeScope {
87             enclosing_item: enclosing_item
88         }
89     }
90
91     pub fn fresh_substs(&self, astconv: &AstConv<'gcx, 'tcx>, span: Span)
92                         -> &'tcx Substs<'tcx> {
93         use collect::mk_item_substs;
94
95         mk_item_substs(astconv, span, self.enclosing_item)
96     }
97 }
98
99 /// A scope wrapper which optionally allows anonymized types.
100 #[derive(Copy, Clone)]
101 pub struct MaybeWithAnonTypes<R> {
102     base_scope: R,
103     anon_scope: Option<AnonTypeScope>
104 }
105
106 impl<R: RegionScope> MaybeWithAnonTypes<R>  {
107     pub fn new(base_scope: R, anon_scope: Option<AnonTypeScope>) -> Self {
108         MaybeWithAnonTypes {
109             base_scope: base_scope,
110             anon_scope: anon_scope
111         }
112     }
113 }
114
115 impl<R: RegionScope> RegionScope for MaybeWithAnonTypes<R> {
116     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
117         self.base_scope.object_lifetime_default(span)
118     }
119
120     fn anon_regions(&self,
121                     span: Span,
122                     count: usize)
123                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
124         self.base_scope.anon_regions(span, count)
125     }
126
127     fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
128         self.base_scope.base_object_lifetime_default(span)
129     }
130
131     fn anon_type_scope(&self) -> Option<AnonTypeScope> {
132         self.anon_scope
133     }
134 }
135
136 // A scope in which all regions must be explicitly named. This is used
137 // for types that appear in structs and so on.
138 #[derive(Copy, Clone)]
139 pub struct ExplicitRscope;
140
141 impl RegionScope for ExplicitRscope {
142     fn anon_regions(&self,
143                     _span: Span,
144                     _count: usize)
145                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
146         Err(None)
147     }
148
149     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
150         Some(self.base_object_lifetime_default(span))
151     }
152
153     fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
154         ty::ReStatic
155     }
156 }
157
158 // Same as `ExplicitRscope`, but provides some extra information for diagnostics
159 pub struct UnelidableRscope(Option<Vec<ElisionFailureInfo>>);
160
161 impl UnelidableRscope {
162     pub fn new(v: Option<Vec<ElisionFailureInfo>>) -> UnelidableRscope {
163         UnelidableRscope(v)
164     }
165 }
166
167 impl RegionScope for UnelidableRscope {
168     fn anon_regions(&self,
169                     _span: Span,
170                     _count: usize)
171                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
172         let UnelidableRscope(ref v) = *self;
173         Err(v.clone())
174     }
175
176     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
177         Some(self.base_object_lifetime_default(span))
178     }
179
180     fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
181         ty::ReStatic
182     }
183 }
184
185 // A scope in which omitted anonymous region defaults to
186 // `default`. This is used after the `->` in function signatures. The
187 // latter use may go away. Note that object-lifetime defaults work a
188 // bit differently, as specified in RFC #599.
189 pub struct ElidableRscope {
190     default: ty::Region,
191 }
192
193 impl ElidableRscope {
194     pub fn new(r: ty::Region) -> ElidableRscope {
195         ElidableRscope { default: r }
196     }
197 }
198
199 impl RegionScope for ElidableRscope {
200     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
201         // Per RFC #599, object-lifetimes default to 'static unless
202         // overridden by context, and this takes precedence over
203         // lifetime elision.
204         Some(self.base_object_lifetime_default(span))
205     }
206
207     fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
208         ty::ReStatic
209     }
210
211     fn anon_regions(&self,
212                     _span: Span,
213                     count: usize)
214                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
215     {
216         Ok(vec![self.default; count])
217     }
218 }
219
220 /// A scope that behaves as an ElidabeRscope with a `'static` default region
221 /// that should also warn if the `static_in_const` feature is unset.
222 #[derive(Copy, Clone)]
223 pub struct StaticRscope<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
224     tcx: &'a ty::TyCtxt<'a, 'gcx, 'tcx>,
225 }
226
227 impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> StaticRscope<'a, 'gcx, 'tcx> {
228     /// create a new StaticRscope from a reference to the `TyCtxt`
229     pub fn new(tcx: &'a ty::TyCtxt<'a, 'gcx, 'tcx>) -> Self {
230         StaticRscope { tcx: tcx }
231     }
232 }
233
234 impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> RegionScope for StaticRscope<'a, 'gcx, 'tcx> {
235     fn anon_regions(&self,
236                     span: Span,
237                     count: usize)
238                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
239         if !self.tcx.sess.features.borrow().static_in_const {
240             self.tcx
241                 .sess
242                 .struct_span_err(span,
243                                  "this needs a `'static` lifetime or the \
244                                  `static_in_const` feature, see #35897")
245                 .emit();
246         }
247         Ok(vec![ty::ReStatic; count])
248     }
249
250     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
251         Some(self.base_object_lifetime_default(span))
252     }
253
254     fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
255         ty::ReStatic
256     }
257 }
258
259 /// A scope in which we generate anonymous, late-bound regions for
260 /// omitted regions. This occurs in function signatures.
261 pub struct BindingRscope {
262     anon_bindings: Cell<u32>,
263 }
264
265 impl BindingRscope {
266     pub fn new() -> BindingRscope {
267         BindingRscope {
268             anon_bindings: Cell::new(0),
269         }
270     }
271
272     fn next_region(&self) -> ty::Region {
273         let idx = self.anon_bindings.get();
274         self.anon_bindings.set(idx + 1);
275         ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(idx))
276     }
277 }
278
279 impl RegionScope for BindingRscope {
280     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
281         // Per RFC #599, object-lifetimes default to 'static unless
282         // overridden by context, and this takes precedence over the
283         // binding defaults in a fn signature.
284         Some(self.base_object_lifetime_default(span))
285     }
286
287     fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
288         ty::ReStatic
289     }
290
291     fn anon_regions(&self,
292                     _: Span,
293                     count: usize)
294                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
295     {
296         Ok((0..count).map(|_| self.next_region()).collect())
297     }
298 }
299
300 /// A scope which overrides the default object lifetime but has no other effect.
301 pub struct ObjectLifetimeDefaultRscope<'r> {
302     base_scope: &'r (RegionScope+'r),
303     default: ty::ObjectLifetimeDefault<'r>,
304 }
305
306 impl<'r> ObjectLifetimeDefaultRscope<'r> {
307     pub fn new(base_scope: &'r (RegionScope+'r),
308                default: ty::ObjectLifetimeDefault<'r>)
309                -> ObjectLifetimeDefaultRscope<'r>
310     {
311         ObjectLifetimeDefaultRscope {
312             base_scope: base_scope,
313             default: default,
314         }
315     }
316 }
317
318 impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
319     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
320         match self.default {
321             ty::ObjectLifetimeDefault::Ambiguous =>
322                 None,
323
324             ty::ObjectLifetimeDefault::BaseDefault =>
325                 // NB: This behavior changed in Rust 1.3.
326                 Some(self.base_object_lifetime_default(span)),
327
328             ty::ObjectLifetimeDefault::Specific(r) =>
329                 Some(*r),
330         }
331     }
332
333     fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
334         self.base_scope.base_object_lifetime_default(span)
335     }
336
337     fn anon_regions(&self,
338                     span: Span,
339                     count: usize)
340                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
341     {
342         self.base_scope.anon_regions(span, count)
343     }
344
345     fn anon_type_scope(&self) -> Option<AnonTypeScope> {
346         self.base_scope.anon_type_scope()
347     }
348 }
349
350 /// A scope which simply shifts the Debruijn index of other scopes
351 /// to account for binding levels.
352 pub struct ShiftedRscope<'r> {
353     base_scope: &'r (RegionScope+'r)
354 }
355
356 impl<'r> ShiftedRscope<'r> {
357     pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> {
358         ShiftedRscope { base_scope: base_scope }
359     }
360 }
361
362 impl<'r> RegionScope for ShiftedRscope<'r> {
363     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
364         self.base_scope.object_lifetime_default(span)
365             .map(|r| ty::fold::shift_region(r, 1))
366     }
367
368     fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
369         ty::fold::shift_region(self.base_scope.base_object_lifetime_default(span), 1)
370     }
371
372     fn anon_regions(&self,
373                     span: Span,
374                     count: usize)
375                     -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
376     {
377         match self.base_scope.anon_regions(span, count) {
378             Ok(mut v) => {
379                 for r in &mut v {
380                     *r = ty::fold::shift_region(*r, 1);
381                 }
382                 Ok(v)
383             }
384             Err(errs) => {
385                 Err(errs)
386             }
387         }
388     }
389
390     fn anon_type_scope(&self) -> Option<AnonTypeScope> {
391         self.base_scope.anon_type_scope()
392     }
393 }