diff --git a/src/rustc/middle/typeck/check/alt.rs b/src/rustc/middle/typeck/check/alt.rs index 4fb348e598c..cb25cb5382f 100644 --- a/src/rustc/middle/typeck/check/alt.rs +++ b/src/rustc/middle/typeck/check/alt.rs @@ -166,7 +166,9 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) { // ref x | ref const x | ref mut x // then the type of x is &M T where M is the mutability // and T is the expected type - let region_var = fcx.infcx.next_region_var_nb(); + let region_var = + fcx.infcx.next_region_var({lb: some(pcx.block_region), + ub: none}); let mt = {ty: expected, mutbl: mutbl}; let region_ty = ty::mk_rptr(tcx, region_var, mt); demand::eqtype(fcx, pat.span, region_ty, typ); diff --git a/src/rustc/middle/typeck/check/regionck.rs b/src/rustc/middle/typeck/check/regionck.rs index 03a27e88c97..e623c3ec0b9 100644 --- a/src/rustc/middle/typeck/check/regionck.rs +++ b/src/rustc/middle/typeck/check/regionck.rs @@ -22,6 +22,7 @@ import syntax::print::pprust; import infer::{resolve_type, resolve_all, force_all, resolve_rvar, force_rvar, fres}; import middle::kind::check_owned; +import middle::pat_util::pat_bindings; enum rcx { rcx_({fcx: @fn_ctxt, mut errors_reported: uint}) } type rvt = visit::vt<@rcx>; @@ -80,7 +81,6 @@ fn regionck_visitor() -> rvt { visit_stmt: visit_stmt, visit_expr: visit_expr, visit_block: visit_block, - visit_pat: visit_pat, visit_local: visit_local with *visit::default_visitor()}) } @@ -90,8 +90,26 @@ fn visit_item(_item: @ast::item, &&_rcx: @rcx, _v: rvt) { } fn visit_local(l: @ast::local, &&rcx: @rcx, v: rvt) { + // Check to make sure that the regions in all local variables are + // within scope. + // + // Note: we do this here rather than in visit_pat because we do + // not wish to constrain the regions in *patterns* in quite the + // same way. `visit_node()` guarantees that the region encloses + // the node in question, which ultimately constraints the regions + // in patterns to enclose the match expression as a whole. But we + // want them to enclose the *arm*. However, regions in patterns + // must either derive from the discriminant or a ref pattern: in + // the case of the discriminant, the regions will be constrained + // when the type of the discriminant is checked. In the case of a + // ref pattern, the variable is created with a suitable lower + // bound. let e = rcx.errors_reported; v.visit_pat(l.node.pat, rcx, v); + let def_map = rcx.fcx.ccx.tcx.def_map; + do pat_bindings(def_map, l.node.pat) |_bm, id, sp, _path| { + visit_node(id, sp, rcx); + } if e != rcx.errors_reported { return; // if decl has errors, skip initializer expr } @@ -102,20 +120,6 @@ fn visit_local(l: @ast::local, &&rcx: @rcx, v: rvt) { } } -fn visit_pat(p: @ast::pat, &&rcx: @rcx, v: rvt) { - let fcx = rcx.fcx; - match p.node { - ast::pat_ident(_, path, _) - if !pat_util::pat_is_variant(fcx.ccx.tcx.def_map, p) => { - debug!{"visit_pat binding=%s", *path.idents[0]}; - visit_node(p.id, p.span, rcx); - } - _ => () - } - - visit::visit_pat(p, rcx, v); -} - fn visit_block(b: ast::blk, &&rcx: @rcx, v: rvt) { visit::visit_block(b, rcx, v); } diff --git a/src/test/compile-fail/borrowck-binding-mutbl.rs b/src/test/compile-fail/borrowck-binding-mutbl.rs index 57c0375f4e4..c8ed3f143df 100644 --- a/src/test/compile-fail/borrowck-binding-mutbl.rs +++ b/src/test/compile-fail/borrowck-binding-mutbl.rs @@ -1,13 +1,13 @@ -fn impure(_v: ~[int]) { +fn impure(_v: &[int]) { } fn main() { let x = {mut f: ~[3]}; match x { - {f: v} => { - impure(v); //~ ERROR illegal borrow unless pure: unique value in aliasable, mutable location + {f: ref mut v} => { + impure(*v); //~ ERROR illegal borrow unless pure //~^ NOTE impure due to access to impure function } } -} \ No newline at end of file +} diff --git a/src/test/compile-fail/borrowck-issue-2657-1.rs b/src/test/compile-fail/borrowck-issue-2657-1.rs index f8cbb52d996..9bfc4cc1d0d 100644 --- a/src/test/compile-fail/borrowck-issue-2657-1.rs +++ b/src/test/compile-fail/borrowck-issue-2657-1.rs @@ -1,7 +1,7 @@ fn main() { let x = some(~1); match x { //~ NOTE loan of immutable local variable granted here - some(y) => { + some(ref y) => { let _a <- x; //~ ERROR moving out of immutable local variable prohibited due to outstanding loan } _ => {} diff --git a/src/test/compile-fail/borrowck-issue-2657-2.rs b/src/test/compile-fail/borrowck-issue-2657-2.rs index ab6e63174aa..1444889bc75 100644 --- a/src/test/compile-fail/borrowck-issue-2657-2.rs +++ b/src/test/compile-fail/borrowck-issue-2657-2.rs @@ -1,8 +1,8 @@ fn main() { let x = some(~1); match x { - some(y) => { - let _b <- y; //~ ERROR moving out of pattern binding + some(ref y) => { + let _b <- *y; //~ ERROR moving out of dereference of immutable & pointer } _ => {} } diff --git a/src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs b/src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs index ef696048219..8655ea0ab70 100644 --- a/src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs +++ b/src/test/compile-fail/borrowck-no-cycle-in-exchange-heap.rs @@ -6,8 +6,8 @@ fn main() { let x = ~node({mut a: ~empty}); // Create a cycle! match check *x { //~ NOTE loan of immutable local variable granted here - node(y) => { + node(ref y) => { y.a <- x; //~ ERROR moving out of immutable local variable prohibited due to outstanding loan } }; -} \ No newline at end of file +} diff --git a/src/test/compile-fail/borrowck-pat-enum-in-box.rs b/src/test/compile-fail/borrowck-pat-enum-in-box.rs index cd4893f87f2..84a78580141 100644 --- a/src/test/compile-fail/borrowck-pat-enum-in-box.rs +++ b/src/test/compile-fail/borrowck-pat-enum-in-box.rs @@ -1,13 +1,13 @@ fn match_imm_box(v: &const @option) -> int { match *v { - @some(i) => {i} + @some(ref i) => {*i} @none => {0} } } fn match_const_box(v: &const @const option) -> int { match *v { - @some(i) => { i } // ok because this is pure + @some(ref i) => { *i } // ok because this is pure @none => {0} } } @@ -16,8 +16,8 @@ pure fn pure_process(_i: int) {} fn match_const_box_and_do_pure_things(v: &const @const option) { match *v { - @some(i) => { - pure_process(i) + @some(ref i) => { + pure_process(*i) } @none => {} } @@ -27,8 +27,8 @@ fn process(_i: int) {} fn match_const_box_and_do_bad_things(v: &const @const option) { match *v { - @some(i) => { //~ ERROR illegal borrow unless pure: enum variant in aliasable, mutable location - process(i) //~ NOTE impure due to access to impure function + @some(ref i) => { //~ ERROR illegal borrow unless pure + process(*i) //~ NOTE impure due to access to impure function } @none => {} } diff --git a/src/test/compile-fail/borrowck-pat-enum.rs b/src/test/compile-fail/borrowck-pat-enum.rs index b29321ed818..bc30a2f13db 100644 --- a/src/test/compile-fail/borrowck-pat-enum.rs +++ b/src/test/compile-fail/borrowck-pat-enum.rs @@ -1,7 +1,7 @@ fn match_ref(&&v: option) -> int { match v { - some(i) => { - i + some(ref i) => { + *i } none => {0} } @@ -16,7 +16,7 @@ fn match_ref_unused(&&v: option) { fn match_const_reg(v: &const option) -> int { match *v { - some(i) => {i} // OK because this is pure + some(ref i) => {*i} // OK because this is pure none => {0} } } @@ -33,7 +33,7 @@ fn match_const_reg_unused(v: &const option) { fn match_const_reg_impure(v: &const option) { match *v { - some(i) => {impure(i)} //~ ERROR illegal borrow unless pure: enum variant in aliasable, mutable location + some(ref i) => {impure(*i)} //~ ERROR illegal borrow unless pure //~^ NOTE impure due to access to impure function none => {} } @@ -41,7 +41,7 @@ fn match_const_reg_impure(v: &const option) { fn match_imm_reg(v: &option) { match *v { - some(i) => {impure(i)} // OK because immutable + some(ref i) => {impure(*i)} // OK because immutable none => {} } } diff --git a/src/test/compile-fail/borrowck-pat-reassign-binding.rs b/src/test/compile-fail/borrowck-pat-reassign-binding.rs index 02604f65227..fb3f13f909a 100644 --- a/src/test/compile-fail/borrowck-pat-reassign-binding.rs +++ b/src/test/compile-fail/borrowck-pat-reassign-binding.rs @@ -4,9 +4,9 @@ fn main() { let mut x: option = none; match x { //~ NOTE loan of mutable local variable granted here none => {} - some(i) => { + some(ref i) => { // Not ok: i is an outstanding ptr into x. - x = some(i+1); //~ ERROR assigning to mutable local variable prohibited due to outstanding loan + x = some(*i+1); //~ ERROR assigning to mutable local variable prohibited due to outstanding loan } } copy x; // just to prevent liveness warnings diff --git a/src/test/compile-fail/borrowck-pat-reassign-sometimes-binding.rs b/src/test/compile-fail/borrowck-pat-reassign-sometimes-binding.rs index 42dd5024603..e0d96fb9e26 100644 --- a/src/test/compile-fail/borrowck-pat-reassign-sometimes-binding.rs +++ b/src/test/compile-fail/borrowck-pat-reassign-sometimes-binding.rs @@ -8,7 +8,7 @@ fn main() { // fact no outstanding loan of x! x = some(0); } - some(i) => { + some(ref i) => { x = some(1); //~ ERROR assigning to mutable local variable prohibited due to outstanding loan } } diff --git a/src/test/compile-fail/borrowck-unchecked-with-borrow.rs b/src/test/compile-fail/borrowck-unchecked-with-borrow.rs index 86a855de6f1..aa16a272645 100644 --- a/src/test/compile-fail/borrowck-unchecked-with-borrow.rs +++ b/src/test/compile-fail/borrowck-unchecked-with-borrow.rs @@ -3,10 +3,10 @@ fn impure(_i: int) {} // check that unchecked alone does not override borrowck: fn foo(v: &const option) { match *v { - some(i) => { - //~^ ERROR illegal borrow unless pure: enum variant in aliasable, mutable location + some(ref i) => { + //~^ ERROR illegal borrow unless pure unchecked { - impure(i); //~ NOTE impure due to access to impure function + impure(*i); //~ NOTE impure due to access to impure function } } none => { @@ -16,9 +16,9 @@ fn foo(v: &const option) { fn bar(v: &const option) { match *v { - some(i) => { + some(ref i) => { unsafe { - impure(i); + impure(*i); } } none => { @@ -27,4 +27,4 @@ fn bar(v: &const option) { } fn main() { -} \ No newline at end of file +} diff --git a/src/test/run-pass/alt-ref-binding-mut-option.rs b/src/test/run-pass/alt-ref-binding-mut-option.rs new file mode 100644 index 00000000000..c81d87f3464 --- /dev/null +++ b/src/test/run-pass/alt-ref-binding-mut-option.rs @@ -0,0 +1,8 @@ +fn main() { + let mut v = some(22); + match v { + none => {} + some(ref mut p) => { *p += 1; } + } + assert v == some(23); +}