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 syntax
::codemap
::Span
;
19 pub struct ElisionFailureInfo
{
21 pub lifetime_count
: usize,
22 pub have_bound_regions
: bool
25 pub type ElidedLifetime
= Result
<ty
::Region
, Option
<Vec
<ElisionFailureInfo
>>>;
27 /// Defines strategies for handling regions that are omitted. For
28 /// example, if one writes the type `&Foo`, then the lifetime of
29 /// this reference has been omitted. When converting this
30 /// type, the generic functions in astconv will invoke `anon_regions`
31 /// on the provided region-scope to decide how to translate this
34 /// It is not always legal to omit regions, therefore `anon_regions`
35 /// can return `Err(())` to indicate that this is not a scope in which
36 /// regions can legally be omitted.
37 pub trait RegionScope
{
38 fn anon_regions(&self,
41 -> Result
<Vec
<ty
::Region
>, Option
<Vec
<ElisionFailureInfo
>>>;
43 /// If an object omits any explicit lifetime bound, and none can
44 /// be derived from the object traits, what should we use? If
45 /// `None` is returned, an explicit annotation is required.
46 fn object_lifetime_default(&self, span
: Span
) -> Option
<ty
::Region
>;
48 /// The "base" default is the initial default for a scope. This is
49 /// 'static except for in fn bodies, where it is a fresh inference
50 /// variable. You shouldn't call this except for as part of
51 /// computing `object_lifetime_default` (in particular, in legacy
52 /// modes, it may not be relevant).
53 fn base_object_lifetime_default(&self, span
: Span
) -> ty
::Region
;
56 // A scope in which all regions must be explicitly named. This is used
57 // for types that appear in structs and so on.
58 #[derive(Copy, Clone)]
59 pub struct ExplicitRscope
;
61 impl RegionScope
for ExplicitRscope
{
62 fn anon_regions(&self,
65 -> Result
<Vec
<ty
::Region
>, Option
<Vec
<ElisionFailureInfo
>>> {
69 fn object_lifetime_default(&self, span
: Span
) -> Option
<ty
::Region
> {
70 Some(self.base_object_lifetime_default(span
))
73 fn base_object_lifetime_default(&self, _span
: Span
) -> ty
::Region
{
78 // Same as `ExplicitRscope`, but provides some extra information for diagnostics
79 pub struct UnelidableRscope(Option
<Vec
<ElisionFailureInfo
>>);
81 impl UnelidableRscope
{
82 pub fn new(v
: Option
<Vec
<ElisionFailureInfo
>>) -> UnelidableRscope
{
87 impl RegionScope
for UnelidableRscope
{
88 fn anon_regions(&self,
91 -> Result
<Vec
<ty
::Region
>, Option
<Vec
<ElisionFailureInfo
>>> {
92 let UnelidableRscope(ref v
) = *self;
96 fn object_lifetime_default(&self, span
: Span
) -> Option
<ty
::Region
> {
97 Some(self.base_object_lifetime_default(span
))
100 fn base_object_lifetime_default(&self, _span
: Span
) -> ty
::Region
{
105 // A scope in which omitted anonymous region defaults to
106 // `default`. This is used after the `->` in function signatures. The
107 // latter use may go away. Note that object-lifetime defaults work a
108 // bit differently, as specified in RFC #599.
109 pub struct ElidableRscope
{
113 impl ElidableRscope
{
114 pub fn new(r
: ty
::Region
) -> ElidableRscope
{
115 ElidableRscope { default: r }
119 impl RegionScope
for ElidableRscope
{
120 fn object_lifetime_default(&self, span
: Span
) -> Option
<ty
::Region
> {
121 // Per RFC #599, object-lifetimes default to 'static unless
122 // overridden by context, and this takes precedence over
124 Some(self.base_object_lifetime_default(span
))
127 fn base_object_lifetime_default(&self, _span
: Span
) -> ty
::Region
{
131 fn anon_regions(&self,
134 -> Result
<Vec
<ty
::Region
>, Option
<Vec
<ElisionFailureInfo
>>>
136 Ok(vec
![self.default; count
])
140 /// A scope in which we generate anonymous, late-bound regions for
141 /// omitted regions. This occurs in function signatures.
142 pub struct BindingRscope
{
143 anon_bindings
: Cell
<u32>,
147 pub fn new() -> BindingRscope
{
149 anon_bindings
: Cell
::new(0),
153 fn next_region(&self) -> ty
::Region
{
154 let idx
= self.anon_bindings
.get();
155 self.anon_bindings
.set(idx
+ 1);
156 ty
::ReLateBound(ty
::DebruijnIndex
::new(1), ty
::BrAnon(idx
))
160 impl RegionScope
for BindingRscope
{
161 fn object_lifetime_default(&self, span
: Span
) -> Option
<ty
::Region
> {
162 // Per RFC #599, object-lifetimes default to 'static unless
163 // overridden by context, and this takes precedence over the
164 // binding defaults in a fn signature.
165 Some(self.base_object_lifetime_default(span
))
168 fn base_object_lifetime_default(&self, _span
: Span
) -> ty
::Region
{
172 fn anon_regions(&self,
175 -> Result
<Vec
<ty
::Region
>, Option
<Vec
<ElisionFailureInfo
>>>
177 Ok((0..count
).map(|_
| self.next_region()).collect())
181 /// A scope which overrides the default object lifetime but has no other effect.
182 pub struct ObjectLifetimeDefaultRscope
<'r
> {
183 base_scope
: &'
r (RegionScope
+'r
),
184 default: ty
::ObjectLifetimeDefault
,
187 impl<'r
> ObjectLifetimeDefaultRscope
<'r
> {
188 pub fn new(base_scope
: &'
r (RegionScope
+'r
),
189 default: ty
::ObjectLifetimeDefault
)
190 -> ObjectLifetimeDefaultRscope
<'r
>
192 ObjectLifetimeDefaultRscope
{
193 base_scope
: base_scope
,
199 impl<'r
> RegionScope
for ObjectLifetimeDefaultRscope
<'r
> {
200 fn object_lifetime_default(&self, span
: Span
) -> Option
<ty
::Region
> {
202 ty
::ObjectLifetimeDefault
::Ambiguous
=>
205 ty
::ObjectLifetimeDefault
::BaseDefault
=>
206 // NB: This behavior changed in Rust 1.3.
207 Some(self.base_object_lifetime_default(span
)),
209 ty
::ObjectLifetimeDefault
::Specific(r
) =>
214 fn base_object_lifetime_default(&self, span
: Span
) -> ty
::Region
{
215 self.base_scope
.base_object_lifetime_default(span
)
218 fn anon_regions(&self,
221 -> Result
<Vec
<ty
::Region
>, Option
<Vec
<ElisionFailureInfo
>>>
223 self.base_scope
.anon_regions(span
, count
)
227 /// A scope which simply shifts the Debruijn index of other scopes
228 /// to account for binding levels.
229 pub struct ShiftedRscope
<'r
> {
230 base_scope
: &'
r (RegionScope
+'r
)
233 impl<'r
> ShiftedRscope
<'r
> {
234 pub fn new(base_scope
: &'
r (RegionScope
+'r
)) -> ShiftedRscope
<'r
> {
235 ShiftedRscope { base_scope: base_scope }
239 impl<'r
> RegionScope
for ShiftedRscope
<'r
> {
240 fn object_lifetime_default(&self, span
: Span
) -> Option
<ty
::Region
> {
241 self.base_scope
.object_lifetime_default(span
)
242 .map(|r
| ty_fold
::shift_region(r
, 1))
245 fn base_object_lifetime_default(&self, span
: Span
) -> ty
::Region
{
246 ty_fold
::shift_region(self.base_scope
.base_object_lifetime_default(span
), 1)
249 fn anon_regions(&self,
252 -> Result
<Vec
<ty
::Region
>, Option
<Vec
<ElisionFailureInfo
>>>
254 match self.base_scope
.anon_regions(span
, count
) {
257 *r
= ty_fold
::shift_region(*r
, 1);