Skip to content

Ref bindings in irrefut patterns #7262

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
17b3712
Update existing tests to account for stricter, more correct handling …
nikomatsakis Jun 20, 2013
1670a8c
Add new tests for irrefutable patterns used in various tricky ways
nikomatsakis Jun 20, 2013
ba13482
update ptr intrinsics and rewrite vec routines to be more correct.
nikomatsakis Jun 20, 2013
9999622
Patch up some code that was using irrefutable patterns incorrectly.
nikomatsakis Jun 20, 2013
366a233
syntax: Patch up code that was using irrefutable patterns incorrectly
nikomatsakis Jun 20, 2013
90843b6
extra: Patch up code that was using irrefutable patterns incorrectly.
nikomatsakis Jun 20, 2013
41efcdf
Make all allocas named so we can see where they originate
nikomatsakis Jun 20, 2013
2d3262c
Update trans to use type to decide when to move, not the moves table …
nikomatsakis Jun 20, 2013
729b07f
Modify borrow checker to visit irrefutable patterns that appear in
nikomatsakis Jun 20, 2013
541c45b
Miscellaneous fixes and cleanup
nikomatsakis Jun 20, 2013
af453a3
This assert does not necessarily hold; sometimes we temporarily incre…
nikomatsakis Jun 20, 2013
59083d2
Address nits by @catamorphism
nikomatsakis Jun 21, 2013
682e746
Patch up some new errors from rustpkg
nikomatsakis Jun 21, 2013
50e95ea
Fix pretty printer, which was ignoring `ref` in irrefutable patterns
nikomatsakis Jun 21, 2013
0e81072
Move stats into an @mut stats
nikomatsakis Jun 22, 2013
ce602c6
Add llvm instrumentation
nikomatsakis Jun 23, 2013
979d3a5
Correct merge failures
nikomatsakis Jun 24, 2013
a6d64df
Correct illegal pattern in windows-only code
nikomatsakis Jul 1, 2013
b5fc4ae
Correct match-drop-strs-issue-4541 when used in check-fast
nikomatsakis Jul 1, 2013
0c6d02f
Correct merge errors
nikomatsakis Jul 8, 2013
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions src/libextra/fileinput.rs
Original file line number Diff line number Diff line change
Expand Up @@ -418,8 +418,8 @@ mod test {
fn make_file(path : &Path, contents: &[~str]) {
let file = io::file_writer(path, [io::Create, io::Truncate]).get();

for contents.iter().advance |&str| {
file.write_str(str);
for contents.iter().advance |str| {
file.write_str(*str);
file.write_char('\n');
}
}
Expand All @@ -445,7 +445,7 @@ mod test {
|i| fmt!("tmp/lib-fileinput-test-fileinput-read-byte-%u.tmp", i)), true);

// 3 files containing 0\n, 1\n, and 2\n respectively
for filenames.iter().enumerate().advance |(i, &filename)| {
for filenames.iter().enumerate().advance |(i, filename)| {
make_file(filename.get_ref(), [fmt!("%u", i)]);
}

Expand Down Expand Up @@ -475,7 +475,7 @@ mod test {
|i| fmt!("tmp/lib-fileinput-test-fileinput-read-%u.tmp", i)), true);

// 3 files containing 1\n, 2\n, and 3\n respectively
for filenames.iter().enumerate().advance |(i, &filename)| {
for filenames.iter().enumerate().advance |(i, filename)| {
make_file(filename.get_ref(), [fmt!("%u", i)]);
}

Expand All @@ -495,10 +495,11 @@ mod test {
3,
|i| fmt!("tmp/lib-fileinput-test-input-vec-%u.tmp", i)), true);

for filenames.iter().enumerate().advance |(i, &filename)| {
for filenames.iter().enumerate().advance |(i, filename)| {
let contents =
vec::from_fn(3, |j| fmt!("%u %u", i, j));
make_file(filename.get_ref(), contents);
debug!("contents=%?", contents);
all_lines.push_all(contents);
}

Expand All @@ -515,7 +516,7 @@ mod test {
3,
|i| fmt!("tmp/lib-fileinput-test-input-vec-state-%u.tmp", i)),true);

for filenames.iter().enumerate().advance |(i, &filename)| {
for filenames.iter().enumerate().advance |(i, filename)| {
let contents =
vec::from_fn(3, |j| fmt!("%u %u", i, j + 1));
make_file(filename.get_ref(), contents);
Expand Down Expand Up @@ -579,10 +580,10 @@ mod test {
3,
|i| fmt!("tmp/lib-fileinput-test-next-file-%u.tmp", i)),true);

for filenames.iter().enumerate().advance |(i, &filename)| {
for filenames.iter().enumerate().advance |(i, filename)| {
let contents =
vec::from_fn(3, |j| fmt!("%u %u", i, j + 1));
make_file(&filename.get(), contents);
make_file(filename.get_ref(), contents);
}

let in = FileInput::from_vec(filenames);
Expand Down
12 changes: 6 additions & 6 deletions src/libextra/num/bigint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1571,10 +1571,10 @@ mod biguint_tests {
fn test_to_str_radix() {
let r = to_str_pairs();
for r.iter().advance |num_pair| {
let &(n, rs) = num_pair;
let &(ref n, ref rs) = num_pair;
for rs.iter().advance |str_pair| {
let &(radix, str) = str_pair;
assert_eq!(n.to_str_radix(radix), str);
let &(ref radix, ref str) = str_pair;
assert_eq!(&n.to_str_radix(*radix), str);
}
}
}
Expand All @@ -1583,10 +1583,10 @@ mod biguint_tests {
fn test_from_str_radix() {
let r = to_str_pairs();
for r.iter().advance |num_pair| {
let &(n, rs) = num_pair;
let &(ref n, ref rs) = num_pair;
for rs.iter().advance |str_pair| {
let &(radix, str) = str_pair;
assert_eq!(&n, &FromStrRadix::from_str_radix(str, radix).get());
let &(ref radix, ref str) = str_pair;
assert_eq!(n, &FromStrRadix::from_str_radix(*str, *radix).get());
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/libextra/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl<T> Drop for Rc<T> {
if self.ptr.is_not_null() {
(*self.ptr).count -= 1;
if (*self.ptr).count == 0 {
ptr::replace_ptr(self.ptr, intrinsics::uninit());
ptr::read_ptr(self.ptr);
free(self.ptr as *c_void)
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/libextra/term.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,8 @@ impl Terminal {
pub fn reset(&self) {
let mut vars = Variables::new();
let s = do self.ti.strings.find_equiv(&("op"))
.map_consume_default(Err(~"can't find terminfo capability `op`")) |&op| {
expand(op, [], &mut vars)
.map_consume_default(Err(~"can't find terminfo capability `op`")) |op| {
expand(copy *op, [], &mut vars)
};
if s.is_ok() {
self.out.write(s.unwrap());
Expand Down
4 changes: 2 additions & 2 deletions src/libextra/terminfo/parm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables)

// Copy parameters into a local vector for mutability
let mut mparams = [Number(0), ..9];
for mparams.mut_iter().zip(params.iter()).advance |(dst, &src)| {
*dst = src;
for mparams.mut_iter().zip(params.iter()).advance |(dst, src)| {
*dst = copy *src;
}

for cap.iter().transform(|&x| x).advance |c| {
Expand Down
10 changes: 5 additions & 5 deletions src/libextra/treemap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -773,15 +773,15 @@ mod test_treemap {
map: &TreeMap<K, V>) {
assert_eq!(ctrl.is_empty(), map.is_empty());
for ctrl.iter().advance |x| {
let &(k, v) = x;
assert!(map.find(&k).unwrap() == &v)
let &(ref k, ref v) = x;
assert!(map.find(k).unwrap() == v)
}
for map.iter().advance |(map_k, map_v)| {
let mut found = false;
for ctrl.iter().advance |x| {
let &(ctrl_k, ctrl_v) = x;
if *map_k == ctrl_k {
assert!(*map_v == ctrl_v);
let &(ref ctrl_k, ref ctrl_v) = x;
if *map_k == *ctrl_k {
assert!(*map_v == *ctrl_v);
found = true;
break;
}
Expand Down
4 changes: 2 additions & 2 deletions src/libextra/workcache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,8 +157,8 @@ impl<D:Decoder> Decodable<D> for WorkMap {
fn decode(d: &mut D) -> WorkMap {
let v : ~[(WorkKey,~str)] = Decodable::decode(d);
let mut w = WorkMap::new();
for v.iter().advance |&(k, v)| {
w.insert(copy k, copy v);
for v.iter().advance |pair| {
w.insert(pair.first(), pair.second());
}
w
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/back/passes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,10 @@ pub fn create_standard_passes(level: OptLevel) -> ~[~str] {
}

pub fn populate_pass_manager(sess: Session, pm: &mut PassManager, pass_list:&[~str]) {
for pass_list.iter().advance |&nm| {
match create_pass(nm) {
for pass_list.iter().advance |nm| {
match create_pass(*nm) {
Some(p) => pm.add_pass(p),
None => sess.warn(fmt!("Unknown pass %s", nm))
None => sess.warn(fmt!("Unknown pass %s", *nm))
}
}
}
Expand Down
1 change: 0 additions & 1 deletion src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,6 @@ pub fn compile_rest(sess: Session,
method_map: method_map,
vtable_map: vtable_map,
write_guard_map: write_guard_map,
moves_map: moves_map,
capture_map: capture_map
};

Expand Down
4 changes: 3 additions & 1 deletion src/librustc/metadata/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,9 @@ fn find_library_crate_aux(
cx.diag.span_err(
cx.span, fmt!("multiple matching crates for `%s`", crate_name));
cx.diag.handler().note("candidates:");
for matches.iter().advance |&(ident, data)| {
for matches.iter().advance |pair| {
let ident = pair.first();
let data = pair.second();
cx.diag.handler().note(fmt!("path: %s", ident));
let attrs = decoder::get_crate_attributes(data);
note_linkage_attrs(cx.intr, cx.diag, attrs);
Expand Down
11 changes: 1 addition & 10 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@ pub struct Maps {
method_map: middle::typeck::method_map,
vtable_map: middle::typeck::vtable_map,
write_guard_map: middle::borrowck::write_guard_map,
moves_map: middle::moves::MovesMap,
capture_map: middle::moves::CaptureMap,
}

Expand Down Expand Up @@ -952,12 +951,6 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
}
}

if maps.moves_map.contains(&id) {
do ebml_w.tag(c::tag_table_moves_map) |ebml_w| {
ebml_w.id(id);
}
}

{
let r = maps.capture_map.find(&id);
for r.iter().advance |&cap_vars| {
Expand Down Expand Up @@ -1121,9 +1114,7 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext,
xcx.dcx.tcx.sess.bug(
fmt!("unknown tag found in side tables: %x", tag));
}
Some(value) => if value == c::tag_table_moves_map {
dcx.maps.moves_map.insert(id);
} else {
Some(value) => {
let val_doc = entry_doc.get(c::tag_table_val as uint);
let mut val_dsr = reader::Decoder(val_doc);
let val_dsr = &mut val_dsr;
Expand Down
91 changes: 40 additions & 51 deletions src/librustc/middle/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ pub fn check_loans(bccx: @BorrowckCtxt,

enum MoveError {
MoveOk,
MoveWhileBorrowed(/*move*/@LoanPath, /*loan*/@LoanPath, /*loan*/span)
MoveWhileBorrowed(/*loan*/@LoanPath, /*loan*/span)
}

impl<'self> CheckLoanCtxt<'self> {
Expand Down Expand Up @@ -348,7 +348,7 @@ impl<'self> CheckLoanCtxt<'self> {
cmt = b;
}

mc::cat_rvalue |
mc::cat_rvalue(*) |
mc::cat_static_item |
mc::cat_implicit_self |
mc::cat_copied_upvar(*) |
Expand Down Expand Up @@ -547,45 +547,50 @@ impl<'self> CheckLoanCtxt<'self> {
self.bccx.loan_path_to_str(loan_path)));
}

pub fn check_move_out_from_expr(&self, ex: @ast::expr) {
match ex.node {
ast::expr_paren(*) => {
/* In the case of an expr_paren(), the expression inside
* the parens will also be marked as being moved. Ignore
* the parents then so as not to report duplicate errors. */
fn check_move_out_from_expr(&self, expr: @ast::expr) {
match expr.node {
ast::expr_fn_block(*) => {
// moves due to capture clauses are checked
// in `check_loans_in_fn`, so that we can
// give a better error message
}
_ => {
let cmt = self.bccx.cat_expr(ex);
match self.analyze_move_out_from_cmt(cmt) {
MoveOk => {}
MoveWhileBorrowed(move_path, loan_path, loan_span) => {
self.bccx.span_err(
cmt.span,
fmt!("cannot move out of `%s` \
because it is borrowed",
self.bccx.loan_path_to_str(move_path)));
self.bccx.span_note(
loan_span,
fmt!("borrow of `%s` occurs here",
self.bccx.loan_path_to_str(loan_path)));
}
self.check_move_out_from_id(expr.id, expr.span)
}
}
}

fn check_move_out_from_id(&self, id: ast::node_id, span: span) {
for self.move_data.each_path_moved_by(id) |_, move_path| {
match self.analyze_move_out_from(id, move_path) {
MoveOk => {}
MoveWhileBorrowed(loan_path, loan_span) => {
self.bccx.span_err(
span,
fmt!("cannot move out of `%s` \
because it is borrowed",
self.bccx.loan_path_to_str(move_path)));
self.bccx.span_note(
loan_span,
fmt!("borrow of `%s` occurs here",
self.bccx.loan_path_to_str(loan_path)));
}
}
}
}

pub fn analyze_move_out_from_cmt(&self, cmt: mc::cmt) -> MoveError {
debug!("analyze_move_out_from_cmt(cmt=%s)", cmt.repr(self.tcx()));
pub fn analyze_move_out_from(&self,
expr_id: ast::node_id,
move_path: @LoanPath) -> MoveError {
debug!("analyze_move_out_from(expr_id=%?, move_path=%s)",
expr_id, move_path.repr(self.tcx()));

// FIXME(#4384) inadequare if/when we permit `move a.b`

// check for a conflicting loan:
let r = opt_loan_path(cmt);
for r.iter().advance |&lp| {
for self.each_in_scope_restriction(cmt.id, lp) |loan, _| {
// Any restriction prevents moves.
return MoveWhileBorrowed(lp, loan.loan_path, loan.span);
}
for self.each_in_scope_restriction(expr_id, move_path) |loan, _| {
// Any restriction prevents moves.
return MoveWhileBorrowed(loan.loan_path, loan.span);
}

MoveOk
Expand Down Expand Up @@ -652,13 +657,11 @@ fn check_loans_in_fn<'a>(fk: &visit::fn_kind,
closure_id: ast::node_id,
cap_var: &moves::CaptureVar) {
let var_id = ast_util::def_id_of_def(cap_var.def).node;
let ty = ty::node_id_to_type(this.tcx(), var_id);
let cmt = this.bccx.cat_def(closure_id, cap_var.span,
ty, cap_var.def);
let move_err = this.analyze_move_out_from_cmt(cmt);
let move_path = @LpVar(var_id);
let move_err = this.analyze_move_out_from(closure_id, move_path);
match move_err {
MoveOk => {}
MoveWhileBorrowed(move_path, loan_path, loan_span) => {
MoveWhileBorrowed(loan_path, loan_span) => {
this.bccx.span_err(
cap_var.span,
fmt!("cannot move `%s` into closure \
Expand Down Expand Up @@ -689,10 +692,7 @@ fn check_loans_in_expr<'a>(expr: @ast::expr,
expr.repr(this.tcx()));

this.check_for_conflicting_loans(expr.id);

if this.bccx.moves_map.contains(&expr.id) {
this.check_move_out_from_expr(expr);
}
this.check_move_out_from_expr(expr);

match expr.node {
ast::expr_self |
Expand Down Expand Up @@ -742,18 +742,7 @@ fn check_loans_in_pat<'a>(pat: @ast::pat,
visit::vt<@mut CheckLoanCtxt<'a>>))
{
this.check_for_conflicting_loans(pat.id);

// Note: moves out of pattern bindings are not checked by
// the borrow checker, at least not directly. What happens
// is that if there are any moved bindings, the discriminant
// will be considered a move, and this will be checked as
// normal. Then, in `middle::check_match`, we will check
// that no move occurs in a binding that is underneath an
// `@` or `&`. Together these give the same guarantees as
// `check_move_out_from_expr()` without requiring us to
// rewalk the patterns and rebuild the pattern
// categorizations.

this.check_move_out_from_id(pat.id, pat.span);
visit::visit_pat(pat, (this, vt));
}

Expand Down
Loading