Skip to content

Commit 27b3e01

Browse files
committed
auto merge of #4914 : nikomatsakis/rust/issue-4856, r=nikomatsakis
and then adjust code to match. rs=unsound (will review post-landing) rs=unsound
2 parents 1a394e5 + ab25349 commit 27b3e01

25 files changed

+1043
-572
lines changed

src/libcore/hashmap.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,9 @@ pub mod linear {
383383
},
384384
};
385385
386-
self.value_for_bucket(idx)
386+
unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker
387+
::cast::transmute_region(self.value_for_bucket(idx))
388+
}
387389
}
388390
389391
/// Return the value corresponding to the key in the map, or create,
@@ -412,7 +414,9 @@ pub mod linear {
412414
},
413415
};
414416
415-
self.value_for_bucket(idx)
417+
unsafe { // FIXME(#4903)---requires flow-sensitive borrow checker
418+
::cast::transmute_region(self.value_for_bucket(idx))
419+
}
416420
}
417421
418422
fn consume(&mut self, f: fn(K, V)) {

src/libcore/private.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -256,15 +256,15 @@ pub unsafe fn shared_mutable_state<T: Owned>(data: T) ->
256256
}
257257
258258
#[inline(always)]
259-
pub unsafe fn get_shared_mutable_state<T: Owned>(rc: &a/SharedMutableState<T>)
260-
-> &a/mut T {
259+
pub unsafe fn get_shared_mutable_state<T: Owned>(
260+
rc: *SharedMutableState<T>) -> *mut T
261+
{
261262
unsafe {
262263
let ptr: ~ArcData<T> = cast::reinterpret_cast(&(*rc).data);
263264
assert ptr.count > 0;
264-
// Cast us back into the correct region
265-
let r = cast::transmute_region(option::get_ref(&ptr.data));
265+
let r = cast::transmute(option::get_ref(&ptr.data));
266266
cast::forget(move ptr);
267-
return cast::transmute_mut(r);
267+
return r;
268268
}
269269
}
270270
#[inline(always)]
@@ -376,15 +376,17 @@ impl<T: Owned> Exclusive<T> {
376376
// the exclusive. Supporting that is a work in progress.
377377
#[inline(always)]
378378
unsafe fn with<U>(f: fn(x: &mut T) -> U) -> U {
379-
let rec = unsafe { get_shared_mutable_state(&self.x) };
380-
do rec.lock.lock {
381-
if rec.failed {
382-
die!(~"Poisoned exclusive - another task failed inside!");
379+
unsafe {
380+
let rec = get_shared_mutable_state(&self.x);
381+
do (*rec).lock.lock {
382+
if (*rec).failed {
383+
die!(~"Poisoned exclusive - another task failed inside!");
384+
}
385+
(*rec).failed = true;
386+
let result = f(&mut (*rec).data);
387+
(*rec).failed = false;
388+
move result
383389
}
384-
rec.failed = true;
385-
let result = f(&mut rec.data);
386-
rec.failed = false;
387-
move result
388390
}
389391
}
390392

src/libcore/str.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2071,17 +2071,19 @@ pub mod raw {
20712071

20722072
/// Appends a byte to a string. (Not UTF-8 safe).
20732073
pub unsafe fn push_byte(s: &mut ~str, b: u8) {
2074-
reserve_at_least(&mut *s, s.len() + 1);
2074+
let new_len = s.len() + 1;
2075+
reserve_at_least(&mut *s, new_len);
20752076
do as_buf(*s) |buf, len| {
20762077
let buf: *mut u8 = ::cast::reinterpret_cast(&buf);
20772078
*ptr::mut_offset(buf, len) = b;
20782079
}
2079-
set_len(&mut *s, s.len() + 1);
2080+
set_len(&mut *s, new_len);
20802081
}
20812082

20822083
/// Appends a vector of bytes to a string. (Not UTF-8 safe).
20832084
unsafe fn push_bytes(s: &mut ~str, bytes: &[u8]) {
2084-
reserve_at_least(&mut *s, s.len() + bytes.len());
2085+
let new_len = s.len() + bytes.len();
2086+
reserve_at_least(&mut *s, new_len);
20852087
for vec::each(bytes) |byte| { push_byte(&mut *s, *byte); }
20862088
}
20872089

src/libcore/vec.rs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -623,13 +623,15 @@ unsafe fn push_fast<T>(v: &mut ~[T], initval: T) {
623623

624624
#[inline(never)]
625625
fn push_slow<T>(v: &mut ~[T], initval: T) {
626-
reserve_at_least(&mut *v, v.len() + 1u);
626+
let new_len = v.len() + 1;
627+
reserve_at_least(&mut *v, new_len);
627628
unsafe { push_fast(v, initval) }
628629
}
629630

630631
#[inline(always)]
631632
pub fn push_all<T: Copy>(v: &mut ~[T], rhs: &[const T]) {
632-
reserve(&mut *v, v.len() + rhs.len());
633+
let new_len = v.len() + rhs.len();
634+
reserve(&mut *v, new_len);
633635

634636
for uint::range(0u, rhs.len()) |i| {
635637
push(&mut *v, unsafe { raw::get(rhs, i) })
@@ -638,7 +640,8 @@ pub fn push_all<T: Copy>(v: &mut ~[T], rhs: &[const T]) {
638640

639641
#[inline(always)]
640642
pub fn push_all_move<T>(v: &mut ~[T], mut rhs: ~[T]) {
641-
reserve(&mut *v, v.len() + rhs.len());
643+
let new_len = v.len() + rhs.len();
644+
reserve(&mut *v, new_len);
642645
unsafe {
643646
do as_mut_buf(rhs) |p, len| {
644647
for uint::range(0, len) |i| {
@@ -663,9 +666,9 @@ pub fn truncate<T>(v: &mut ~[T], newlen: uint) {
663666
let mut dropped = rusti::init();
664667
dropped <-> *ptr::mut_offset(p, i);
665668
}
666-
raw::set_len(&mut *v, newlen);
667669
}
668670
}
671+
unsafe { raw::set_len(&mut *v, newlen); }
669672
}
670673

671674
/**
@@ -740,7 +743,8 @@ pub pure fn append_mut<T: Copy>(lhs: ~[mut T], rhs: &[const T]) -> ~[mut T] {
740743
* * initval - The value for the new elements
741744
*/
742745
pub fn grow<T: Copy>(v: &mut ~[T], n: uint, initval: &T) {
743-
reserve_at_least(&mut *v, v.len() + n);
746+
let new_len = v.len() + n;
747+
reserve_at_least(&mut *v, new_len);
744748
let mut i: uint = 0u;
745749

746750
while i < n {
@@ -763,7 +767,8 @@ pub fn grow<T: Copy>(v: &mut ~[T], n: uint, initval: &T) {
763767
* value
764768
*/
765769
pub fn grow_fn<T>(v: &mut ~[T], n: uint, op: iter::InitOp<T>) {
766-
reserve_at_least(&mut *v, v.len() + n);
770+
let new_len = v.len() + n;
771+
reserve_at_least(&mut *v, new_len);
767772
let mut i: uint = 0u;
768773
while i < n {
769774
v.push(op(i));

src/librustc/middle/borrowck/check_loans.rs

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -305,22 +305,31 @@ impl CheckLoanCtxt {
305305
return;
306306
}
307307

308-
match (old_loan.mutbl, new_loan.mutbl) {
309-
(m_const, _) | (_, m_const) | (m_imm, m_imm) => {
310-
/*ok*/
308+
match (old_loan.kind, new_loan.kind) {
309+
(PartialFreeze, PartialTake) | (PartialTake, PartialFreeze) |
310+
(TotalFreeze, PartialFreeze) | (PartialFreeze, TotalFreeze) |
311+
(Immobile, _) | (_, Immobile) |
312+
(PartialFreeze, PartialFreeze) |
313+
(PartialTake, PartialTake) |
314+
(TotalFreeze, TotalFreeze) => {
315+
/* ok */
311316
}
312317

313-
(m_mutbl, m_mutbl) | (m_mutbl, m_imm) | (m_imm, m_mutbl) => {
318+
(PartialTake, TotalFreeze) | (TotalFreeze, PartialTake) |
319+
(TotalTake, TotalFreeze) | (TotalFreeze, TotalTake) |
320+
(TotalTake, PartialFreeze) | (PartialFreeze, TotalTake) |
321+
(TotalTake, PartialTake) | (PartialTake, TotalTake) |
322+
(TotalTake, TotalTake) => {
314323
self.bccx.span_err(
315324
new_loan.cmt.span,
316325
fmt!("loan of %s as %s \
317326
conflicts with prior loan",
318327
self.bccx.cmt_to_str(new_loan.cmt),
319-
self.bccx.mut_to_str(new_loan.mutbl)));
328+
self.bccx.loan_kind_to_str(new_loan.kind)));
320329
self.bccx.span_note(
321330
old_loan.cmt.span,
322331
fmt!("prior loan as %s granted here",
323-
self.bccx.mut_to_str(old_loan.mutbl)));
332+
self.bccx.loan_kind_to_str(old_loan.kind)));
324333
}
325334
}
326335
}
@@ -348,13 +357,13 @@ impl CheckLoanCtxt {
348357
// are only assigned once
349358
} else {
350359
match cmt.mutbl {
351-
m_mutbl => { /*ok*/ }
352-
m_const | m_imm => {
353-
self.bccx.span_err(
354-
ex.span,
355-
at.ing_form(self.bccx.cmt_to_str(cmt)));
356-
return;
357-
}
360+
McDeclared | McInherited => { /*ok*/ }
361+
McReadOnly | McImmutable => {
362+
self.bccx.span_err(
363+
ex.span,
364+
at.ing_form(self.bccx.cmt_to_str(cmt)));
365+
return;
366+
}
358367
}
359368
}
360369

@@ -428,19 +437,20 @@ impl CheckLoanCtxt {
428437
cmt: cmt,
429438
lp: @loan_path) {
430439
for self.walk_loans_of(ex.id, lp) |loan| {
431-
match loan.mutbl {
432-
m_const => { /*ok*/ }
433-
m_mutbl | m_imm => {
434-
self.bccx.span_err(
435-
ex.span,
436-
fmt!("%s prohibited due to outstanding loan",
437-
at.ing_form(self.bccx.cmt_to_str(cmt))));
438-
self.bccx.span_note(
439-
loan.cmt.span,
440-
fmt!("loan of %s granted here",
441-
self.bccx.cmt_to_str(loan.cmt)));
442-
return;
443-
}
440+
match loan.kind {
441+
Immobile => { /* ok */ }
442+
TotalFreeze | PartialFreeze |
443+
TotalTake | PartialTake => {
444+
self.bccx.span_err(
445+
ex.span,
446+
fmt!("%s prohibited due to outstanding loan",
447+
at.ing_form(self.bccx.cmt_to_str(cmt))));
448+
self.bccx.span_note(
449+
loan.cmt.span,
450+
fmt!("loan of %s granted here",
451+
self.bccx.cmt_to_str(loan.cmt)));
452+
return;
453+
}
444454
}
445455
}
446456

src/librustc/middle/borrowck/gather_loans.rs

Lines changed: 43 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ use core::prelude::*;
2020

2121
use middle::borrowck::preserve::{PreserveCondition, PcOk, PcIfPure};
2222
use middle::borrowck::{Loan, bckerr, bckres, BorrowckCtxt, err_mutbl};
23+
use middle::borrowck::{LoanKind, TotalFreeze, PartialFreeze,
24+
TotalTake, PartialTake, Immobile};
2325
use middle::borrowck::{req_maps};
26+
use middle::borrowck::loan;
2427
use middle::mem_categorization::{cat_binding, cat_discr, cmt, comp_variant};
2528
use middle::mem_categorization::{mem_categorization_ctxt};
2629
use middle::mem_categorization::{opt_deref_kind};
@@ -340,13 +343,22 @@ impl GatherLoanCtxt {
340343
fn guarantee_valid(@mut self,
341344
cmt: cmt,
342345
req_mutbl: ast::mutability,
343-
scope_r: ty::Region) {
346+
scope_r: ty::Region)
347+
{
348+
349+
let loan_kind = match req_mutbl {
350+
m_mutbl => TotalTake,
351+
m_imm => TotalFreeze,
352+
m_const => Immobile
353+
};
344354

345355
self.bccx.stats.guaranteed_paths += 1;
346356

347-
debug!("guarantee_valid(cmt=%s, req_mutbl=%s, scope_r=%s)",
357+
debug!("guarantee_valid(cmt=%s, req_mutbl=%?, \
358+
loan_kind=%?, scope_r=%s)",
348359
self.bccx.cmt_to_repr(cmt),
349-
self.bccx.mut_to_str(req_mutbl),
360+
req_mutbl,
361+
loan_kind,
350362
region_to_str(self.tcx(), scope_r));
351363
let _i = indenter();
352364

@@ -362,10 +374,10 @@ impl GatherLoanCtxt {
362374
// it within that scope, the loan will be detected and an
363375
// error will be reported.
364376
Some(_) => {
365-
match self.bccx.loan(cmt, scope_r, req_mutbl) {
377+
match loan::loan(self.bccx, cmt, scope_r, loan_kind) {
366378
Err(ref e) => { self.bccx.report((*e)); }
367379
Ok(move loans) => {
368-
self.add_loans(cmt, req_mutbl, scope_r, move loans);
380+
self.add_loans(cmt, loan_kind, scope_r, move loans);
369381
}
370382
}
371383
}
@@ -378,7 +390,7 @@ impl GatherLoanCtxt {
378390
// pointer is desired, that is ok as long as we are pure)
379391
None => {
380392
let result: bckres<PreserveCondition> = {
381-
do self.check_mutbl(req_mutbl, cmt).chain |pc1| {
393+
do self.check_mutbl(loan_kind, cmt).chain |pc1| {
382394
do self.bccx.preserve(cmt, scope_r,
383395
self.item_ub,
384396
self.root_ub).chain |pc2| {
@@ -446,37 +458,41 @@ impl GatherLoanCtxt {
446458
// reqires an immutable pointer, but `f` lives in (aliased)
447459
// mutable memory.
448460
fn check_mutbl(@mut self,
449-
req_mutbl: ast::mutability,
461+
loan_kind: LoanKind,
450462
cmt: cmt)
451463
-> bckres<PreserveCondition> {
452-
debug!("check_mutbl(req_mutbl=%?, cmt.mutbl=%?)",
453-
req_mutbl, cmt.mutbl);
464+
debug!("check_mutbl(loan_kind=%?, cmt.mutbl=%?)",
465+
loan_kind, cmt.mutbl);
454466

455-
if req_mutbl == m_const || req_mutbl == cmt.mutbl {
456-
debug!("required is const or they are the same");
457-
Ok(PcOk)
458-
} else {
459-
let e = bckerr { cmt: cmt, code: err_mutbl(req_mutbl) };
460-
if req_mutbl == m_imm {
461-
// if this is an @mut box, then it's generally OK to borrow as
462-
// &imm; this will result in a write guard
463-
if cmt.cat.is_mutable_box() {
467+
match loan_kind {
468+
Immobile => Ok(PcOk),
469+
470+
TotalTake | PartialTake => {
471+
if cmt.mutbl.is_mutable() {
464472
Ok(PcOk)
465473
} else {
466-
// you can treat mutable things as imm if you are pure
467-
debug!("imm required, must be pure");
474+
Err(bckerr { cmt: cmt, code: err_mutbl(loan_kind) })
475+
}
476+
}
468477

478+
TotalFreeze | PartialFreeze => {
479+
if cmt.mutbl.is_immutable() {
480+
Ok(PcOk)
481+
} else if cmt.cat.is_mutable_box() {
482+
Ok(PcOk)
483+
} else {
484+
// Eventually:
485+
let e = bckerr {cmt: cmt,
486+
code: err_mutbl(loan_kind)};
469487
Ok(PcIfPure(e))
470488
}
471-
} else {
472-
Err(e)
473489
}
474490
}
475491
}
476492

477493
fn add_loans(@mut self,
478494
cmt: cmt,
479-
req_mutbl: ast::mutability,
495+
loan_kind: LoanKind,
480496
scope_r: ty::Region,
481497
+loans: ~[Loan]) {
482498
if loans.len() == 0 {
@@ -526,7 +542,7 @@ impl GatherLoanCtxt {
526542

527543
self.add_loans_to_scope_id(scope_id, move loans);
528544

529-
if req_mutbl == m_imm && cmt.mutbl != m_imm {
545+
if loan_kind.is_freeze() && !cmt.mutbl.is_immutable() {
530546
self.bccx.stats.loaned_paths_imm += 1;
531547

532548
if self.tcx().sess.borrowck_note_loan() {
@@ -542,7 +558,9 @@ impl GatherLoanCtxt {
542558
fn add_loans_to_scope_id(@mut self,
543559
scope_id: ast::node_id,
544560
+loans: ~[Loan]) {
545-
debug!("adding %u loans to scope_id %?", loans.len(), scope_id);
561+
debug!("adding %u loans to scope_id %?: %s",
562+
loans.len(), scope_id,
563+
str::connect(loans.map(|l| self.bccx.loan_to_repr(l)), ", "));
546564
match self.req_maps.req_loan_map.find(&scope_id) {
547565
Some(req_loans) => {
548566
req_loans.push_all(loans);

0 commit comments

Comments
 (0)