Skip to content

Commit 239557d

Browse files
committed
auto merge of #13724 : nikomatsakis/rust/expr-use-visitor, r=pnkfelix
Pre-step towards issue #12624 and others: Introduce ExprUseVisitor, remove the moves computation. ExprUseVisitor is a visitor that walks the AST for a function and calls a delegate to inform it where borrows, copies, and moves occur. In this patch, I rewrite the gather_loans visitor to use ExprUseVisitor, but in future patches, I think we could rewrite regionck, check_loans, and possibly other passes to use it as well. This would refactor the repeated code between those places that tries to determine where copies/moves/etc occur. r? @alexcrichton
2 parents 5c0abea + b9af043 commit 239557d

29 files changed

+1265
-1631
lines changed

src/librustc/back/rpath.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ pub fn get_rpath_relative_to_output(os: abi::Os,
133133
}
134134

135135
pub fn get_install_prefix_rpath(sysroot: &Path, target_triple: &str) -> ~str {
136-
let install_prefix = env!("CFG_PREFIX");
136+
let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX");
137137

138138
let tlib = filesearch::relative_target_lib_path(sysroot, target_triple);
139139
let mut path = Path::new(install_prefix);
@@ -171,7 +171,7 @@ mod test {
171171
fn test_prefix_rpath() {
172172
let sysroot = filesearch::get_or_default_sysroot();
173173
let res = get_install_prefix_rpath(&sysroot, "triple");
174-
let mut d = Path::new(env!("CFG_PREFIX"));
174+
let mut d = Path::new((option_env!("CFG_PREFIX")).expect("CFG_PREFIX"));
175175
d.push("lib");
176176
d.push(filesearch::rustlibdir());
177177
d.push("triple/lib");

src/librustc/driver/driver.rs

+6-17
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use metadata::{creader, filesearch};
2323
use metadata::cstore::CStore;
2424
use metadata::creader::Loader;
2525
use metadata;
26-
use middle::{trans, freevars, kind, ty, typeck, lint, astencode, reachable};
26+
use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
2727
use middle;
2828
use util::common::time;
2929
use util::ppaux;
@@ -35,7 +35,6 @@ use std::cell::{Cell, RefCell};
3535
use std::io;
3636
use std::io::fs;
3737
use std::io::MemReader;
38-
use std::mem::drop;
3938
use std::os;
4039
use getopts::{optopt, optmulti, optflag, optflagopt};
4140
use getopts;
@@ -278,7 +277,6 @@ pub struct CrateAnalysis {
278277
pub exported_items: middle::privacy::ExportedItems,
279278
pub public_items: middle::privacy::PublicItems,
280279
pub ty_cx: ty::ctxt,
281-
pub maps: astencode::Maps,
282280
pub reachable: NodeSet,
283281
}
284282

@@ -354,21 +352,14 @@ pub fn phase_3_run_analysis_passes(sess: Session,
354352
time(time_passes, "effect checking", (), |_|
355353
middle::effect::check_crate(&ty_cx, krate));
356354

357-
let middle::moves::MoveMaps {moves_map, capture_map} =
358-
time(time_passes, "compute moves", (), |_|
359-
middle::moves::compute_moves(&ty_cx, krate));
360-
361355
time(time_passes, "match checking", (), |_|
362-
middle::check_match::check_crate(&ty_cx, &moves_map, krate));
356+
middle::check_match::check_crate(&ty_cx, krate));
363357

364358
time(time_passes, "liveness checking", (), |_|
365-
middle::liveness::check_crate(&ty_cx, &capture_map, krate));
359+
middle::liveness::check_crate(&ty_cx, krate));
366360

367361
time(time_passes, "borrow checking", (), |_|
368-
middle::borrowck::check_crate(&ty_cx, &moves_map,
369-
&capture_map, krate));
370-
371-
drop(moves_map);
362+
middle::borrowck::check_crate(&ty_cx, krate));
372363

373364
time(time_passes, "kind checking", (), |_|
374365
kind::check_crate(&ty_cx, krate));
@@ -392,9 +383,6 @@ pub fn phase_3_run_analysis_passes(sess: Session,
392383
ty_cx: ty_cx,
393384
exported_items: exported_items,
394385
public_items: public_items,
395-
maps: astencode::Maps {
396-
capture_map: RefCell::new(capture_map)
397-
},
398386
reachable: reachable_map
399387
}
400388
}
@@ -810,7 +798,8 @@ pub fn host_triple() -> &'static str {
810798
// Instead of grabbing the host triple (for the current host), we grab (at
811799
// compile time) the target triple that this rustc is built with and
812800
// calling that (at runtime) the host triple.
813-
env!("CFG_COMPILER_HOST_TRIPLE")
801+
(option_env!("CFG_COMPILER_HOST_TRIPLE")).
802+
expect("CFG_COMPILER_HOST_TRIPLE")
814803
}
815804

