librustc: Hook borrow check loan checking up to the moves-based-on-type infrastructure. rs=helps-unbreak-the-build

This commit is contained in:
Patrick Walton 2012-12-05 15:06:54 -08:00
parent a05ba09d90
commit 1282fc8074
18 changed files with 143 additions and 87 deletions

View file

@ -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 {

View file

@ -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<util::NonCopyable>,
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...
}

View file

@ -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);

View file

@ -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.

View file

@ -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<ident, node_id>;
@ -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;
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -8,11 +8,25 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub enum Fold<T> = Fold_<T>;
pub struct Fold<T> {
ctxt: T,
fold_doc: FoldDoc<T>,
fold_crate: FoldCrate<T>,
fold_item: FoldItem<T>,
fold_mod: FoldMod<T>,
fold_nmod: FoldNmod<T>,
fold_fn: FoldFn<T>,
fold_const: FoldConst<T>,
fold_enum: FoldEnum<T>,
fold_trait: FoldTrait<T>,
fold_impl: FoldImpl<T>,
fold_type: FoldType<T>,
fold_struct: FoldStruct<T>
}
impl<T: Clone> Fold<T>: Clone {
fn clone(&self) -> Fold<T> {
Fold({
Fold {
ctxt: self.ctxt.clone(),
fold_doc: copy self.fold_doc,
fold_crate: copy self.fold_crate,
@ -26,7 +40,7 @@ impl<T: Clone> Fold<T>: 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<T> = fn~(fold: &Fold<T>, +doc: doc::TyDoc) -> doc::TyDoc;
type FoldStruct<T> = fn~(fold: &Fold<T>,
+doc: doc::StructDoc) -> doc::StructDoc;
type Fold_<T> = {
ctxt: T,
fold_doc: FoldDoc<T>,
fold_crate: FoldCrate<T>,
fold_item: FoldItem<T>,
fold_mod: FoldMod<T>,
fold_nmod: FoldNmod<T>,
fold_fn: FoldFn<T>,
fold_const: FoldConst<T>,
fold_enum: FoldEnum<T>,
fold_trait: FoldTrait<T>,
fold_impl: FoldImpl<T>,
fold_type: FoldType<T>,
fold_struct: FoldStruct<T>
};
// This exists because fn types don't infer correctly as record
// initializers, but they do as function arguments
fn mk_fold<T:Clone>(
@ -78,7 +75,7 @@ fn mk_fold<T:Clone>(
+fold_type: FoldType<T>,
+fold_struct: FoldStruct<T>
) -> Fold<T> {
Fold({
Fold {
ctxt: move ctxt,
fold_doc: move fold_doc,
fold_crate: move fold_crate,
@ -92,7 +89,7 @@ fn mk_fold<T:Clone>(
fold_impl: move fold_impl,
fold_type: move fold_type,
fold_struct: move fold_struct
})
}
}
pub fn default_any_fold<T:Send Clone>(+ctxt: T) -> Fold<T> {

View file

@ -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)
}

View file

@ -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);

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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 {