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
, usize)>>>;
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
>;
40 /// The "base" default is the initial default for a scope. This is
41 /// 'static except for in fn bodies, where it is a fresh inference
42 /// variable. You shouldn't call this except for as part of
43 /// computing `object_lifetime_default` (in particular, in legacy
44 /// modes, it may not be relevant).
45 fn base_object_lifetime_default(&self, span
: Span
) -> ty
::Region
;
47 /// Used to issue warnings in Rust 1.2, not needed after that.
48 /// True if the result of `object_lifetime_default` will change in 1.3.
49 fn object_lifetime_default_will_change_in_1_3(&self) -> bool
{
53 /// Used to issue warnings in Rust 1.2, not needed after that.
54 /// True if the result of `base_object_lifetime_default` differs
55 /// from the result of `object_lifetime_default`.
56 fn base_object_lifetime_default_differs(&self) -> bool
{
61 // A scope in which all regions must be explicitly named. This is used
62 // for types that appear in structs and so on.
63 #[derive(Copy, Clone)]
64 pub struct ExplicitRscope
;
66 impl RegionScope
for ExplicitRscope
{
67 fn anon_regions(&self,
70 -> Result
<Vec
<ty
::Region
>, Option
<Vec
<(String
, usize)>>> {
74 fn object_lifetime_default(&self, span
: Span
) -> Option
<ty
::Region
> {
75 Some(self.base_object_lifetime_default(span
))
78 fn base_object_lifetime_default(&self, _span
: Span
) -> ty
::Region
{
83 // Same as `ExplicitRscope`, but provides some extra information for diagnostics
84 pub struct UnelidableRscope(Vec
<(String
, usize)>);
86 impl UnelidableRscope
{
87 pub fn new(v
: Vec
<(String
, usize)>) -> UnelidableRscope
{
92 impl RegionScope
for UnelidableRscope
{
93 fn anon_regions(&self,
96 -> Result
<Vec
<ty
::Region
>, Option
<Vec
<(String
, usize)>>> {
97 let UnelidableRscope(ref v
) = *self;
101 fn object_lifetime_default(&self, span
: Span
) -> Option
<ty
::Region
> {
102 Some(self.base_object_lifetime_default(span
))
105 fn base_object_lifetime_default(&self, _span
: Span
) -> ty
::Region
{
110 // A scope in which omitted anonymous region defaults to
111 // `default`. This is used after the `->` in function signatures. The
112 // latter use may go away. Note that object-lifetime defaults work a
113 // bit differently, as specified in RFC #599.
114 pub struct ElidableRscope
{
118 impl ElidableRscope
{
119 pub fn new(r
: ty
::Region
) -> ElidableRscope
{
120 ElidableRscope { default: r }
124 impl RegionScope
for ElidableRscope
{
125 fn object_lifetime_default(&self, span
: Span
) -> Option
<ty
::Region
> {
126 // Per RFC #599, object-lifetimes default to 'static unless
127 // overridden by context, and this takes precedence over
129 Some(self.base_object_lifetime_default(span
))
132 fn base_object_lifetime_default(&self, _span
: Span
) -> ty
::Region
{
136 fn anon_regions(&self,
139 -> Result
<Vec
<ty
::Region
>, Option
<Vec
<(String
, usize)>>>
141 Ok(repeat(self.default).take(count
).collect())
145 /// A scope in which we generate anonymous, late-bound regions for
146 /// omitted regions. This occurs in function signatures.
147 pub struct BindingRscope
{
148 anon_bindings
: Cell
<u32>,
152 pub fn new() -> BindingRscope
{
154 anon_bindings
: Cell
::new(0),
158 fn next_region(&self) -> ty
::Region
{
159 let idx
= self.anon_bindings
.get();
160 self.anon_bindings
.set(idx
+ 1);
161 ty
::ReLateBound(ty
::DebruijnIndex
::new(1), ty
::BrAnon(idx
))
165 impl RegionScope
for BindingRscope
{
166 fn object_lifetime_default(&self, span
: Span
) -> Option
<ty
::Region
> {
167 // Per RFC #599, object-lifetimes default to 'static unless
168 // overridden by context, and this takes precedence over the
169 // binding defaults in a fn signature.
170 Some(self.base_object_lifetime_default(span
))
173 fn base_object_lifetime_default(&self, _span
: Span
) -> ty
::Region
{
177 fn anon_regions(&self,
180 -> Result
<Vec
<ty
::Region
>, Option
<Vec
<(String
, usize)>>>
182 Ok((0..count
).map(|_
| self.next_region()).collect())
186 /// A scope which overrides the default object lifetime but has no other effect.
187 pub struct ObjectLifetimeDefaultRscope
<'r
> {
188 base_scope
: &'
r (RegionScope
+'r
),
189 default: ty
::ObjectLifetimeDefault
,
192 impl<'r
> ObjectLifetimeDefaultRscope
<'r
> {
193 pub fn new(base_scope
: &'
r (RegionScope
+'r
),
194 default: ty
::ObjectLifetimeDefault
)
195 -> ObjectLifetimeDefaultRscope
<'r
>
197 ObjectLifetimeDefaultRscope
{
198 base_scope
: base_scope
,
204 impl<'r
> RegionScope
for ObjectLifetimeDefaultRscope
<'r
> {
205 fn object_lifetime_default(&self, span
: Span
) -> Option
<ty
::Region
> {
207 ty
::ObjectLifetimeDefault
::Ambiguous
=>
210 ty
::ObjectLifetimeDefault
::BaseDefault
=>
211 if false { // this will become the behavior in Rust 1.3
212 Some(self.base_object_lifetime_default(span
))
214 self.base_scope
.object_lifetime_default(span
)
217 ty
::ObjectLifetimeDefault
::Specific(r
) =>
222 fn base_object_lifetime_default(&self, span
: Span
) -> ty
::Region
{
223 assert
!(false, "this code should not execute until Rust 1.3");
224 self.base_scope
.base_object_lifetime_default(span
)
227 fn object_lifetime_default_will_change_in_1_3(&self) -> bool
{
228 debug
!("object_lifetime_default_will_change_in_1_3: {:?}", self.default);
231 ty
::ObjectLifetimeDefault
::Ambiguous
|
232 ty
::ObjectLifetimeDefault
::Specific(_
) =>
235 ty
::ObjectLifetimeDefault
::BaseDefault
=>
236 self.base_scope
.base_object_lifetime_default_differs()
240 fn base_object_lifetime_default_differs(&self) -> bool
{
241 debug
!("base_object_lifetime_default_differs: {:?}", self.default);
244 ty
::ObjectLifetimeDefault
::Ambiguous
|
245 ty
::ObjectLifetimeDefault
::Specific(_
) =>
248 ty
::ObjectLifetimeDefault
::BaseDefault
=>
249 self.base_scope
.base_object_lifetime_default_differs(),
253 fn anon_regions(&self,
256 -> Result
<Vec
<ty
::Region
>, Option
<Vec
<(String
, usize)>>>
258 self.base_scope
.anon_regions(span
, count
)
262 /// A scope which simply shifts the Debruijn index of other scopes
263 /// to account for binding levels.
264 pub struct ShiftedRscope
<'r
> {
265 base_scope
: &'
r (RegionScope
+'r
)
268 impl<'r
> ShiftedRscope
<'r
> {
269 pub fn new(base_scope
: &'
r (RegionScope
+'r
)) -> ShiftedRscope
<'r
> {
270 ShiftedRscope { base_scope: base_scope }
274 impl<'r
> RegionScope
for ShiftedRscope
<'r
> {
275 fn object_lifetime_default(&self, span
: Span
) -> Option
<ty
::Region
> {
276 self.base_scope
.object_lifetime_default(span
)
277 .map(|r
| ty_fold
::shift_region(r
, 1))
280 fn base_object_lifetime_default(&self, span
: Span
) -> ty
::Region
{
281 ty_fold
::shift_region(self.base_scope
.base_object_lifetime_default(span
), 1)
284 fn anon_regions(&self,
287 -> Result
<Vec
<ty
::Region
>, Option
<Vec
<(String
, usize)>>>
289 match self.base_scope
.anon_regions(span
, count
) {
292 *r
= ty_fold
::shift_region(*r
, 1);