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