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.
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.
12 use rustc::hir::def_id::DefId;
14 use rustc::ty::subst::Substs;
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.
27 pub lifetime_count: usize,
28 pub have_bound_regions: bool
31 pub type ElidedLifetime = Result<ty::Region, Option<Vec<ElisionFailureInfo>>>;
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
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,
47 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>;
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>;
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;
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:
65 /// fn foo<'a, T>() -> impl Trait { ... }
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> {
79 #[derive(Copy, Clone)]
80 pub struct AnonTypeScope {
84 impl<'gcx: 'tcx, 'tcx> AnonTypeScope {
85 pub fn new(enclosing_item: DefId) -> AnonTypeScope {
87 enclosing_item: enclosing_item
91 pub fn fresh_substs(&self, astconv: &AstConv<'gcx, 'tcx>, span: Span)
92 -> &'tcx Substs<'tcx> {
93 use collect::mk_item_substs;
95 mk_item_substs(astconv, span, self.enclosing_item)
99 /// A scope wrapper which optionally allows anonymized types.
100 #[derive(Copy, Clone)]
101 pub struct MaybeWithAnonTypes<R> {
103 anon_scope: Option<AnonTypeScope>
106 impl<R: RegionScope> MaybeWithAnonTypes<R> {
107 pub fn new(base_scope: R, anon_scope: Option<AnonTypeScope>) -> Self {
109 base_scope: base_scope,
110 anon_scope: anon_scope
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)
120 fn anon_regions(&self,
123 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
124 self.base_scope.anon_regions(span, count)
127 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
128 self.base_scope.base_object_lifetime_default(span)
131 fn anon_type_scope(&self) -> Option<AnonTypeScope> {
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;
141 impl RegionScope for ExplicitRscope {
142 fn anon_regions(&self,
145 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
149 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
150 Some(self.base_object_lifetime_default(span))
153 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
158 // Same as `ExplicitRscope`, but provides some extra information for diagnostics
159 pub struct UnelidableRscope(Option<Vec<ElisionFailureInfo>>);
161 impl UnelidableRscope {
162 pub fn new(v: Option<Vec<ElisionFailureInfo>>) -> UnelidableRscope {
167 impl RegionScope for UnelidableRscope {
168 fn anon_regions(&self,
171 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
172 let UnelidableRscope(ref v) = *self;
176 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
177 Some(self.base_object_lifetime_default(span))
180 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
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 {
193 impl ElidableRscope {
194 pub fn new(r: ty::Region) -> ElidableRscope {
195 ElidableRscope { default: r }
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
204 Some(self.base_object_lifetime_default(span))
207 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
211 fn anon_regions(&self,
214 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
216 Ok(vec![self.default; count])
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>,
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 }
234 impl<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> RegionScope for StaticRscope<'a, 'gcx, 'tcx> {
235 fn anon_regions(&self,
238 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
239 if !self.tcx.sess.features.borrow().static_in_const {
242 .struct_span_err(span,
243 "this needs a `'static` lifetime or the \
244 `static_in_const` feature, see #35897")
247 Ok(vec![ty::ReStatic; count])
250 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
251 Some(self.base_object_lifetime_default(span))
254 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
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>,
266 pub fn new() -> BindingRscope {
268 anon_bindings: Cell::new(0),
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))
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))
287 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
291 fn anon_regions(&self,
294 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
296 Ok((0..count).map(|_| self.next_region()).collect())
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>,
306 impl<'r> ObjectLifetimeDefaultRscope<'r> {
307 pub fn new(base_scope: &'r (RegionScope+'r),
308 default: ty::ObjectLifetimeDefault<'r>)
309 -> ObjectLifetimeDefaultRscope<'r>
311 ObjectLifetimeDefaultRscope {
312 base_scope: base_scope,
318 impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
319 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
321 ty::ObjectLifetimeDefault::Ambiguous =>
324 ty::ObjectLifetimeDefault::BaseDefault =>
325 // NB: This behavior changed in Rust 1.3.
326 Some(self.base_object_lifetime_default(span)),
328 ty::ObjectLifetimeDefault::Specific(r) =>
333 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
334 self.base_scope.base_object_lifetime_default(span)
337 fn anon_regions(&self,
340 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
342 self.base_scope.anon_regions(span, count)
345 fn anon_type_scope(&self) -> Option<AnonTypeScope> {
346 self.base_scope.anon_type_scope()
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)
356 impl<'r> ShiftedRscope<'r> {
357 pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> {
358 ShiftedRscope { base_scope: base_scope }
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))
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)
372 fn anon_regions(&self,
375 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
377 match self.base_scope.anon_regions(span, count) {
380 *r = ty::fold::shift_region(*r, 1);
390 fn anon_type_scope(&self) -> Option<AnonTypeScope> {
391 self.base_scope.anon_type_scope()