From 1282fc80740b5c462a094c45f65cb1ce0c1d7756 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Wed, 5 Dec 2012 15:06:54 -0800 Subject: [PATCH] librustc: Hook borrow check loan checking up to the moves-based-on-type infrastructure. rs=helps-unbreak-the-build --- src/libcore/path.rs | 4 +- src/libcore/task/mod.rs | 56 ++++++++++----------- src/librustc/middle/borrowck/check_loans.rs | 8 +++ src/librustc/middle/mode.rs | 17 ++++++- src/librustc/middle/pat_util.rs | 20 ++++++++ src/librustdoc/attr_pass.rs | 7 +-- src/librustdoc/desc_to_brief_pass.rs | 7 +-- src/librustdoc/fold.rs | 41 +++++++-------- src/librustdoc/markdown_index_pass.rs | 7 +-- src/librustdoc/page_pass.rs | 7 +-- src/librustdoc/path_pass.rs | 7 +-- src/librustdoc/prune_hidden_pass.rs | 7 +-- src/librustdoc/prune_private_pass.rs | 8 +-- src/librustdoc/sectionalize_pass.rs | 7 +-- src/librustdoc/sort_pass.rs | 7 +-- src/librustdoc/text_pass.rs | 7 +-- src/librustdoc/tystr_pass.rs | 7 +-- src/libsyntax/print/pp.rs | 6 ++- 18 files changed, 143 insertions(+), 87 deletions(-) diff --git a/src/libcore/path.rs b/src/libcore/path.rs index afff41e53db1..0fd30501a4c5 100644 --- a/src/libcore/path.rs +++ b/src/libcore/path.rs @@ -502,7 +502,7 @@ impl PosixPath : GenericPath { let mut v = copy self.components; let mut ss = str::split_nonempty(s, |c| windows::is_sep(c as u8)); unsafe { v.push_all_move(move ss); } - PosixPath { components: move v, ..self } + PosixPath { components: move v, ..copy self } } pure fn pop() -> PosixPath { @@ -707,7 +707,7 @@ impl WindowsPath : GenericPath { let mut v = copy self.components; let mut ss = str::split_nonempty(s, |c| windows::is_sep(c as u8)); unsafe { v.push_all_move(move ss); } - return WindowsPath { components: move v, ..self } + return WindowsPath { components: move v, ..copy self } } pure fn pop() -> WindowsPath { diff --git a/src/libcore/task/mod.rs b/src/libcore/task/mod.rs index bd8ddda9e7ff..7495bf7be4ca 100644 --- a/src/libcore/task/mod.rs +++ b/src/libcore/task/mod.rs @@ -215,12 +215,12 @@ pub type TaskOpts = { // the run function move them in. // FIXME (#3724): Replace the 'consumed' bit with move mode on self -pub enum TaskBuilder = { +pub struct TaskBuilder { opts: TaskOpts, gen_body: fn@(v: fn~()) -> fn~(), can_not_copy: Option, mut consumed: bool, -}; +} /** * Generate the base configuration for spawning a task, off of which more @@ -228,12 +228,12 @@ pub enum TaskBuilder = { * For example, task().unlinked().spawn is equivalent to spawn_unlinked. */ pub fn task() -> TaskBuilder { - TaskBuilder({ + TaskBuilder { opts: default_task_opts(), gen_body: |body| move body, // Identity function can_not_copy: None, mut consumed: false, - }) + } } #[doc(hidden)] // FIXME #3538 @@ -244,7 +244,7 @@ priv impl TaskBuilder { } self.consumed = true; let notify_chan = replace(&mut self.opts.notify_chan, None); - TaskBuilder({ + TaskBuilder { opts: { linked: self.opts.linked, supervised: self.opts.supervised, @@ -254,7 +254,7 @@ priv impl TaskBuilder { gen_body: self.gen_body, can_not_copy: None, mut consumed: false - }) + } } } @@ -265,7 +265,7 @@ impl TaskBuilder { */ fn unlinked() -> TaskBuilder { let notify_chan = replace(&mut self.opts.notify_chan, None); - TaskBuilder({ + TaskBuilder { opts: { linked: false, supervised: self.opts.supervised, @@ -273,8 +273,8 @@ impl TaskBuilder { sched: self.opts.sched }, can_not_copy: None, - .. *self.consume() - }) + .. self.consume() + } } /** * Unidirectionally link the child task's failure with the parent's. The @@ -283,7 +283,7 @@ impl TaskBuilder { */ fn supervised() -> TaskBuilder { let notify_chan = replace(&mut self.opts.notify_chan, None); - TaskBuilder({ + TaskBuilder { opts: { linked: false, supervised: true, @@ -291,8 +291,8 @@ impl TaskBuilder { sched: self.opts.sched }, can_not_copy: None, - .. *self.consume() - }) + .. self.consume() + } } /** * Link the child task's and parent task's failures. If either fails, the @@ -300,7 +300,7 @@ impl TaskBuilder { */ fn linked() -> TaskBuilder { let notify_chan = replace(&mut self.opts.notify_chan, None); - TaskBuilder({ + TaskBuilder { opts: { linked: true, supervised: false, @@ -308,8 +308,8 @@ impl TaskBuilder { sched: self.opts.sched }, can_not_copy: None, - .. *self.consume() - }) + .. self.consume() + } } /** @@ -345,7 +345,7 @@ impl TaskBuilder { blk(move notify_pipe_po); // Reconfigure self to use a notify channel. - TaskBuilder({ + TaskBuilder { opts: { linked: self.opts.linked, supervised: self.opts.supervised, @@ -353,13 +353,13 @@ impl TaskBuilder { sched: self.opts.sched }, can_not_copy: None, - .. *self.consume() - }) + .. self.consume() + } } /// Configure a custom scheduler mode for the task. fn sched_mode(mode: SchedMode) -> TaskBuilder { let notify_chan = replace(&mut self.opts.notify_chan, None); - TaskBuilder({ + TaskBuilder { opts: { linked: self.opts.linked, supervised: self.opts.supervised, @@ -367,8 +367,8 @@ impl TaskBuilder { sched: Some({ mode: mode, foreign_stack_size: None}) }, can_not_copy: None, - .. *self.consume() - }) + .. self.consume() + } } /** @@ -386,7 +386,7 @@ impl TaskBuilder { fn add_wrapper(wrapper: fn@(v: fn~()) -> fn~()) -> TaskBuilder { let prev_gen_body = self.gen_body; let notify_chan = replace(&mut self.opts.notify_chan, None); - TaskBuilder({ + TaskBuilder { opts: { linked: self.opts.linked, supervised: self.opts.supervised, @@ -399,8 +399,8 @@ impl TaskBuilder { gen_body: |move prev_gen_body, body| { wrapper(prev_gen_body(move body)) }, can_not_copy: None, - .. *self.consume() - }) + .. self.consume() + } } /** @@ -782,11 +782,11 @@ fn test_spawn_linked_sup_fail_up() { // child fails; parent fails }; let b0 = task(); - let b1 = TaskBuilder({ + let b1 = TaskBuilder { opts: move opts, can_not_copy: None, .. *b0 - }); + }; do b1.spawn { fail; } comm::recv(po); // We should get punted awake } @@ -802,11 +802,11 @@ fn test_spawn_linked_sup_fail_down() { // parent fails; child fails }; let b0 = task(); - let b1 = TaskBuilder({ + let b1 = TaskBuilder { opts: move opts, can_not_copy: None, .. *b0 - }); + }; do b1.spawn { loop { task::yield(); } } fail; // *both* mechanisms would be wrong if this didn't kill the child... } diff --git a/src/librustc/middle/borrowck/check_loans.rs b/src/librustc/middle/borrowck/check_loans.rs index 7ff7c48f54a1..8f3a3d1440b8 100644 --- a/src/librustc/middle/borrowck/check_loans.rs +++ b/src/librustc/middle/borrowck/check_loans.rs @@ -17,6 +17,8 @@ // 3. assignments do not affect things loaned out as immutable // 4. moves to dnot affect things loaned out in any way +use middle::ty::{CopyValue, MoveValue, ReadValue}; + use dvec::DVec; export check_loans; @@ -624,6 +626,12 @@ fn check_loans_in_expr(expr: @ast::expr, self.check_for_conflicting_loans(expr.id); + // If this is a move, check it. + match self.tcx().value_modes.find(expr.id) { + Some(MoveValue) => self.check_move_out(expr), + Some(ReadValue) | Some(CopyValue) | None => {} + } + match expr.node { ast::expr_path(*) if self.bccx.last_use_map.contains_key(expr.id) => { self.check_last_use(expr); diff --git a/src/librustc/middle/mode.rs b/src/librustc/middle/mode.rs index b3125077ec2d..c763c9f74891 100644 --- a/src/librustc/middle/mode.rs +++ b/src/librustc/middle/mode.rs @@ -9,7 +9,7 @@ use syntax::ast::{expr_addr_of, expr_assign_op, expr_binary, expr_call}; use syntax::ast::{expr_copy, expr_field, expr_index, expr_method_call}; use syntax::ast::{expr_path, expr_swap, expr_unary, node_id, sty_uniq}; use syntax::ast::{sty_value}; -use syntax::ast::{box, uniq, deref, not, neg, expr_paren}; +use syntax::ast::{box, uniq, deref, not, neg, expr_match, expr_paren}; use syntax::visit; use syntax::visit::vt; @@ -158,6 +158,21 @@ fn compute_modes_for_expr(expr: @expr, compute_modes_for_expr(arg, cx, v); record_mode_for_expr(expr, cx); } + expr_match(head, ref arms) => { + let by_move_bindings_present = + pat_util::arms_have_by_move_bindings(cx.tcx.def_map, *arms); + if by_move_bindings_present { + // Propagate the current mode flag downward. + visit::visit_expr(expr, cx, v); + } else { + // We aren't moving into any pattern, so this is just a read. + let head_cx = VisitContext { mode: ReadValue, ..cx }; + compute_modes_for_expr(head, head_cx, v); + for arms.each |arm| { + (v.visit_arm)(*arm, cx, v); + } + } + } _ => { // XXX: Spell out every expression above so when we add them we // don't forget to update this file. diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 8ef743b71a69..467897db9d9e 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -19,6 +19,7 @@ use std::map::HashMap; export pat_binding_ids, pat_bindings, pat_id_map, PatIdMap; export pat_is_variant_or_struct, pat_is_binding, pat_is_binding_or_wild; export pat_is_const; +export arms_have_by_move_bindings; type PatIdMap = std::map::HashMap; @@ -91,3 +92,22 @@ fn pat_binding_ids(dm: resolve::DefMap, pat: @pat) -> ~[node_id] { pat_bindings(dm, pat, |_bm, b_id, _sp, _pt| found.push(b_id) ); return found; } + +fn arms_have_by_move_bindings(dm: resolve::DefMap, +arms: &[arm]) -> bool { + for arms.each |arm| { + for arm.pats.each |pat| { + let mut found = false; + do pat_bindings(dm, *pat) |binding_mode, _node_id, _span, _path| { + match binding_mode { + bind_by_move => found = true, + bind_by_implicit_ref | + bind_by_ref(*) | + bind_by_value => {} + } + } + if found { return true; } + } + } + return false; +} + diff --git a/src/librustdoc/attr_pass.rs b/src/librustdoc/attr_pass.rs index d8555b780b15..aaffe3bfeaa1 100644 --- a/src/librustdoc/attr_pass.rs +++ b/src/librustdoc/attr_pass.rs @@ -18,6 +18,7 @@ of the natural-language documentation for a crate. use doc::ItemUtils; use extract::to_str; +use fold::Fold; use syntax::ast; use syntax::ast_map; use std::map::HashMap; @@ -33,14 +34,14 @@ fn run( srv: astsrv::Srv, +doc: doc::Doc ) -> doc::Doc { - let fold = fold::Fold({ + let fold = Fold { fold_crate: fold_crate, fold_item: fold_item, fold_enum: fold_enum, fold_trait: fold_trait, fold_impl: fold_impl, - .. *fold::default_any_fold(srv) - }); + .. fold::default_any_fold(srv) + }; (fold.fold_doc)(&fold, doc) } diff --git a/src/librustdoc/desc_to_brief_pass.rs b/src/librustdoc/desc_to_brief_pass.rs index 99f69b53a3a9..fa21366d917c 100644 --- a/src/librustdoc/desc_to_brief_pass.rs +++ b/src/librustdoc/desc_to_brief_pass.rs @@ -16,6 +16,7 @@ is interpreted as the brief description. */ use doc::ItemUtils; +use fold::Fold; pub fn mk_pass() -> Pass { { @@ -28,12 +29,12 @@ fn run( _srv: astsrv::Srv, +doc: doc::Doc ) -> doc::Doc { - let fold = fold::Fold({ + let fold = Fold { fold_item: fold_item, fold_trait: fold_trait, fold_impl: fold_impl, - .. *fold::default_any_fold(()) - }); + .. fold::default_any_fold(()) + }; (fold.fold_doc)(&fold, doc) } diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 23f020d9254a..da276922fe77 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -8,11 +8,25 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -pub enum Fold = Fold_; +pub struct Fold { + ctxt: T, + fold_doc: FoldDoc, + fold_crate: FoldCrate, + fold_item: FoldItem, + fold_mod: FoldMod, + fold_nmod: FoldNmod, + fold_fn: FoldFn, + fold_const: FoldConst, + fold_enum: FoldEnum, + fold_trait: FoldTrait, + fold_impl: FoldImpl, + fold_type: FoldType, + fold_struct: FoldStruct +} impl Fold: Clone { fn clone(&self) -> Fold { - Fold({ + Fold { ctxt: self.ctxt.clone(), fold_doc: copy self.fold_doc, fold_crate: copy self.fold_crate, @@ -26,7 +40,7 @@ impl Fold: Clone { fold_impl: copy self.fold_impl, fold_type: copy self.fold_type, fold_struct: copy self.fold_struct - }) + } } } @@ -44,23 +58,6 @@ type FoldType = fn~(fold: &Fold, +doc: doc::TyDoc) -> doc::TyDoc; type FoldStruct = fn~(fold: &Fold, +doc: doc::StructDoc) -> doc::StructDoc; -type Fold_ = { - ctxt: T, - fold_doc: FoldDoc, - fold_crate: FoldCrate, - fold_item: FoldItem, - fold_mod: FoldMod, - fold_nmod: FoldNmod, - fold_fn: FoldFn, - fold_const: FoldConst, - fold_enum: FoldEnum, - fold_trait: FoldTrait, - fold_impl: FoldImpl, - fold_type: FoldType, - fold_struct: FoldStruct -}; - - // This exists because fn types don't infer correctly as record // initializers, but they do as function arguments fn mk_fold( @@ -78,7 +75,7 @@ fn mk_fold( +fold_type: FoldType, +fold_struct: FoldStruct ) -> Fold { - Fold({ + Fold { ctxt: move ctxt, fold_doc: move fold_doc, fold_crate: move fold_crate, @@ -92,7 +89,7 @@ fn mk_fold( fold_impl: move fold_impl, fold_type: move fold_type, fold_struct: move fold_struct - }) + } } pub fn default_any_fold(+ctxt: T) -> Fold { diff --git a/src/librustdoc/markdown_index_pass.rs b/src/librustdoc/markdown_index_pass.rs index 8ed15fbad365..b1cc778bd1bf 100644 --- a/src/librustdoc/markdown_index_pass.rs +++ b/src/librustdoc/markdown_index_pass.rs @@ -11,6 +11,7 @@ //! Build indexes as appropriate for the markdown pass use doc::ItemUtils; +use fold::Fold; pub fn mk_pass(+config: config::Config) -> Pass { { @@ -26,11 +27,11 @@ fn run( +doc: doc::Doc, +config: config::Config ) -> doc::Doc { - let fold = fold::Fold({ + let fold = Fold { fold_mod: fold_mod, fold_nmod: fold_nmod, - .. *fold::default_any_fold(config) - }); + .. fold::default_any_fold(config) + }; (fold.fold_doc)(&fold, doc) } diff --git a/src/librustdoc/page_pass.rs b/src/librustdoc/page_pass.rs index 07f4bd73cc03..5125f7c1da60 100644 --- a/src/librustdoc/page_pass.rs +++ b/src/librustdoc/page_pass.rs @@ -16,6 +16,7 @@ individual modules, pages for the crate, indexes, etc. */ use doc::{ItemUtils, PageUtils}; +use fold::Fold; use syntax::ast; use util::NominalOp; @@ -68,12 +69,12 @@ fn make_doc_from_pages(page_port: PagePort) -> doc::Doc { } fn find_pages(doc: doc::Doc, page_chan: PageChan) { - let fold = fold::Fold({ + let fold = Fold { fold_crate: fold_crate, fold_mod: fold_mod, fold_nmod: fold_nmod, - .. *fold::default_any_fold(NominalOp { op: page_chan }) - }); + .. fold::default_any_fold(NominalOp { op: page_chan }) + }; (fold.fold_doc)(&fold, doc); comm::send(page_chan, None); diff --git a/src/librustdoc/path_pass.rs b/src/librustdoc/path_pass.rs index f93005f7d793..b17f4d67a5c3 100644 --- a/src/librustdoc/path_pass.rs +++ b/src/librustdoc/path_pass.rs @@ -11,6 +11,7 @@ //! Records the full path to items use doc::ItemUtils; +use fold::Fold; use syntax::ast; pub fn mk_pass() -> Pass { @@ -35,12 +36,12 @@ fn run(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc { srv: srv, mut path: ~[] }; - let fold = fold::Fold({ + let fold = Fold { fold_item: fold_item, fold_mod: fold_mod, fold_nmod: fold_nmod, - .. *fold::default_any_fold(move ctxt) - }); + .. fold::default_any_fold(move ctxt) + }; (fold.fold_doc)(&fold, doc) } diff --git a/src/librustdoc/prune_hidden_pass.rs b/src/librustdoc/prune_hidden_pass.rs index fde31baca571..bfe6f8387041 100644 --- a/src/librustdoc/prune_hidden_pass.rs +++ b/src/librustdoc/prune_hidden_pass.rs @@ -11,6 +11,7 @@ //! Prunes things with the #[doc(hidden)] attribute use doc::ItemUtils; +use fold::Fold; use std::map::HashMap; pub fn mk_pass() -> Pass { @@ -21,10 +22,10 @@ pub fn mk_pass() -> Pass { } fn run(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc { - let fold = fold::Fold({ + let fold = Fold { fold_mod: fold_mod, - .. *fold::default_any_fold(srv) - }); + .. fold::default_any_fold(srv) + }; (fold.fold_doc)(&fold, doc) } diff --git a/src/librustdoc/prune_private_pass.rs b/src/librustdoc/prune_private_pass.rs index 8841deefb77b..e3dc1553a639 100644 --- a/src/librustdoc/prune_private_pass.rs +++ b/src/librustdoc/prune_private_pass.rs @@ -12,6 +12,8 @@ #[legacy_exports]; +use fold::Fold; + export mk_pass; fn mk_pass() -> Pass { @@ -22,10 +24,10 @@ fn mk_pass() -> Pass { } fn run(srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc { - let fold = fold::Fold({ + let fold = Fold { fold_mod: fold_mod, - .. *fold::default_any_fold(srv) - }); + .. fold::default_any_fold(srv) + }; (fold.fold_doc)(&fold, doc) } diff --git a/src/librustdoc/sectionalize_pass.rs b/src/librustdoc/sectionalize_pass.rs index bb11ba074a65..2c73d4c478b1 100644 --- a/src/librustdoc/sectionalize_pass.rs +++ b/src/librustdoc/sectionalize_pass.rs @@ -11,6 +11,7 @@ //! Breaks rustdocs into sections according to their headers use doc::ItemUtils; +use fold::Fold; pub fn mk_pass() -> Pass { { @@ -20,12 +21,12 @@ pub fn mk_pass() -> Pass { } fn run(_srv: astsrv::Srv, +doc: doc::Doc) -> doc::Doc { - let fold = fold::Fold({ + let fold = Fold { fold_item: fold_item, fold_trait: fold_trait, fold_impl: fold_impl, - .. *fold::default_any_fold(()) - }); + .. fold::default_any_fold(()) + }; (fold.fold_doc)(&fold, doc) } diff --git a/src/librustdoc/sort_pass.rs b/src/librustdoc/sort_pass.rs index 8418110c647c..a4926e765a77 100644 --- a/src/librustdoc/sort_pass.rs +++ b/src/librustdoc/sort_pass.rs @@ -11,6 +11,7 @@ //! A general sorting pass use doc::ItemUtils; +use fold::Fold; use std::sort; use util::NominalOp; @@ -33,10 +34,10 @@ fn run( +doc: doc::Doc, +lteq: ItemLtEq ) -> doc::Doc { - let fold = fold::Fold({ + let fold = Fold { fold_mod: fold_mod, - .. *fold::default_any_fold(move lteq) - }); + .. fold::default_any_fold(move lteq) + }; (fold.fold_doc)(&fold, doc) } diff --git a/src/librustdoc/text_pass.rs b/src/librustdoc/text_pass.rs index 3beaba840e1b..9a48822b4536 100644 --- a/src/librustdoc/text_pass.rs +++ b/src/librustdoc/text_pass.rs @@ -11,6 +11,7 @@ //! Generic pass for performing an operation on all descriptions use doc::ItemUtils; +use fold::Fold; use util::NominalOp; pub fn mk_pass(name: ~str, +op: fn~(~str) -> ~str) -> Pass { @@ -33,13 +34,13 @@ fn run( let op = NominalOp { op: move op }; - let fold = fold::Fold({ + let fold = Fold { fold_item: fold_item, fold_enum: fold_enum, fold_trait: fold_trait, fold_impl: fold_impl, - .. *fold::default_any_fold(move op) - }); + .. fold::default_any_fold(move op) + }; (fold.fold_doc)(&fold, doc) } diff --git a/src/librustdoc/tystr_pass.rs b/src/librustdoc/tystr_pass.rs index eace2db5ac13..7d5c5b15e55f 100644 --- a/src/librustdoc/tystr_pass.rs +++ b/src/librustdoc/tystr_pass.rs @@ -11,6 +11,7 @@ //! Pulls type information out of the AST and attaches it to the document use doc::ItemUtils; +use fold::Fold; use syntax::ast; use syntax::print::pprust; use syntax::ast_map; @@ -28,7 +29,7 @@ fn run( srv: astsrv::Srv, +doc: doc::Doc ) -> doc::Doc { - let fold = fold::Fold({ + let fold = Fold { fold_fn: fold_fn, fold_const: fold_const, fold_enum: fold_enum, @@ -36,8 +37,8 @@ fn run( fold_impl: fold_impl, fold_type: fold_type, fold_struct: fold_struct, - .. *fold::default_any_fold(srv) - }); + .. fold::default_any_fold(srv) + }; (fold.fold_doc)(&fold, doc) } diff --git a/src/libsyntax/print/pp.rs b/src/libsyntax/print/pp.rs index a51089334f00..3e9fe8052600 100644 --- a/src/libsyntax/print/pp.rs +++ b/src/libsyntax/print/pp.rs @@ -461,7 +461,11 @@ impl printer { fn print(x: token, L: int) { debug!("print %s %d (remaining line space=%d)", tok_str(x), L, self.space); - log(debug, buf_str(self.token, self.size, self.left, self.right, 6u)); + log(debug, buf_str(copy self.token, + copy self.size, + self.left, + self.right, + 6u)); match x { BEGIN(b) => { if L > self.space {