diff --git a/src/rustc/middle/borrowck.rs b/src/rustc/middle/borrowck.rs index f0ff9ba49d2..595ad2d0917 100644 --- a/src/rustc/middle/borrowck.rs +++ b/src/rustc/middle/borrowck.rs @@ -72,10 +72,11 @@ type root_map_key = {id: ast::node_id, derefs: uint}; type mutbl_map = std::map::hashmap; enum bckerr_code { - err_mutbl(ast::mutability, ast::mutability), err_mut_uniq, err_mut_variant, - err_preserve_gc + err_preserve_gc, + err_mutbl(ast::mutability, + ast::mutability) } type bckerr = {cmt: cmt, code: bckerr_code}; @@ -136,32 +137,6 @@ enum loan_path { // a complete record of a loan that was granted type loan = {lp: @loan_path, cmt: cmt, mutbl: ast::mutability}; -fn sup_mutbl(req_m: ast::mutability, - act_m: ast::mutability) -> bool { - alt (req_m, act_m) { - (m_const, _) | - (m_imm, m_imm) | - (m_mutbl, m_mutbl) { - true - } - - (_, m_const) | - (m_imm, m_mutbl) | - (m_mutbl, m_imm) { - false - } - } -} - -fn check_sup_mutbl(req_m: ast::mutability, - cmt: cmt) -> bckres<()> { - if sup_mutbl(req_m, cmt.mutbl) { - ok(()) - } else { - err({cmt:cmt, code:err_mutbl(req_m, cmt.mutbl)}) - } -} - fn save_and_restore(&t: T, f: fn() -> U) -> U { let old_t = t; let u <- f(); @@ -278,12 +253,12 @@ impl methods for gather_loan_ctxt { // also entail "rooting" GC'd pointers, which means ensuring // dynamically that they are not freed. fn guarantee_valid(cmt: cmt, - mutbl: ast::mutability, + req_mutbl: ast::mutability, scope_r: ty::region) { - #debug["guarantee_valid(cmt=%s, mutbl=%s, scope_r=%s)", + #debug["guarantee_valid(cmt=%s, req_mutbl=%s, scope_r=%s)", self.bccx.cmt_to_repr(cmt), - self.bccx.mut_to_str(mutbl), + self.bccx.mut_to_str(req_mutbl), region_to_str(self.tcx(), scope_r)]; let _i = indenter(); @@ -300,10 +275,8 @@ impl methods for gather_loan_ctxt { some(_) { alt scope_r { ty::re_scope(scope_id) { - alt self.bccx.loan(cmt, mutbl) { - ok(loans) { self.add_loans(scope_id, loans); } - err(e) { self.bccx.report(e); } - } + let loans = self.bccx.loan(cmt, req_mutbl); + self.add_loans(scope_id, loans); } _ { self.bccx.span_err( @@ -321,7 +294,7 @@ impl methods for gather_loan_ctxt { // rooted in some immutable path) none { self.bccx.report_if_err( - check_sup_mutbl(mutbl, cmt).chain { |_ok| + self.check_mutbl(req_mutbl, cmt).chain { |_ok| let opt_scope_id = alt scope_r { ty::re_scope(scope_id) { some(scope_id) } _ { none } @@ -333,6 +306,32 @@ impl methods for gather_loan_ctxt { } } + // Check that the pat `cmt` is compatible with the required + // mutability, presuming that it can be preserved to stay alive + // long enough. + // + // For example, if you have an expression like `&x.f` where `x` + // has type `@mut{f:int}`, this check might fail because `&x.f` + // reqires an immutable pointer, but `f` lives in (aliased) + // mutable memory. + fn check_mutbl(req_mutbl: ast::mutability, + cmt: cmt) -> bckres<()> { + alt (req_mutbl, cmt.mutbl) { + (m_const, _) | + (m_imm, m_imm) | + (m_mutbl, m_mutbl) { + ok(()) + } + + (_, m_const) | + (m_imm, m_mutbl) | + (m_mutbl, m_imm) { + err({cmt: cmt, + code: err_mutbl(req_mutbl, cmt.mutbl)}) + } + } + } + fn add_loans(scope_id: ast::node_id, loans: @const [loan]) { alt self.req_maps.req_loan_map.find(scope_id) { some(l) { @@ -1404,7 +1403,7 @@ impl categorize_methods for borrowck_ctxt { fn bckerr_code_to_str(code: bckerr_code) -> str { alt code { err_mutbl(req, act) { - #fmt["mutability mismatch, required %s but found %s", + #fmt["creating %s alias to aliasable, %s memory", self.mut_to_str(req), self.mut_to_str(act)] } err_mut_uniq { @@ -1647,29 +1646,25 @@ type loan_ctxt = @{ }; impl loan_methods for borrowck_ctxt { - fn loan(cmt: cmt, - mutbl: ast::mutability) -> bckres<@const [loan]> { + fn loan(cmt: cmt, mutbl: ast::mutability) -> @const [loan] { let lc = @{bccx: self, loans: @mut []}; - alt lc.loan(cmt, mutbl) { - ok(()) { ok(lc.loans) } - err(e) { err(e) } - } + lc.loan(cmt, mutbl); + ret lc.loans; } } impl loan_methods for loan_ctxt { fn ok_with_loan_of(cmt: cmt, - mutbl: ast::mutability) -> bckres<()> { + mutbl: ast::mutability) { // Note: all cmt's that we deal with will have a non-none lp, because // the entry point into this routine, `borrowck_ctxt::loan()`, rejects // any cmt with a none-lp. *self.loans += [{lp:option::get(cmt.lp), cmt:cmt, mutbl:mutbl}]; - ok(()) } - fn loan(cmt: cmt, req_mutbl: ast::mutability) -> bckres<()> { + fn loan(cmt: cmt, req_mutbl: ast::mutability) { #debug["loan(%s, %s)", self.bccx.cmt_to_repr(cmt), @@ -1711,9 +1706,8 @@ impl loan_methods for loan_ctxt { m_const | m_mutbl { m_const } }; - self.loan(cmt_base, base_mutbl).chain { |_ok| - self.ok_with_loan_of(cmt, req_mutbl) - } + self.loan(cmt_base, base_mutbl); + self.ok_with_loan_of(cmt, req_mutbl) } cat_comp(cmt1, comp_variant) | cat_deref(cmt1, _, uniq_ptr) { @@ -1723,9 +1717,8 @@ impl loan_methods for loan_ctxt { // // Unique pointers: the base must be immutable, because if // it is overwritten, the unique content will be freed. - self.loan(cmt1, m_imm).chain { |_ok| - self.ok_with_loan_of(cmt, req_mutbl) - } + self.loan(cmt1, m_imm); + self.ok_with_loan_of(cmt, req_mutbl) } cat_deref(cmt1, _, unsafe_ptr) | cat_deref(cmt1, _, gc_ptr) |