]> git.proxmox.com Git - rustc.git/blame - src/librustc_borrowck/borrowck/gather_loans/lifetime.rs
Imported Upstream version 1.3.0+dfsg1
[rustc.git] / src / librustc_borrowck / borrowck / gather_loans / lifetime.rs
CommitLineData
1a4d82fc
JJ
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//! This module implements the check that the lifetime of a borrow
12//! does not exceed the lifetime of the value being borrowed.
13
14use borrowck::*;
15use rustc::middle::expr_use_visitor as euv;
16use rustc::middle::mem_categorization as mc;
17use rustc::middle::region;
18use rustc::middle::ty;
62682a34 19
1a4d82fc
JJ
20use syntax::ast;
21use syntax::codemap::Span;
22
23type R = Result<(),()>;
24
25pub fn guarantee_lifetime<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
26 item_scope: region::CodeExtent,
27 span: Span,
28 cause: euv::LoanCause,
29 cmt: mc::cmt<'tcx>,
30 loan_region: ty::Region,
31 _: ty::BorrowKind)
32 -> Result<(),()> {
33 //! Reports error if `loan_region` is larger than S
34 //! where S is `item_scope` if `cmt` is an upvar,
35 //! and is scope of `cmt` otherwise.
62682a34
SL
36 debug!("guarantee_lifetime(cmt={:?}, loan_region={:?})",
37 cmt, loan_region);
1a4d82fc
JJ
38 let ctxt = GuaranteeLifetimeContext {bccx: bccx,
39 item_scope: item_scope,
40 span: span,
41 cause: cause,
42 loan_region: loan_region,
43 cmt_original: cmt.clone()};
44 ctxt.check(&cmt, None)
45}
46
47///////////////////////////////////////////////////////////////////////////
48// Private
49
50struct GuaranteeLifetimeContext<'a, 'tcx: 'a> {
51 bccx: &'a BorrowckCtxt<'a, 'tcx>,
52
53 // the scope of the function body for the enclosing item
54 item_scope: region::CodeExtent,
55
56 span: Span,
57 cause: euv::LoanCause,
58 loan_region: ty::Region,
59 cmt_original: mc::cmt<'tcx>
60}
61
62impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> {
63
64 fn check(&self, cmt: &mc::cmt<'tcx>, discr_scope: Option<ast::NodeId>) -> R {
65 //! Main routine. Walks down `cmt` until we find the
66 //! "guarantor". Reports an error if `self.loan_region` is
67 //! larger than scope of `cmt`.
62682a34
SL
68 debug!("guarantee_lifetime.check(cmt={:?}, loan_region={:?})",
69 cmt,
70 self.loan_region);
1a4d82fc
JJ
71
72 match cmt.cat {
73 mc::cat_rvalue(..) |
74 mc::cat_local(..) | // L-Local
75 mc::cat_upvar(..) |
76 mc::cat_deref(_, _, mc::BorrowedPtr(..)) | // L-Deref-Borrowed
77 mc::cat_deref(_, _, mc::Implicit(..)) |
78 mc::cat_deref(_, _, mc::UnsafePtr(..)) => {
79 self.check_scope(self.scope(cmt))
80 }
81
82 mc::cat_static_item => {
83 Ok(())
84 }
85
86 mc::cat_downcast(ref base, _) |
87 mc::cat_deref(ref base, _, mc::Unique) | // L-Deref-Send
88 mc::cat_interior(ref base, _) => { // L-Field
89 self.check(base, discr_scope)
90 }
91 }
92 }
93
94 fn check_scope(&self, max_scope: ty::Region) -> R {
95 //! Reports an error if `loan_region` is larger than `max_scope`
96
97 if !self.bccx.is_subregion_of(self.loan_region, max_scope) {
98 Err(self.report_error(err_out_of_scope(max_scope, self.loan_region)))
99 } else {
100 Ok(())
101 }
102 }
103
104 fn scope(&self, cmt: &mc::cmt) -> ty::Region {
105 //! Returns the maximal region scope for the which the
106 //! lvalue `cmt` is guaranteed to be valid without any
107 //! rooting etc, and presuming `cmt` is not mutated.
108
1a4d82fc
JJ
109 match cmt.cat {
110 mc::cat_rvalue(temp_scope) => {
111 temp_scope
112 }
113 mc::cat_upvar(..) => {
114 ty::ReScope(self.item_scope)
115 }
116 mc::cat_static_item => {
117 ty::ReStatic
118 }
119 mc::cat_local(local_id) => {
120 ty::ReScope(self.bccx.tcx.region_maps.var_scope(local_id))
121 }
122 mc::cat_deref(_, _, mc::UnsafePtr(..)) => {
123 ty::ReStatic
124 }
125 mc::cat_deref(_, _, mc::BorrowedPtr(_, r)) |
126 mc::cat_deref(_, _, mc::Implicit(_, r)) => {
127 r
128 }
129 mc::cat_downcast(ref cmt, _) |
130 mc::cat_deref(ref cmt, _, mc::Unique) |
131 mc::cat_interior(ref cmt, _) => {
132 self.scope(cmt)
133 }
134 }
135 }
136
137 fn report_error(&self, code: bckerr_code) {
138 self.bccx.report(BckError { cmt: self.cmt_original.clone(),
139 span: self.span,
c1a9b12d 140 cause: BorrowViolation(self.cause),
1a4d82fc
JJ
141 code: code });
142 }
143}