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.
15 use syntax::codemap::Span;
18 pub struct ElisionFailureInfo {
20 pub lifetime_count: usize,
21 pub have_bound_regions: bool
24 pub type ElidedLifetime = Result<ty::Region, Option<Vec<ElisionFailureInfo>>>;
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
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,
40 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>;
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>;
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;
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;
60 impl RegionScope for ExplicitRscope {
61 fn anon_regions(&self,
64 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
68 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
69 Some(self.base_object_lifetime_default(span))
72 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
77 // Same as `ExplicitRscope`, but provides some extra information for diagnostics
78 pub struct UnelidableRscope(Option<Vec<ElisionFailureInfo>>);
80 impl UnelidableRscope {
81 pub fn new(v: Option<Vec<ElisionFailureInfo>>) -> UnelidableRscope {
86 impl RegionScope for UnelidableRscope {
87 fn anon_regions(&self,
90 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>> {
91 let UnelidableRscope(ref v) = *self;
95 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
96 Some(self.base_object_lifetime_default(span))
99 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
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 {
112 impl ElidableRscope {
113 pub fn new(r: ty::Region) -> ElidableRscope {
114 ElidableRscope { default: r }
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
123 Some(self.base_object_lifetime_default(span))
126 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
130 fn anon_regions(&self,
133 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
135 Ok(vec![self.default; count])
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>,
146 pub fn new() -> BindingRscope {
148 anon_bindings: Cell::new(0),
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))
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))
167 fn base_object_lifetime_default(&self, _span: Span) -> ty::Region {
171 fn anon_regions(&self,
174 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
176 Ok((0..count).map(|_| self.next_region()).collect())
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,
186 impl<'r> ObjectLifetimeDefaultRscope<'r> {
187 pub fn new(base_scope: &'r (RegionScope+'r),
188 default: ty::ObjectLifetimeDefault)
189 -> ObjectLifetimeDefaultRscope<'r>
191 ObjectLifetimeDefaultRscope {
192 base_scope: base_scope,
198 impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
199 fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
201 ty::ObjectLifetimeDefault::Ambiguous =>
204 ty::ObjectLifetimeDefault::BaseDefault =>
205 // NB: This behavior changed in Rust 1.3.
206 Some(self.base_object_lifetime_default(span)),
208 ty::ObjectLifetimeDefault::Specific(r) =>
213 fn base_object_lifetime_default(&self, span: Span) -> ty::Region {
214 self.base_scope.base_object_lifetime_default(span)
217 fn anon_regions(&self,
220 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
222 self.base_scope.anon_regions(span, count)
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)
232 impl<'r> ShiftedRscope<'r> {
233 pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> {
234 ShiftedRscope { base_scope: base_scope }
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))
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)
248 fn anon_regions(&self,
251 -> Result<Vec<ty::Region>, Option<Vec<ElisionFailureInfo>>>
253 match self.base_scope.anon_regions(span, count) {
256 *r = ty::fold::shift_region(*r, 1);