Skip to content

Commit 419ac4a

Browse files
committed
Issue #3511 - Rationalize temporary lifetimes.
Major changes: - Define temporary scopes in a syntax-based way that basically defaults to the innermost statement or conditional block, except for in a `let` initializer, where we default to the innermost block. Rules are documented in the code, but not in the manual (yet). See new test run-pass/cleanup-value-scopes.rs for examples. - Refactors Datum to better define cleanup roles. - Refactor cleanup scopes to not be tied to basic blocks, permitting us to have a very large number of scopes (one per AST node). - Introduce nascent documentation in trans/doc.rs covering datums and cleanup in a more comprehensive way.
1 parent 149fc76 commit 419ac4a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+4797
-3662
lines changed

src/librustc/lib/llvm.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -1698,6 +1698,7 @@ pub mod llvm {
16981698

16991699
pub fn LLVMDICompositeTypeSetTypeArray(CompositeType: ValueRef, TypeArray: ValueRef);
17001700
pub fn LLVMTypeToString(Type: TypeRef) -> *c_char;
1701+
pub fn LLVMValueToString(value_ref: ValueRef) -> *c_char;
17011702

17021703
pub fn LLVMIsAArgument(value_ref: ValueRef) -> ValueRef;
17031704

@@ -1847,8 +1848,10 @@ impl TypeNames {
18471848

18481849
pub fn val_to_str(&self, val: ValueRef) -> ~str {
18491850
unsafe {
1850-
let ty = Type::from_ref(llvm::LLVMTypeOf(val));
1851-
self.type_to_str(ty)
1851+
let s = llvm::LLVMValueToString(val);
1852+
let ret = from_c_str(s);
1853+
free(s as *c_void);
1854+
ret
18521855
}
18531856
}
18541857
}

src/librustc/middle/astencode.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,14 @@
1212
use c = metadata::common;
1313
use cstore = metadata::cstore;
1414
use driver::session::Session;
15-
use e = metadata::encoder;
1615
use metadata::decoder;
16+
use e = metadata::encoder;
17+
use middle::freevars::freevar_entry;
18+
use middle::region;
1719
use metadata::tydecode;
1820
use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
1921
RegionParameter};
2022
use metadata::tyencode;
21-
use middle::freevars::freevar_entry;
2223
use middle::typeck::{method_origin, method_map_entry};
2324
use middle::{ty, typeck, moves};
2425
use middle;
@@ -146,6 +147,7 @@ pub fn decode_inlined_item(cdata: @cstore::crate_metadata,
146147
debug!("< Decoded inlined fn: {}::{}",
147148
ast_map::path_to_str(path, token::get_ident_interner()),
148149
tcx.sess.str_of(ident));
150+
region::resolve_inlined_item(tcx.sess, &tcx.region_maps, &ii);
149151
decode_side_tables(xcx, ast_doc);
150152
match ii {
151153
ast::IIItem(i) => {

src/librustc/middle/borrowck/gather_loans/lifetime.rs

+4-15
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
220220

221221
// If inside of a match arm, expand the rooting to the entire
222222
// match. See the detailed discussion in `check()` above.
223-
let mut root_scope = match discr_scope {
223+
let root_scope = match discr_scope {
224224
None => root_scope,
225225
Some(id) => {
226226
if self.bccx.is_subscope_of(root_scope, id) {
@@ -231,17 +231,6 @@ impl<'a> GuaranteeLifetimeContext<'a> {
231231
}
232232
};
233233

234-
// FIXME(#3511) grow to the nearest cleanup scope---this can
235-
// cause observable errors if freezing!
236-
if !self.bccx.tcx.region_maps.is_cleanup_scope(root_scope) {
237-
debug!("{:?} is not a cleanup scope, adjusting", root_scope);
238-
239-
let cleanup_scope =
240-
self.bccx.tcx.region_maps.cleanup_scope(root_scope);
241-
242-
root_scope = cleanup_scope;
243-
}
244-
245234
// Add a record of what is required
246235
let rm_key = root_map_key {id: cmt_deref.id, derefs: derefs};
247236
let root_info = RootInfo {scope: root_scope};
@@ -301,8 +290,8 @@ impl<'a> GuaranteeLifetimeContext<'a> {
301290
// See the SCOPE(LV) function in doc.rs
302291

303292
match cmt.cat {
304-
mc::cat_rvalue(cleanup_scope_id) => {
305-
ty::ReScope(cleanup_scope_id)
293+
mc::cat_rvalue(temp_scope) => {
294+
temp_scope
306295
}
307296
mc::cat_copied_upvar(_) => {
308297
ty::ReScope(self.item_scope_id)
@@ -313,7 +302,7 @@ impl<'a> GuaranteeLifetimeContext<'a> {
313302
mc::cat_local(local_id) |
314303
mc::cat_arg(local_id) |
315304
mc::cat_self(local_id) => {
316-
self.bccx.tcx.region_maps.encl_region(local_id)
305+
ty::ReScope(self.bccx.tcx.region_maps.var_scope(local_id))
317306
}
318307
mc::cat_deref(_, _, mc::unsafe_ptr(..)) => {
319308
ty::ReStatic

src/librustc/middle/borrowck/gather_loans/mod.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -662,8 +662,9 @@ impl<'a> GatherLoanCtxt<'a> {
662662
//! with immutable `&` pointers, because borrows of such pointers
663663
//! do not require restrictions and hence do not cause a loan.
664664
665-
let lexical_scope = self.bccx.tcx.region_maps.encl_scope(lp.node_id());
666-
if self.bccx.tcx.region_maps.is_subscope_of(lexical_scope, loan_scope) {
665+
let rm = &self.bccx.tcx.region_maps;
666+
let lexical_scope = rm.var_scope(lp.node_id());
667+
if rm.is_subscope_of(lexical_scope, loan_scope) {
667668
lexical_scope
668669
} else {
669670
assert!(self.bccx.tcx.region_maps.is_subscope_of(loan_scope, lexical_scope));
@@ -688,7 +689,7 @@ impl<'a> GatherLoanCtxt<'a> {
688689
let arg_cmt = mc_ctxt.cat_rvalue(
689690
arg.id,
690691
arg.pat.span,
691-
body.id, // Arguments live only as long as the fn body.
692+
ty::ReScope(body.id), // Args live only as long as the fn body.
692693
arg_ty);
693694

694695
self.gather_pat(arg_cmt, arg.pat, None);

src/librustc/middle/borrowck/move_data.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ impl MoveData {
471471
for path in paths.get().iter() {
472472
match *path.loan_path {
473473
LpVar(id) => {
474-
let kill_id = tcx.region_maps.encl_scope(id);
474+
let kill_id = tcx.region_maps.var_scope(id);
475475
let path = {
476476
let path_map = self.path_map.borrow();
477477
*path_map.get().get(&path.loan_path)
@@ -490,7 +490,7 @@ impl MoveData {
490490
var_assignments.get().iter().enumerate() {
491491
match *self.path_loan_path(assignment.path) {
492492
LpVar(id) => {
493-
let kill_id = tcx.region_maps.encl_scope(id);
493+
let kill_id = tcx.region_maps.var_scope(id);
494494
dfcx_assign.add_kill(kill_id, assignment_index);
495495
}
496496
LpExtend(..) => {

src/librustc/middle/mem_categorization.rs

+12-7
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ use syntax::parse::token;
6060

6161
#[deriving(Eq)]
6262
pub enum categorization {
63-
cat_rvalue(ast::NodeId), // temporary val, argument is its scope
63+
cat_rvalue(ty::Region), // temporary val, argument is its scope
6464
cat_static_item,
6565
cat_copied_upvar(CopiedUpvar), // upvar copied into @fn or ~fn env
6666
cat_stack_upvar(cmt), // by ref upvar from ||
@@ -585,21 +585,26 @@ impl mem_categorization_ctxt {
585585
pub fn cat_rvalue_node<N:ast_node>(&self,
586586
node: &N,
587587
expr_ty: ty::t) -> cmt {
588-
self.cat_rvalue(node.id(),
589-
node.span(),
590-
self.tcx.region_maps.cleanup_scope(node.id()),
591-
expr_ty)
588+
match self.tcx.region_maps.temporary_scope(node.id()) {
589+
Some(scope) => {
590+
self.cat_rvalue(node.id(), node.span(),
591+
ty::ReScope(scope), expr_ty)
592+
}
593+
None => {
594+
self.cat_rvalue(node.id(), node.span(), ty::ReStatic, expr_ty)
595+
}
596+
}
592597
}
593598

594599
pub fn cat_rvalue(&self,
595600
cmt_id: ast::NodeId,
596601
span: Span,
597-
cleanup_scope_id: ast::NodeId,
602+
temp_scope: ty::Region,
598603
expr_ty: ty::t) -> cmt {
599604
@cmt_ {
600605
id:cmt_id,
601606
span:span,
602-
cat:cat_rvalue(cleanup_scope_id),
607+
cat:cat_rvalue(temp_scope),
603608
mutbl:McDeclared,
604609
ty:expr_ty
605610
}

src/librustc/middle/pat_util.rs

+11
Original file line numberDiff line numberDiff line change
@@ -108,3 +108,14 @@ pub fn pat_contains_bindings(dm: resolve::DefMap, pat: &Pat) -> bool {
108108
});
109109
contains_bindings
110110
}
111+
112+
pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Path> {
113+
match pat.node {
114+
PatIdent(BindByValue(_), ref path, None) => {
115+
Some(path)
116+
}
117+
_ => {
118+
None
119+
}
120+
}
121+
}

0 commit comments

Comments
 (0)