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.
16 use std::iter::repeat;
17 use syntax::codemap::Span;
19 /// Defines strategies for handling regions that are omitted. For
20 /// example, if one writes the type `&Foo`, then the lifetime of
21 /// this reference has been omitted. When converting this
22 /// type, the generic functions in astconv will invoke `anon_regions`
23 /// on the provided region-scope to decide how to translate this
26 /// It is not always legal to omit regions, therefore `anon_regions`
27 /// can return `Err(())` to indicate that this is not a scope in which
28 /// regions can legally be omitted.
29 pub trait RegionScope {
30 fn anon_regions(&self,
33 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>;
35 fn default_region_bound(&self, span: Span) -> Option<ty::Region>;
38 // A scope in which all regions must be explicitly named. This is used
39 // for types that appear in structs and so on.
41 pub struct ExplicitRscope;
43 impl RegionScope for ExplicitRscope {
44 fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
48 fn anon_regions(&self,
51 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
56 // Same as `ExplicitRscope`, but provides some extra information for diagnostics
57 pub struct UnelidableRscope(Vec<(String, uint)>);
59 impl UnelidableRscope {
60 pub fn new(v: Vec<(String, uint)>) -> UnelidableRscope {
65 impl RegionScope for UnelidableRscope {
66 fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
70 fn anon_regions(&self,
73 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
74 let UnelidableRscope(ref v) = *self;
79 // A scope in which any omitted region defaults to `default`. This is
80 // used after the `->` in function signatures, but also for backwards
81 // compatibility with object types. The latter use may go away.
82 #[allow(missing_copy_implementations)]
83 pub struct SpecificRscope {
88 pub fn new(r: ty::Region) -> SpecificRscope {
89 SpecificRscope { default: r }
93 impl RegionScope for SpecificRscope {
94 fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
98 fn anon_regions(&self,
101 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
103 Ok(repeat(self.default).take(count).collect())
107 /// A scope in which we generate anonymous, late-bound regions for
108 /// omitted regions. This occurs in function signatures.
109 pub struct BindingRscope {
110 anon_bindings: Cell<u32>,
114 pub fn new() -> BindingRscope {
116 anon_bindings: Cell::new(0),
120 fn next_region(&self) -> ty::Region {
121 let idx = self.anon_bindings.get();
122 self.anon_bindings.set(idx + 1);
123 ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(idx))
127 impl RegionScope for BindingRscope {
128 fn default_region_bound(&self, _span: Span) -> Option<ty::Region>
130 Some(self.next_region())
133 fn anon_regions(&self,
136 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
138 Ok(range(0, count).map(|_| self.next_region()).collect())
142 /// A scope which simply shifts the Debruijn index of other scopes
143 /// to account for binding levels.
144 pub struct ShiftedRscope<'r> {
145 base_scope: &'r (RegionScope+'r)
148 impl<'r> ShiftedRscope<'r> {
149 pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> {
150 ShiftedRscope { base_scope: base_scope }
154 impl<'r> RegionScope for ShiftedRscope<'r> {
155 fn default_region_bound(&self, span: Span) -> Option<ty::Region>
157 self.base_scope.default_region_bound(span)
158 .map(|r| ty_fold::shift_region(r, 1))
161 fn anon_regions(&self,
164 -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
166 match self.base_scope.anon_regions(span, count) {
168 for r in v.iter_mut() {
169 *r = ty_fold::shift_region(*r, 1);