816805
pub fn build_session_options(matches: &getopts::Matches) -> session::Options {

src/librustc/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,13 @@ pub mod middle {
8686
pub mod astencode;
8787
pub mod lang_items;
8888
pub mod privacy;
89-
pub mod moves;
9089
pub mod entry;
9190
pub mod effect;
9291
pub mod reachable;
9392
pub mod graph;
9493
pub mod cfg;
9594
pub mod dead;
95+
pub mod expr_use_visitor;
9696
}
9797

9898
pub mod front {

src/librustc/middle/astencode.rs

+4-65
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
2424
RegionParameter};
2525
use metadata::tyencode;
2626
use middle::typeck::{MethodCall, MethodCallee, MethodOrigin};
27-
use middle::{ty, typeck, moves};
28-
use middle;
27+
use middle::{ty, typeck};
2928
use util::ppaux::ty_to_str;
3029

3130
use syntax::{ast, ast_map, ast_util, codemap, fold};
@@ -36,7 +35,6 @@ use syntax;
3635

3736
use libc;
3837
use std::cast;
39-
use std::cell::RefCell;
4038
use std::io::Seek;
4139
use std::io::MemWriter;
4240
use std::rc::Rc;
@@ -52,15 +50,9 @@ use writer = serialize::ebml::writer;
5250
#[cfg(test)] use syntax::parse;
5351
#[cfg(test)] use syntax::print::pprust;
5452

55-
// Auxiliary maps of things to be encoded
56-
pub struct Maps {
57-
pub capture_map: RefCell<middle::moves::CaptureMap>,
58-
}
59-
6053
struct DecodeContext<'a> {
6154
cdata: &'a cstore::crate_metadata,
6255
tcx: &'a ty::ctxt,
63-
maps: &'a Maps
6456
}
6557

6658
struct ExtendedDecodeContext<'a> {
@@ -84,8 +76,7 @@ pub type Encoder<'a> = writer::Encoder<'a, MemWriter>;
8476

