]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/rscope.rs
Add a doctest for the std::string::as_string method.
[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
12 use middle::ty;
13 use middle::ty_fold;
14
15 use std::cell::Cell;
16 use syntax::codemap::Span;
17
18 /// Defines strategies for handling regions that are omitted.  For
19 /// example, if one writes the type `&Foo`, then the lifetime of
20 /// this reference has been omitted. When converting this
21 /// type, the generic functions in astconv will invoke `anon_regions`
22 /// on the provided region-scope to decide how to translate this
23 /// omitted region.
24 ///
25 /// It is not always legal to omit regions, therefore `anon_regions`
26 /// can return `Err(())` to indicate that this is not a scope in which
27 /// regions can legally be omitted.
28 pub trait RegionScope {
29     fn anon_regions(&self,
30                     span: Span,
31                     count: uint)
32                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>;
33
34     fn default_region_bound(&self, span: Span) -> Option<ty::Region>;
35 }
36
37 // A scope in which all regions must be explicitly named. This is used
38 // for types that appear in structs and so on.
39 pub struct ExplicitRscope;
40
41 impl RegionScope for ExplicitRscope {
42     fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
43         None
44     }
45
46     fn anon_regions(&self,
47                     _span: Span,
48                     _count: uint)
49                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
50         Err(None)
51     }
52 }
53
54 // Same as `ExplicitRscope`, but provides some extra information for diagnostics
55 pub struct UnelidableRscope(Vec<(String, uint)>);
56
57 impl UnelidableRscope {
58     pub fn new(v: Vec<(String, uint)>) -> UnelidableRscope {
59         UnelidableRscope(v)
60     }
61 }
62
63 impl RegionScope for UnelidableRscope {
64     fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
65         None
66     }
67
68     fn anon_regions(&self,
69                     _span: Span,
70                     _count: uint)
71                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
72         let UnelidableRscope(ref v) = *self;
73         Err(Some(v.clone()))
74     }
75 }
76
77 // A scope in which any omitted region defaults to `default`. This is
78 // used after the `->` in function signatures, but also for backwards
79 // compatibility with object types. The latter use may go away.
80 pub struct SpecificRscope {
81     default: ty::Region
82 }
83
84 impl SpecificRscope {
85     pub fn new(r: ty::Region) -> SpecificRscope {
86         SpecificRscope { default: r }
87     }
88 }
89
90 impl RegionScope for SpecificRscope {
91     fn default_region_bound(&self, _span: Span) -> Option<ty::Region> {
92         Some(self.default)
93     }
94
95     fn anon_regions(&self,
96                     _span: Span,
97                     count: uint)
98                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
99     {
100         Ok(Vec::from_elem(count, self.default))
101     }
102 }
103
104 /// A scope in which we generate anonymous, late-bound regions for
105 /// omitted regions. This occurs in function signatures.
106 pub struct BindingRscope {
107     anon_bindings: Cell<uint>,
108 }
109
110 impl BindingRscope {
111     pub fn new() -> BindingRscope {
112         BindingRscope {
113             anon_bindings: Cell::new(0),
114         }
115     }
116
117     fn next_region(&self) -> ty::Region {
118         let idx = self.anon_bindings.get();
119         self.anon_bindings.set(idx + 1);
120         ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(idx))
121     }
122 }
123
124 impl RegionScope for BindingRscope {
125     fn default_region_bound(&self, _span: Span) -> Option<ty::Region>
126     {
127         Some(self.next_region())
128     }
129
130     fn anon_regions(&self,
131                     _: Span,
132                     count: uint)
133                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
134     {
135         Ok(Vec::from_fn(count, |_| self.next_region()))
136     }
137 }
138
139 /// A scope which simply shifts the Debruijn index of other scopes
140 /// to account for binding levels.
141 pub struct ShiftedRscope<'r> {
142     base_scope: &'r (RegionScope+'r)
143 }
144
145 impl<'r> ShiftedRscope<'r> {
146     pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> {
147         ShiftedRscope { base_scope: base_scope }
148     }
149 }
150
151 impl<'r> RegionScope for ShiftedRscope<'r> {
152     fn default_region_bound(&self, span: Span) -> Option<ty::Region>
153     {
154         self.base_scope.default_region_bound(span)
155             .map(|r| ty_fold::shift_region(r, 1))
156     }
157
158     fn anon_regions(&self,
159                     span: Span,
160                     count: uint)
161                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
162     {
163         match self.base_scope.anon_regions(span, count) {
164             Ok(mut v) => {
165                 for r in v.iter_mut() {
166                     *r = ty_fold::shift_region(*r, 1);
167                 }
168                 Ok(v)
169             }
170             Err(errs) => {
171                 Err(errs)
172             }
173         }
174     }
175 }