]> git.lizzy.rs Git - rust.git/blob - src/librustc_typeck/rscope.rs
check: Reword the warning to be more prescriptive
[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 std::iter::repeat;
17 use syntax::codemap::Span;
18
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
24 /// omitted region.
25 ///
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,
31                     span: Span,
32                     count: uint)
33                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>;
34
35     /// If an object omits any explicit lifetime bound, and none can
36     /// be derived from the object traits, what should we use? If
37     /// `None` is returned, an explicit annotation is required.
38     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region>;
39 }
40
41 // A scope in which all regions must be explicitly named. This is used
42 // for types that appear in structs and so on.
43 #[derive(Copy)]
44 pub struct ExplicitRscope;
45
46 impl RegionScope for ExplicitRscope {
47     fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
48         Some(ty::ReStatic)
49     }
50
51     fn anon_regions(&self,
52                     _span: Span,
53                     _count: uint)
54                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
55         Err(None)
56     }
57 }
58
59 // Same as `ExplicitRscope`, but provides some extra information for diagnostics
60 pub struct UnelidableRscope(Vec<(String, uint)>);
61
62 impl UnelidableRscope {
63     pub fn new(v: Vec<(String, uint)>) -> UnelidableRscope {
64         UnelidableRscope(v)
65     }
66 }
67
68 impl RegionScope for UnelidableRscope {
69     fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
70         Some(ty::ReStatic)
71     }
72
73     fn anon_regions(&self,
74                     _span: Span,
75                     _count: uint)
76                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>> {
77         let UnelidableRscope(ref v) = *self;
78         Err(Some(v.clone()))
79     }
80 }
81
82 // A scope in which omitted anonymous region defaults to
83 // `default`. This is used after the `->` in function signatures. The
84 // latter use may go away. Note that object-lifetime defaults work a
85 // bit differently, as specified in RFC #599.
86 pub struct ElidableRscope {
87     default: ty::Region,
88 }
89
90 impl ElidableRscope {
91     pub fn new(r: ty::Region) -> ElidableRscope {
92         ElidableRscope { default: r }
93     }
94 }
95
96 impl RegionScope for ElidableRscope {
97     fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
98         // Per RFC #599, object-lifetimes default to 'static unless
99         // overridden by context, and this takes precedence over
100         // lifetime elision.
101         Some(ty::ReStatic)
102     }
103
104     fn anon_regions(&self,
105                     _span: Span,
106                     count: uint)
107                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
108     {
109         Ok(repeat(self.default).take(count).collect())
110     }
111 }
112
113 /// A scope in which we generate anonymous, late-bound regions for
114 /// omitted regions. This occurs in function signatures.
115 pub struct BindingRscope {
116     anon_bindings: Cell<u32>,
117 }
118
119 impl BindingRscope {
120     pub fn new() -> BindingRscope {
121         BindingRscope {
122             anon_bindings: Cell::new(0),
123         }
124     }
125
126     fn next_region(&self) -> ty::Region {
127         let idx = self.anon_bindings.get();
128         self.anon_bindings.set(idx + 1);
129         ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(idx))
130     }
131 }
132
133 impl RegionScope for BindingRscope {
134     fn object_lifetime_default(&self, _span: Span) -> Option<ty::Region> {
135         // Per RFC #599, object-lifetimes default to 'static unless
136         // overridden by context, and this takes precedence over the
137         // binding defaults.
138         Some(ty::ReStatic)
139     }
140
141     fn anon_regions(&self,
142                     _: Span,
143                     count: uint)
144                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
145     {
146         Ok((0..count).map(|_| self.next_region()).collect())
147     }
148 }
149
150 /// A scope which overrides the default object lifetime but has no other effect.
151 pub struct ObjectLifetimeDefaultRscope<'r> {
152     base_scope: &'r (RegionScope+'r),
153     default: Option<ty::ObjectLifetimeDefault>,
154 }
155
156 impl<'r> ObjectLifetimeDefaultRscope<'r> {
157     pub fn new(base_scope: &'r (RegionScope+'r),
158                default: Option<ty::ObjectLifetimeDefault>)
159                -> ObjectLifetimeDefaultRscope<'r>
160     {
161         ObjectLifetimeDefaultRscope {
162             base_scope: base_scope,
163             default: default,
164         }
165     }
166 }
167
168 impl<'r> RegionScope for ObjectLifetimeDefaultRscope<'r> {
169     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
170         match self.default {
171             None => self.base_scope.object_lifetime_default(span),
172             Some(ty::ObjectLifetimeDefault::Ambiguous) => None,
173             Some(ty::ObjectLifetimeDefault::Specific(r)) => Some(r),
174         }
175     }
176
177     fn anon_regions(&self,
178                     span: Span,
179                     count: uint)
180                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
181     {
182         self.base_scope.anon_regions(span, count)
183     }
184 }
185
186 /// A scope which simply shifts the Debruijn index of other scopes
187 /// to account for binding levels.
188 pub struct ShiftedRscope<'r> {
189     base_scope: &'r (RegionScope+'r)
190 }
191
192 impl<'r> ShiftedRscope<'r> {
193     pub fn new(base_scope: &'r (RegionScope+'r)) -> ShiftedRscope<'r> {
194         ShiftedRscope { base_scope: base_scope }
195     }
196 }
197
198 impl<'r> RegionScope for ShiftedRscope<'r> {
199     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
200         self.base_scope.object_lifetime_default(span)
201             .map(|r| ty_fold::shift_region(r, 1))
202     }
203
204     fn anon_regions(&self,
205                     span: Span,
206                     count: uint)
207                     -> Result<Vec<ty::Region>, Option<Vec<(String, uint)>>>
208     {
209         match self.base_scope.anon_regions(span, count) {
210             Ok(mut v) => {
211                 for r in &mut v {
212                     *r = ty_fold::shift_region(*r, 1);
213                 }
214                 Ok(v)
215             }
216             Err(errs) => {
217                 Err(errs)
218             }
219         }
220     }
221 }