8577
pub fn encode_inlined_item(ecx: &e::EncodeContext,
8678
ebml_w: &mut Encoder,
87-
ii: e::InlinedItemRef,
88-
maps: &Maps) {
79+
ii: e::InlinedItemRef) {
8980
let id = match ii {
9081
e::IIItemRef(i) => i.id,
9182
e::IIForeignRef(i) => i.id,
@@ -101,7 +92,7 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
10192
ebml_w.start_tag(c::tag_ast as uint);
10293
id_range.encode(ebml_w);
10394
encode_ast(ebml_w, ii);
104-
encode_side_tables_for_ii(ecx, maps, ebml_w, &ii);
95+
encode_side_tables_for_ii(ecx, ebml_w, &ii);
10596
ebml_w.end_tag();
10697

10798
debug!("< Encoded inlined fn: {} ({})",
@@ -111,14 +102,12 @@ pub fn encode_inlined_item(ecx: &e::EncodeContext,
111102

112103
pub fn decode_inlined_item(cdata: &cstore::crate_metadata,
113104
tcx: &ty::ctxt,
114-
maps: &Maps,
115105
path: Vec<ast_map::PathElem>,
116106
par_doc: ebml::Doc)
117107
-> Result<ast::InlinedItem, Vec<ast_map::PathElem>> {
118108
let dcx = &DecodeContext {
119109
cdata: cdata,
120110
tcx: tcx,
121-
maps: maps
122111
};
123112
match par_doc.opt_child(c::tag_ast) {
124113
None => Err(path),
@@ -551,32 +540,6 @@ impl tr for freevar_entry {
551540
}
552541
}
553542

554-
// ______________________________________________________________________
555-
// Encoding and decoding of CaptureVar information
556-
557-
trait capture_var_helper {
558-
fn read_capture_var(&mut self, xcx: &ExtendedDecodeContext)
559-
-> moves::CaptureVar;
560-
}
561-
562-
impl<'a> capture_var_helper for reader::Decoder<'a> {
563-
fn read_capture_var(&mut self, xcx: &ExtendedDecodeContext)
564-
-> moves::CaptureVar {
565-
let cvar: moves::CaptureVar = Decodable::decode(self).unwrap();
566-
cvar.tr(xcx)
567-
}
568-
}
569-
570-
impl tr for moves::CaptureVar {
571-
fn tr(&self, xcx: &ExtendedDecodeContext) -> moves::CaptureVar {
572-
moves::CaptureVar {
573-
def: self.def.tr(xcx),
574-
span: self.span.tr(xcx),
575-
mode: self.mode
576-
}
577-
}
578-
}
579-
580543
// ______________________________________________________________________
581544
// Encoding and decoding of MethodCallee
582545

@@ -935,7 +898,6 @@ impl<'a> write_tag_and_id for Encoder<'a> {
935898
struct SideTableEncodingIdVisitor<'a,'b> {
936899
ecx_ptr: *libc::c_void,
937900
new_ebml_w: &'a mut Encoder<'b>,
938-
maps: &'a Maps,
939901
}
940902

941903
impl<'a,'b> ast_util::IdVisitingOperation for
@@ -953,12 +915,11 @@ impl<'a,'b> ast_util::IdVisitingOperation for
953915
let ecx: &e::EncodeContext = unsafe {
954916
cast::transmute(self.ecx_ptr)
955917
};
956-
encode_side_tables_for_id(ecx, self.maps, &mut new_ebml_w, id)
918+
encode_side_tables_for_id(ecx, &mut new_ebml_w, id)
957919
}
958920
}
959921

960922
fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
961-
maps: &Maps,
962923
ebml_w: &mut Encoder,
963924
ii: &ast::InlinedItem) {
964925
ebml_w.start_tag(c::tag_table as uint);
@@ -974,13 +935,11 @@ fn encode_side_tables_for_ii(ecx: &e::EncodeContext,
974935
cast::transmute(ecx)
975936
},
976937
new_ebml_w: &mut new_ebml_w,
977-
maps: maps,
978938
});
979939
ebml_w.end_tag();
980940
}
981941

982942
fn encode_side_tables_for_id(ecx: &e::EncodeContext,
983-
maps: &Maps,
984943
ebml_w: &mut Encoder,
985944
id: ast::NodeId) {
986945
let tcx = ecx.tcx;
@@ -1096,17 +1055,6 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
10961055
})
10971056
})
10981057
}
1099-
1100-
for &cap_vars in maps.capture_map.borrow().find(&id).iter() {
1101-
ebml_w.tag(c::tag_table_capture_map, |ebml_w| {
1102-
ebml_w.id(id);
1103-
ebml_w.tag(c::tag_table_val, |ebml_w| {
1104-
ebml_w.emit_from_vec(cap_vars.as_slice(), |ebml_w, cap_var| {
1105-
cap_var.encode(ebml_w)
1106-
});
1107-
})
1108-
})
1109-
}
11101058
}
11111059

