Skip to content

Commit 3322595

Browse files
committed
Reason about nested free variables that appear in a function
signature. In a nutshell, the idea is to (1) report an error if, for a region pointer `'a T`, the lifetime `'a` is longer than any lifetimes that appear in `T` (in other words, if a borrowed pointer outlives any portion of its contents) and then (2) use this to assume that in a function like `fn(self: &'a &'b T)`, the relationship `'a <= 'b` holds. This is needed for rust-lang#5656. Fixes rust-lang#5728.
1 parent 5606fc0 commit 3322595

27 files changed

+1029
-349
lines changed

src/libcore/cmp.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,19 @@ totalord_impl!(i64)
116116
totalord_impl!(int)
117117
totalord_impl!(uint)
118118

119+
pub fn cmp2<A:TotalOrd,B:TotalOrd>(
120+
a1: &A, b1: &B,
121+
a2: &A, b2: &B) -> Ordering
122+
{
123+
//! Compares (a1, b1) against (a2, b2), where the a values are more significant.
124+
125+
match a1.cmp(a2) {
126+
Less => Less,
127+
Greater => Greater,
128+
Equal => b1.cmp(b2)
129+
}
130+
}
131+
119132
/**
120133
* Trait for values that can be compared for a sort-order.
121134
*
@@ -193,6 +206,14 @@ mod test {
193206
assert_eq!(12.cmp(-5), Greater);
194207
}
195208

209+
#[test]
210+
fn test_cmp2() {
211+
assert_eq!(cmp2(1, 2, 3, 4), Less);
212+
assert_eq!(cmp2(3, 2, 3, 4), Less);
213+
assert_eq!(cmp2(5, 2, 3, 4), Greater);
214+
assert_eq!(cmp2(5, 5, 5, 4), Greater);
215+
}
216+
196217
#[test]
197218
fn test_int_totaleq() {
198219
assert!(5.equals(&5));

src/libcore/str.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -301,7 +301,11 @@ pub fn slice_shift_char<'a>(s: &'a str) -> (char, &'a str) {
301301

302302
/// Prepend a char to a string
303303
pub fn unshift_char(s: &mut ~str, ch: char) {
304-
*s = from_char(ch) + *s;
304+
// This could be more efficient.
305+
let mut new_str = ~"";
306+
new_str.push_char(ch);
307+
new_str.push_str(*s);
308+
*s = new_str;
305309
}
306310

307311
/**

src/libcore/tuple.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,6 @@ impl<A:Ord> Ord for (A,) {
161161
fn gt(&self, other: &(A,)) -> bool { other.lt(&(*self)) }
162162
}
163163

164-
165164
#[cfg(notest)]
166165
impl<A:Eq,B:Eq> Eq for (A, B) {
167166
#[inline(always)]

src/librustc/metadata/tydecode.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,8 @@ fn parse_region(st: @mut PState) -> ty::Region {
239239
assert!(next(st) == '|');
240240
let br = parse_bound_region(st);
241241
assert!(next(st) == ']');
242-
ty::re_free(id, br)
242+
ty::re_free(ty::FreeRegion {scope_id: id,
243+
bound_region: br})
243244
}
244245
's' => {
245246
let id = parse_int(st);

src/librustc/metadata/tyencode.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,12 @@ fn enc_region(w: @io::Writer, cx: @ctxt, r: ty::Region) {
146146
w.write_char('b');
147147
enc_bound_region(w, cx, br);
148148
}
149-
ty::re_free(id, br) => {
149+
ty::re_free(ref fr) => {
150150
w.write_char('f');
151151
w.write_char('[');
152-
w.write_int(id);
152+
w.write_int(fr.scope_id);
153153
w.write_char('|');
154-
enc_bound_region(w, cx, br);
154+
enc_bound_region(w, cx, fr.bound_region);
155155
w.write_char(']');
156156
}
157157
ty::re_scope(nid) => {

src/librustc/middle/astencode.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,9 +475,12 @@ impl tr for ty::Region {
475475
fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::Region {
476476
match *self {
477477
ty::re_bound(br) => ty::re_bound(br.tr(xcx)),
478-
ty::re_free(id, br) => ty::re_free(xcx.tr_id(id), br.tr(xcx)),
479478
ty::re_scope(id) => ty::re_scope(xcx.tr_id(id)),
480479
ty::re_static | ty::re_infer(*) => *self,
480+
ty::re_free(ref fr) => {
481+
ty::re_free(ty::FreeRegion {scope_id: xcx.tr_id(fr.scope_id),
482+
bound_region: fr.bound_region.tr(xcx)})
483+
}
481484
}
482485
}
483486
}

src/librustc/middle/borrowck/check_loans.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,9 +128,9 @@ pub impl CheckLoanCtxt {
128128
Some(e) => return Some(pc_cmt(*e))
129129
}
130130
131-
match self.tcx().region_map.find(&scope_id) {
131+
match self.tcx().region_maps.opt_encl_scope(scope_id) {
132132
None => return default_purity,
133-
Some(&next_scope_id) => scope_id = next_scope_id
133+
Some(next_scope_id) => scope_id = next_scope_id
134134
}
135135
}
136136
}
@@ -146,9 +146,9 @@ pub impl CheckLoanCtxt {
146146
}
147147
}
148148
149-
match self.tcx().region_map.find(&scope_id) {
149+
match self.tcx().region_maps.opt_encl_scope(scope_id) {
150150
None => return,
151-
Some(&next_scope_id) => scope_id = next_scope_id,
151+
Some(next_scope_id) => scope_id = next_scope_id,
152152
}
153153
}
154154
}
@@ -270,7 +270,7 @@ pub impl CheckLoanCtxt {
270270

271271
debug!("new_loans has length %?", new_loans.len());
272272

273-
let par_scope_id = *self.tcx().region_map.get(&scope_id);
273+
let par_scope_id = self.tcx().region_maps.encl_scope(scope_id);
274274
for self.walk_loans(par_scope_id) |old_loan| {
275275
debug!("old_loan=%?", self.bccx.loan_to_repr(old_loan));
276276

src/librustc/middle/borrowck/gather_loans.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,7 @@ fn req_loans_in_expr(ex: @ast::expr,
242242
// (if used like `a.b(...)`), the call where it's an argument
243243
// (if used like `x(a.b)`), or the block (if used like `let x
244244
// = a.b`).
245-
let scope_r = ty::re_scope(*self.tcx().region_map.get(&ex.id));
245+
let scope_r = self.tcx().region_maps.encl_region(ex.id);
246246
let rcvr_cmt = self.bccx.cat_expr(rcvr);
247247
self.guarantee_valid(rcvr_cmt, m_imm, scope_r);
248248
visit::visit_expr(ex, self, vt);
@@ -524,7 +524,10 @@ pub impl GatherLoanCtxt {
524524
// immutable structures, this is just the converse I suppose)
525525

526526
let scope_id = match scope_r {
527-
ty::re_scope(scope_id) | ty::re_free(scope_id, _) => scope_id,
527+
ty::re_scope(scope_id) |
528+
ty::re_free(ty::FreeRegion {scope_id, _}) => {
529+
scope_id
530+
}
528531
_ => {
529532
self.bccx.tcx.sess.span_bug(
530533
cmt.span,

src/librustc/middle/borrowck/loan.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,8 +130,8 @@ pub impl LoanContext {
130130
}
131131
cat_local(local_id) | cat_arg(local_id) | cat_self(local_id) => {
132132
// FIXME(#4903)
133-
let local_scope_id = *self.bccx.tcx.region_map.get(&local_id);
134-
self.issue_loan(cmt, ty::re_scope(local_scope_id), loan_kind,
133+
let local_region = self.bccx.tcx.region_maps.encl_region(local_id);
134+
self.issue_loan(cmt, local_region, loan_kind,
135135
owns_lent_data)
136136
}
137137
cat_stack_upvar(cmt) => {

src/librustc/middle/borrowck/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,6 @@ Borrowck results in two maps.
227227
use core::prelude::*;
228228

229229
use middle::mem_categorization::*;
230-
use middle::region;
231230
use middle::ty;
232231
use middle::typeck;
233232
use middle::moves;
@@ -458,7 +457,7 @@ pub fn root_map() -> root_map {
458457

459458
pub impl BorrowckCtxt {
460459
fn is_subregion_of(&self, r_sub: ty::Region, r_sup: ty::Region) -> bool {
461-
region::is_subregion_of(self.tcx.region_map, r_sub, r_sup)
460+
self.tcx.region_maps.is_subregion_of(r_sub, r_sup)
462461
}
463462

464463
fn cat_expr(&self, expr: @ast::expr) -> cmt {

0 commit comments

Comments
 (0)