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.
11 use rustc::hir::def_id::DefId;
13 use rustc::ty::subst::Substs;
21 pub struct ElisionFailureInfo {
23 pub lifetime_count: usize,
24 pub have_bound_regions: bool
27 pub type ElidedLifetime = Result<ty::Region, Option<Vec<ElisionFailureInfo>>>;
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
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,
43 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>;
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>;
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;
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:
61 /// fn foo<'a, T>() -> impl Trait { ... }
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> {
75 #[derive(Copy, Clone)]
76 pub struct AnonTypeScope {
80 impl<'gcx: 'tcx, 'tcx> AnonTypeScope {
81 pub fn new(enclosing_item: DefId) -> AnonTypeScope {
83 enclosing_item: enclosing_item
87 pub fn fresh_substs(&self, astconv: &AstConv<'gcx, 'tcx>, span: Span)
88 -> &'tcx Substs<'tcx> {
89 use collect::mk_item_substs;
91 mk_item_substs(astconv, span, self.enclosing_item)
95 /// A scope wrapper which optionally allows anonymized types.
96 #[derive(Copy, Clone)]
97 pub struct MaybeWithAnonTypes<R> {
99 anon_scope: Option<AnonTypeScope>
102 impl<R: RegionScope> MaybeWithAnonTypes<R> {
103 pub fn new(base_scope: R, anon_scope: Option<AnonTypeScope>) -> Self {
105 base_scope: base_scope,
106 anon_scope: anon_scope
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)
116 fn anon_regions(&self,
119 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
120 self.base_scope.anon_regions(span, count)
123 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
124 self.base_scope.base_object_lifetime_default(span)
127 fn anon_type_scope(&self) -> Option<AnonTypeScope> {
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;
137 impl RegionScope for ExplicitRscope {
138 fn anon_regions(&self,
141 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
145 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
146 Some(self.base_object_lifetime_default(span))
149 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
154 // Same as `ExplicitRscope`, but provides some extra information for diagnostics
155 pub struct UnelidableRscope(Option<Vec<ElisionFailureInfo>>);
157 impl UnelidableRscope {
158 pub fn new(v: Option<Vec<ElisionFailureInfo>>) -> UnelidableRscope {
163 impl RegionScope for UnelidableRscope {
164 fn anon_regions(&self,
167 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
168 let UnelidableRscope(ref v) = *self;
172 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
173 Some(self.base_object_lifetime_default(span))
176 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
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 {
189 impl ElidableRscope {
190 pub fn new(r: ty::Region) -> ElidableRscope {
191 ElidableRscope { default: r }
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
200 Some(self.base_object_lifetime_default(span))
203 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
207 fn anon_regions(&self,
210 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
212 Ok(vec![self.default; count])
216 /// A scope in which we generate anonymous, late-bound regions for
217 /// omitted regions. This occurs in function signatures.
218 pub struct BindingRscope {
219 anon_bindings: Cell<u32>,
223 pub fn new() -> BindingRscope {
225 anon_bindings: Cell::new(0),
229 fn next_region(&self) -> ty::Region {
230 let idx = self.anon_bindings.get();
231 self.anon_bindings.set(idx + 1);
232 ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(idx))
236 impl RegionScope for BindingRscope {
237 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
238 // Per RFC #599, object-lifetimes default to 'static unless
239 // overridden by context, and this takes precedence over the
240 // binding defaults in a fn signature.
241 Some(self.base_object_lifetime_default(span))
244 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
248 fn anon_regions(&self,
251 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
253 Ok((0..count).map(|_| self.next_region()).collect())
257 /// A scope which overrides the default object lifetime but has no other effect.
258 pub struct ObjectLifetimeDefaultRscope<'r> {
259 base_scope: &'r (RegionScope+'r),
260 default: ty::ObjectLifetimeDefault,
263 impl<'r> ObjectLifetimeDefaultRscope<'r> {
264 pub fn new(base_scope: &'r (RegionScope+'r),
265 default: ty::ObjectLifetimeDefault)
266 -> ObjectLifetimeDefaultRscope<'r>
268 ObjectLifetimeDefaultRscope {
269 base_scope: base_scope,
275 impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
276 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
278 ty::ObjectLifetimeDefault::Ambiguous =>
281 ty::ObjectLifetimeDefault::BaseDefault =>
282 // NB: This behavior changed in Rust 1.3.
283 Some(self.base_object_lifetime_default(span)),
285 ty::ObjectLifetimeDefault::Specific(r) =>
290 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
291 self.base_scope.base_object_lifetime_default(span)
294 fn anon_regions(&self,
297 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
299 self.base_scope.anon_regions(span, count)
302 fn anon_type_scope(&self) -> Option<AnonTypeScope> {
303 self.base_scope.anon_type_scope()
307 /// A scope which simply shifts the Debruijn index of other scopes
308 /// to account for binding levels.
309 pub struct ShiftedRscope<'r> {
310 base_scope: &'r (RegionScope+'r)
313 impl<'r> ShiftedRscope<'r> {
314 pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> {
315 ShiftedRscope { base_scope: base_scope }
319 impl<'r> RegionScope for ShiftedRscope<'r> {
320 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
321 self.base_scope.object_lifetime_default(span)
322 .map(|r| ty::fold::shift_region(r, 1))
325 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
326 ty::fold::shift_region(self.base_scope.base_object_lifetime_default(span), 1)
329 fn anon_regions(&self,
332 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
334 match self.base_scope.anon_regions(span, count) {
337 *r = ty::fold::shift_region(*r, 1);
347 fn anon_type_scope(&self) -> Option<AnonTypeScope> {
348 self.base_scope.anon_type_scope()