11121060
trait doc_decoder_helpers {
@@ -1405,15 +1353,6 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
14051353
let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(xcx);
14061354
dcx.tcx.adjustments.borrow_mut().insert(id, adj);
14071355
}
1408-
c::tag_table_capture_map => {
1409-
let cvars =
1410-
val_dsr.read_to_vec(
1411-
|val_dsr| Ok(val_dsr.read_capture_var(xcx)))
1412-
.unwrap()
1413-
.move_iter()
1414-
.collect();
1415-
dcx.maps.capture_map.borrow_mut().insert(id, Rc::new(cvars));
1416-
}
14171356
_ => {
14181357
xcx.dcx.tcx.sess.bug(
14191358
format!("unknown tag found in side tables: {:x}", tag));

src/librustc/middle/borrowck/check_loans.rs

+25-16
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@
1818
// 4. moves do not affect things loaned out in any way
1919

2020

21-
use mc = middle::mem_categorization;
2221
use middle::borrowck::*;
23-
use middle::moves;
22+
use euv = middle::expr_use_visitor;
23+
use middle::freevars;
24+
use mc = middle::mem_categorization;
2425
use middle::ty;
2526
use middle::typeck::MethodCall;
2627
use syntax::ast;
@@ -288,7 +289,7 @@ impl<'a> CheckLoanCtxt<'a> {
288289
}
289290

290291
match new_loan.cause {
291-
ClosureCapture(span) => {
292+
euv::ClosureCapture(span) => {
292293
self.bccx.span_note(
293294
span,
294295
format!("borrow occurs due to use of `{}` in closure",
@@ -321,13 +322,17 @@ impl<'a> CheckLoanCtxt<'a> {
321322
};
322323

323324
let borrow_summary = match old_loan.cause {
324-
ClosureCapture(_) => {
325+
euv::ClosureCapture(_) => {
325326
format!("previous borrow of `{}` occurs here due to \
326327
use in closure",
327328
self.bccx.loan_path_to_str(&*old_loan.loan_path))
328329
}
329330

330-
AddrOf | AutoRef | RefBinding | ClosureInvocation => {
331+
euv::OverloadedOperator(..) |
332+
euv::AddrOf(..) |
333+
euv::AutoRef(..) |
334+
euv::ClosureInvocation(..) |
335+
euv::RefBinding(..) => {
331336
format!("previous borrow of `{}` occurs here",
332337
self.bccx.loan_path_to_str(&*old_loan.loan_path))
333338
}
@@ -711,29 +716,33 @@ impl<'a> CheckLoanCtxt<'a> {
711716
fn check_captured_variables(&self,
712717
closure_id: ast::NodeId,
713718
span: Span) {
714-
for cap_var in self.bccx.capture_map.get(&closure_id).iter() {
715-
let var_id = ast_util::def_id_of_def(cap_var.def).node;
716-
self.check_if_path_is_moved(closure_id, span,
717-
MovedInCapture, &Rc::new(LpVar(var_id)));
718-
match cap_var.mode {
719-
moves::CapRef | moves::CapCopy => {}
720-
moves::CapMove => {
721-
check_by_move_capture(self, closure_id, cap_var, &LpVar(var_id));
719+
let freevar_mode = freevars::get_capture_mode(self.tcx(), closure_id);
720+
freevars::with_freevars(self.tcx(), closure_id, |freevars| {
721+
for freevar in freevars.iter() {
722+
let var_id = ast_util::def_id_of_def(freevar.def).node;
723+
let var_path = Rc::new(LpVar(var_id));
724+
self.check_if_path_is_moved(closure_id, span,
725+
MovedInCapture, &var_path);
726+
match freevar_mode {
727+
freevars::CaptureByRef => { }
728+
freevars::CaptureByValue => {
729+
check_by_move_capture(self, closure_id, freevar, &*var_path);
730+
}
722731
}
723732
}
724-
}
733+
});
725734
return;
726735

727736
fn check_by_move_capture(this: &CheckLoanCtxt,
728737
closure_id: ast::NodeId,
729-
cap_var: &moves::CaptureVar,
738+
freevar: &freevars::freevar_entry,
730739
move_path: &LoanPath) {
731740
let move_err = this.analyze_move_out_from(closure_id, move_path);
732741
match move_err {
733742
MoveOk => {}
734743
MoveWhileBorrowed(loan_path, loan_span) => {
735744
this.bccx.span_err(
736-
cap_var.span,
745+
freevar.span,
737746
format!("cannot move `{}` into closure \
738747
because it is borrowed",
739748
this.bccx.loan_path_to_str(move_path)));

0 commit comments

Comments
 (0)