1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.


use middle::ty;

use std::cell::Cell;
use syntax::ast;
use syntax::codemap::Span;

/// Defines strategies for handling regions that are omitted.  For
/// example, if one writes the type `&Foo`, then the lifetime of
/// this reference has been omitted. When converting this
/// type, the generic functions in astconv will invoke `anon_regions`
/// on the provided region-scope to decide how to translate this
/// omitted region.
///
/// It is not always legal to omit regions, therefore `anon_regions`
/// can return `Err(())` to indicate that this is not a scope in which
/// regions can legally be omitted.
pub trait RegionScope {
    fn anon_regions(&self,
                    span: Span,
                    count: uint)
                    -> Result<Vec<ty::Region> , ()>;
}

// A scope in which all regions must be explicitly named
pub struct ExplicitRscope;

impl RegionScope for ExplicitRscope {
    fn anon_regions(&self,
                    _span: Span,
                    _count: uint)
                    -> Result<Vec<ty::Region> , ()> {
        Err(())
    }
}

/// A scope in which we generate anonymous, late-bound regions for
/// omitted regions. This occurs in function signatures.
pub struct BindingRscope {
    binder_id: ast::NodeId,
    anon_bindings: Cell<uint>,
}

impl BindingRscope {
    pub fn new(binder_id: ast::NodeId) -> BindingRscope {
        BindingRscope {
            binder_id: binder_id,
            anon_bindings: Cell::new(0),
        }
    }
}

impl RegionScope for BindingRscope {
    fn anon_regions(&self,
                    _: Span,
                    count: uint)
                    -> Result<Vec<ty::Region> , ()> {
        let idx = self.anon_bindings.get();
        self.anon_bindings.set(idx + count);
        Ok(Vec::from_fn(count, |i| ty::ReLateBound(self.binder_id,
                                                   ty::BrAnon(idx + i))))
    }
}