Auto merge of #33443 - jseyfried:resolve_ast, r=nrc

Perform name resolution before and during ast->hir lowering

This PR performs name resolution before and during ast->hir lowering instead of in phase 3.
r? @nrc
This commit is contained in:
bors 2016-05-09 21:31:55 -07:00
commit a4d2424cc3
20 changed files with 708 additions and 557 deletions

View File

@ -43,7 +43,8 @@
use hir;
use hir::map::Definitions;
use hir::map::definitions::DefPathData;
use hir::def_id::DefIndex;
use hir::def_id::{DefIndex, DefId};
use hir::def::Def;
use std::collections::BTreeMap;
use std::iter;
@ -63,19 +64,40 @@ pub struct LoweringContext<'a> {
crate_root: Option<&'static str>,
// Use to assign ids to hir nodes that do not directly correspond to an ast node
id_assigner: &'a NodeIdAssigner,
// We must keep the set of definitions up to date as we add nodes that
// weren't in the AST.
definitions: Option<&'a RefCell<Definitions>>,
// As we walk the AST we must keep track of the current 'parent' def id (in
// the form of a DefIndex) so that if we create a new node which introduces
// a definition, then we can properly create the def id.
parent_def: Cell<Option<DefIndex>>,
resolver: RefCell<&'a mut Resolver>,
}
pub trait Resolver {
// Resolve a global hir path generated by the lowerer when expanding `for`, `if let`, etc.
fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def;
// Record the resolution of a path or binding generated by the lowerer when expanding.
fn record_resolution(&mut self, id: NodeId, def: Def);
// We must keep the set of definitions up to date as we add nodes that weren't in the AST.
// This should only return `None` during testing.
fn definitions(&mut self) -> Option<&mut Definitions>;
}
pub struct DummyResolver;
impl Resolver for DummyResolver {
fn resolve_generated_global_path(&mut self, _path: &hir::Path, _is_value: bool) -> Def {
Def::Err
}
fn record_resolution(&mut self, _id: NodeId, _def: Def) {}
fn definitions(&mut self) -> Option<&mut Definitions> {
None
}
}
impl<'a, 'hir> LoweringContext<'a> {
pub fn new(id_assigner: &'a NodeIdAssigner,
c: Option<&Crate>,
defs: &'a RefCell<Definitions>)
resolver: &'a mut Resolver)
-> LoweringContext<'a> {
let crate_root = c.and_then(|c| {
if std_inject::no_core(c) {
@ -90,19 +112,8 @@ impl<'a, 'hir> LoweringContext<'a> {
LoweringContext {
crate_root: crate_root,
id_assigner: id_assigner,
definitions: Some(defs),
parent_def: Cell::new(None),
}
}
// Only use this when you want a LoweringContext for testing and won't look
// up def ids for anything created during lowering.
pub fn testing_context(id_assigner: &'a NodeIdAssigner) -> LoweringContext<'a> {
LoweringContext {
crate_root: None,
id_assigner: id_assigner,
definitions: None,
parent_def: Cell::new(None),
resolver: RefCell::new(resolver),
}
}
@ -120,23 +131,17 @@ impl<'a, 'hir> LoweringContext<'a> {
}
fn with_parent_def<T, F: FnOnce() -> T>(&self, parent_id: NodeId, f: F) -> T {
if self.definitions.is_none() {
// This should only be used for testing.
return f();
}
let old_def = self.parent_def.get();
self.parent_def.set(Some(self.get_def(parent_id)));
self.parent_def.set(match self.resolver.borrow_mut().definitions() {
Some(defs) => Some(defs.opt_def_index(parent_id).unwrap()),
None => old_def,
});
let result = f();
self.parent_def.set(old_def);
result
}
fn get_def(&self, id: NodeId) -> DefIndex {
let defs = self.definitions.unwrap().borrow();
defs.opt_def_index(id).unwrap()
}
}
pub fn lower_ident(_lctx: &LoweringContext, ident: Ident) -> hir::Ident {
@ -999,7 +1004,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
};
// let placer = <placer_expr> ;
let s1 = {
let (s1, placer_binding) = {
let placer_expr = signal_block_expr(lctx,
hir_vec![],
placer_expr,
@ -1010,15 +1015,15 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
};
// let mut place = Placer::make_place(placer);
let s2 = {
let placer = expr_ident(lctx, e.span, placer_ident, None);
let (s2, place_binding) = {
let placer = expr_ident(lctx, e.span, placer_ident, None, placer_binding);
let call = make_call(lctx, &make_place, hir_vec![placer]);
mk_stmt_let_mut(lctx, place_ident, call)
};
// let p_ptr = Place::pointer(&mut place);
let s3 = {
let agent = expr_ident(lctx, e.span, place_ident, None);
let (s3, p_ptr_binding) = {
let agent = expr_ident(lctx, e.span, place_ident, None, place_binding);
let args = hir_vec![expr_mut_addr_of(lctx, e.span, agent, None)];
let call = make_call(lctx, &place_pointer, args);
mk_stmt_let(lctx, p_ptr_ident, call)
@ -1044,14 +1049,14 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
// InPlace::finalize(place)
// })
let expr = {
let ptr = expr_ident(lctx, e.span, p_ptr_ident, None);
let ptr = expr_ident(lctx, e.span, p_ptr_ident, None, p_ptr_binding);
let call_move_val_init =
hir::StmtSemi(
make_call(lctx, &move_val_init, hir_vec![ptr, pop_unsafe_expr]),
lctx.next_id());
let call_move_val_init = respan(e.span, call_move_val_init);
let place = expr_ident(lctx, e.span, place_ident, None);
let place = expr_ident(lctx, e.span, place_ident, None, place_binding);
let call = make_call(lctx, &inplace_finalize, hir_vec![place]);
signal_block_expr(lctx,
hir_vec![call_move_val_init],
@ -1438,7 +1443,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
let loop_expr = hir::ExprLoop(loop_block,
opt_ident.map(|ident| lower_ident(lctx, ident)));
// add attributes to the outer returned expr node
return expr(lctx, e.span, loop_expr, e.attrs.clone());
let attrs = e.attrs.clone();
return P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: attrs });
}
// Desugar ExprForLoop
@ -1488,6 +1494,10 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
arm(hir_vec![pat_none(lctx, e.span)], break_expr)
};
// `mut iter`
let iter_pat =
pat_ident_binding_mode(lctx, e.span, iter, hir::BindByValue(hir::MutMutable));
// `match ::std::iter::Iterator::next(&mut iter) { ... }`
let match_expr = {
let next_path = {
@ -1495,7 +1505,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
path_global(e.span, strs)
};
let iter = expr_ident(lctx, e.span, iter, None);
let iter = expr_ident(lctx, e.span, iter, None, iter_pat.id);
let ref_mut_iter = expr_mut_addr_of(lctx, e.span, iter, None);
let next_path = expr_path(lctx, next_path, None);
let next_expr = expr_call(lctx,
@ -1515,16 +1525,11 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
let loop_block = block_expr(lctx, match_expr);
let loop_expr = hir::ExprLoop(loop_block,
opt_ident.map(|ident| lower_ident(lctx, ident)));
let loop_expr = expr(lctx, e.span, loop_expr, None);
let loop_expr =
P(hir::Expr { id: e.id, node: loop_expr, span: e.span, attrs: None });
// `mut iter => { ... }`
let iter_arm = {
let iter_pat = pat_ident_binding_mode(lctx,
e.span,
iter,
hir::BindByValue(hir::MutMutable));
arm(hir_vec![iter_pat], loop_expr)
};
let iter_arm = arm(hir_vec![iter_pat], loop_expr);
// `match ::std::iter::IntoIterator::into_iter(<head>) { ... }`
let into_iter_expr = {
@ -1548,13 +1553,10 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
// `{ let _result = ...; _result }`
// underscore prevents an unused_variables lint if the head diverges
let result_ident = lctx.str_to_ident("_result");
let let_stmt = stmt_let(lctx,
e.span,
false,
result_ident,
match_expr,
None);
let result = expr_ident(lctx, e.span, result_ident, None);
let (let_stmt, let_stmt_binding) =
stmt_let(lctx, e.span, false, result_ident, match_expr, None);
let result = expr_ident(lctx, e.span, result_ident, None, let_stmt_binding);
let block = block_all(lctx, e.span, hir_vec![let_stmt], Some(result));
// add the attributes to the outer returned expr node
return expr_block(lctx, block, e.attrs.clone());
@ -1581,7 +1583,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
let ok_arm = {
let val_ident = lctx.str_to_ident("val");
let val_pat = pat_ident(lctx, e.span, val_ident);
let val_expr = expr_ident(lctx, e.span, val_ident, None);
let val_expr = expr_ident(lctx, e.span, val_ident, None, val_pat.id);
let ok_pat = pat_ok(lctx, e.span, val_pat);
arm(hir_vec![ok_pat], val_expr)
@ -1590,11 +1592,12 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
// Err(err) => return Err(From::from(err))
let err_arm = {
let err_ident = lctx.str_to_ident("err");
let err_local = pat_ident(lctx, e.span, err_ident);
let from_expr = {
let path = std_path(lctx, &["convert", "From", "from"]);
let path = path_global(e.span, path);
let from = expr_path(lctx, path, None);
let err_expr = expr_ident(lctx, e.span, err_ident, None);
let err_expr = expr_ident(lctx, e.span, err_ident, None, err_local.id);
expr_call(lctx, e.span, from, hir_vec![err_expr], None)
};
@ -1604,8 +1607,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
let err_ctor = expr_path(lctx, path, None);
expr_call(lctx, e.span, err_ctor, hir_vec![from_expr], None)
};
let err_pat = pat_err(lctx, e.span,
pat_ident(lctx, e.span, err_ident));
let err_pat = pat_err(lctx, e.span, err_local);
let ret_expr = expr(lctx, e.span,
hir::Expr_::ExprRet(Some(err_expr)), None);
@ -1745,8 +1747,15 @@ fn expr_call(lctx: &LoweringContext,
}
fn expr_ident(lctx: &LoweringContext, span: Span, id: hir::Ident,
attrs: ThinAttributes) -> P<hir::Expr> {
expr_path(lctx, path_ident(span, id), attrs)
attrs: ThinAttributes, binding: NodeId) -> P<hir::Expr> {
let expr = expr(lctx, span, hir::ExprPath(None, path_ident(span, id)), attrs);
let mut resolver = lctx.resolver.borrow_mut();
let def = resolver.definitions().map(|defs| Def::Local(defs.local_def_id(binding), binding))
.unwrap_or(Def::Err);
resolver.record_resolution(expr.id, def);
expr
}
fn expr_mut_addr_of(lctx: &LoweringContext, span: Span, e: P<hir::Expr>,
@ -1756,7 +1765,10 @@ fn expr_mut_addr_of(lctx: &LoweringContext, span: Span, e: P<hir::Expr>,
fn expr_path(lctx: &LoweringContext, path: hir::Path,
attrs: ThinAttributes) -> P<hir::Expr> {
expr(lctx, path.span, hir::ExprPath(None, path), attrs)
let def = lctx.resolver.borrow_mut().resolve_generated_global_path(&path, true);
let expr = expr(lctx, path.span, hir::ExprPath(None, path), attrs);
lctx.resolver.borrow_mut().record_resolution(expr.id, def);
expr
}
fn expr_match(lctx: &LoweringContext,
@ -1785,7 +1797,11 @@ fn expr_struct(lctx: &LoweringContext,
fields: hir::HirVec<hir::Field>,
e: Option<P<hir::Expr>>,
attrs: ThinAttributes) -> P<hir::Expr> {
expr(lctx, sp, hir::ExprStruct(path, fields, e), attrs)
let def = lctx.resolver.borrow_mut().resolve_generated_global_path(&path, false);
let expr = expr(lctx, sp, hir::ExprStruct(path, fields, e), attrs);
lctx.resolver.borrow_mut().record_resolution(expr.id, def);
expr
}
fn expr(lctx: &LoweringContext, span: Span, node: hir::Expr_,
@ -1804,12 +1820,13 @@ fn stmt_let(lctx: &LoweringContext,
ident: hir::Ident,
ex: P<hir::Expr>,
attrs: ThinAttributes)
-> hir::Stmt {
-> (hir::Stmt, NodeId) {
let pat = if mutbl {
pat_ident_binding_mode(lctx, sp, ident, hir::BindByValue(hir::MutMutable))
} else {
pat_ident(lctx, sp, ident)
};
let pat_id = pat.id;
let local = P(hir::Local {
pat: pat,
ty: None,
@ -1819,7 +1836,7 @@ fn stmt_let(lctx: &LoweringContext,
attrs: attrs,
});
let decl = respan(sp, hir::DeclLocal(local));
respan(sp, hir::StmtDecl(P(decl), lctx.next_id()))
(respan(sp, hir::StmtDecl(P(decl), lctx.next_id())), pat_id)
}
fn block_expr(lctx: &LoweringContext, expr: P<hir::Expr>) -> P<hir::Block> {
@ -1869,12 +1886,15 @@ fn pat_enum(lctx: &LoweringContext,
path: hir::Path,
subpats: hir::HirVec<P<hir::Pat>>)
-> P<hir::Pat> {
let def = lctx.resolver.borrow_mut().resolve_generated_global_path(&path, true);
let pt = if subpats.is_empty() {
hir::PatKind::Path(path)
} else {
hir::PatKind::TupleStruct(path, Some(subpats))
};
pat(lctx, span, pt)
let pat = pat(lctx, span, pt);
lctx.resolver.borrow_mut().record_resolution(pat.id, def);
pat
}
fn pat_ident(lctx: &LoweringContext, span: Span, ident: hir::Ident) -> P<hir::Pat> {
@ -1895,12 +1915,13 @@ fn pat_ident_binding_mode(lctx: &LoweringContext,
let pat = pat(lctx, span, pat_ident);
if let Some(defs) = lctx.definitions {
let mut defs = defs.borrow_mut();
defs.create_def_with_parent(lctx.parent_def.get(),
pat.id,
DefPathData::Binding(ident.name));
}
let mut resolver = lctx.resolver.borrow_mut();
let def = resolver.definitions().map(|defs| {
let def_path_data = DefPathData::Binding(ident.name);
let def_index = defs.create_def_with_parent(lctx.parent_def.get(), pat.id, def_path_data);
Def::Local(DefId::local(def_index), pat.id)
}).unwrap_or(Def::Err);
resolver.record_resolution(pat.id, def);
pat
}

View File

@ -195,6 +195,10 @@ impl Definitions {
self.opt_def_index(node).map(DefId::local)
}
pub fn local_def_id(&self, node: ast::NodeId) -> DefId {
self.opt_local_def_id(node).unwrap()
}
pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
if def_id.krate == LOCAL_CRATE {
assert!(def_id.index.as_usize() < self.data.len());

View File

@ -1639,6 +1639,7 @@ pub type FreevarMap = NodeMap<Vec<Freevar>>;
pub type CaptureModeMap = NodeMap<CaptureClause>;
#[derive(Clone)]
pub struct TraitCandidate {
pub def_id: DefId,
pub import_id: Option<NodeId>,

View File

@ -108,6 +108,7 @@ pub type Disr = ConstInt;
/// The complete set of all analyses described in this module. This is
/// produced by the driver and fed to trans and later passes.
#[derive(Clone)]
pub struct CrateAnalysis<'a> {
pub export_map: ExportMap,
pub access_levels: middle::privacy::AccessLevels,

View File

@ -10,7 +10,8 @@
use rustc::dep_graph::DepGraph;
use rustc::hir;
use rustc::hir::map as hir_map;
use rustc::hir::{map as hir_map, FreevarMap, TraitMap};
use rustc::hir::def::DefMap;
use rustc_mir as mir;
use rustc::mir::mir_map::MirMap;
use rustc::session::{Session, CompileResult, compile_result_from_err_count};
@ -60,6 +61,14 @@ use syntax::visit;
use syntax;
use syntax_ext;
#[derive(Clone)]
pub struct Resolutions {
pub def_map: RefCell<DefMap>,
pub freevars: FreevarMap,
pub trait_map: TraitMap,
pub maybe_unused_trait_imports: NodeSet,
}
pub fn compile_input(sess: &Session,
cstore: &CStore,
cfg: ast::CrateConfig,
@ -139,15 +148,17 @@ pub fn compile_input(sess: &Session,
time(sess.time_passes(),
"external crate/lib resolution",
|| LocalCrateReader::new(sess, &cstore, &defs, &expanded_crate, &id)
|| LocalCrateReader::new(sess, &cstore, defs, &expanded_crate, &id)
.read_crates(&dep_graph));
// Lower ast -> hir.
let lcx = LoweringContext::new(sess, Some(&expanded_crate), defs);
let hir_forest = &mut time(sess.time_passes(),
"lowering ast -> hir",
|| hir_map::Forest::new(lower_crate(&lcx, &expanded_crate),
dep_graph));
time(sess.time_passes(),
"early lint checks",
|| lint::check_ast_crate(sess, &expanded_crate));
let (analysis, resolutions, mut hir_forest) = {
let defs = &mut *defs.borrow_mut();
lower_and_resolve(sess, &id, defs, &expanded_crate, dep_graph, control.make_glob_map)
};
// Discard MTWT tables that aren't required past lowering to HIR.
if !keep_mtwt_tables(sess) {
@ -157,6 +168,7 @@ pub fn compile_input(sess: &Session,
let arenas = ty::CtxtArenas::new();
// Construct the HIR map
let hir_forest = &mut hir_forest;
let hir_map = time(sess.time_passes(),
"indexing hir",
move || hir_map::map_crate(hir_forest, defs));
@ -175,6 +187,8 @@ pub fn compile_input(sess: &Session,
&arenas,
&cstore,
&hir_map,
&analysis,
&resolutions,
&expanded_crate,
&hir_map.krate(),
&id),
@ -185,10 +199,6 @@ pub fn compile_input(sess: &Session,
hir::check_attr::check_crate(sess, &expanded_crate);
});
time(sess.time_passes(),
"early lint checks",
|| lint::check_ast_crate(sess, &expanded_crate));
let opt_crate = if keep_ast(sess) {
Some(&expanded_crate)
} else {
@ -198,9 +208,10 @@ pub fn compile_input(sess: &Session,
phase_3_run_analysis_passes(sess,
hir_map,
analysis,
resolutions,
&arenas,
&id,
control.make_glob_map,
|tcx, mir_map, analysis, result| {
{
// Eventually, we will want to track plugins.
@ -353,6 +364,7 @@ pub struct CompileState<'a, 'b, 'ast: 'a, 'tcx: 'b> where 'ast: 'tcx {
pub expanded_crate: Option<&'a ast::Crate>,
pub hir_crate: Option<&'a hir::Crate>,
pub ast_map: Option<&'a hir_map::Map<'ast>>,
pub resolutions: Option<&'a Resolutions>,
pub mir_map: Option<&'b MirMap<'tcx>>,
pub analysis: Option<&'a ty::CrateAnalysis<'a>>,
pub tcx: Option<&'b TyCtxt<'tcx>>,
@ -377,6 +389,7 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
expanded_crate: None,
hir_crate: None,
ast_map: None,
resolutions: None,
analysis: None,
mir_map: None,
tcx: None,
@ -423,6 +436,8 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
arenas: &'ast ty::CtxtArenas<'ast>,
cstore: &'a CStore,
hir_map: &'a hir_map::Map<'ast>,
analysis: &'a ty::CrateAnalysis,
resolutions: &'a Resolutions,
krate: &'a ast::Crate,
hir_crate: &'a hir::Crate,
crate_name: &'a str)
@ -432,6 +447,8 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
arenas: Some(arenas),
cstore: Some(cstore),
ast_map: Some(hir_map),
analysis: Some(analysis),
resolutions: Some(resolutions),
expanded_crate: Some(krate),
hir_crate: Some(hir_crate),
out_file: out_file.as_ref().map(|s| &**s),
@ -756,14 +773,48 @@ pub fn assign_node_ids(sess: &Session, krate: ast::Crate) -> ast::Crate {
krate
}
pub fn lower_and_resolve<'a>(sess: &Session,
id: &'a str,
defs: &mut hir_map::Definitions,
krate: &ast::Crate,
dep_graph: DepGraph,
make_glob_map: resolve::MakeGlobMap)
-> (ty::CrateAnalysis<'a>, Resolutions, hir_map::Forest) {
resolve::with_resolver(sess, defs, make_glob_map, |mut resolver| {
time(sess.time_passes(), "name resolution", || {
resolve::resolve_crate(&mut resolver, krate);
});
// Lower ast -> hir.
let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || {
let lcx = LoweringContext::new(sess, Some(krate), &mut resolver);
hir_map::Forest::new(lower_crate(&lcx, krate), dep_graph)
});
(ty::CrateAnalysis {
export_map: resolver.export_map,
access_levels: AccessLevels::default(),
reachable: NodeSet(),
name: &id,
glob_map: if resolver.make_glob_map { Some(resolver.glob_map) } else { None },
}, Resolutions {
def_map: RefCell::new(resolver.def_map),
freevars: resolver.freevars,
trait_map: resolver.trait_map,
maybe_unused_trait_imports: resolver.maybe_unused_trait_imports,
}, hir_forest)
})
}
/// Run the resolution, typechecking, region checking and other
/// miscellaneous analysis passes on the crate. Return various
/// structures carrying the results of the analysis.
pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
hir_map: hir_map::Map<'tcx>,
mut analysis: ty::CrateAnalysis,
resolutions: Resolutions,
arenas: &'tcx ty::CtxtArenas<'tcx>,
name: &str,
make_glob_map: resolve::MakeGlobMap,
f: F)
-> Result<R, usize>
where F: FnOnce(&TyCtxt<'tcx>, Option<MirMap<'tcx>>, ty::CrateAnalysis, CompileResult) -> R
@ -788,30 +839,11 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
})
})?;
let resolve::CrateMap {
def_map,
freevars,
maybe_unused_trait_imports,
export_map,
trait_map,
glob_map,
} = time(sess.time_passes(),
"name resolution",
|| resolve::resolve_crate(sess, &hir_map, make_glob_map));
let mut analysis = ty::CrateAnalysis {
export_map: export_map,
access_levels: AccessLevels::default(),
reachable: NodeSet(),
name: name,
glob_map: glob_map,
};
let named_region_map = time(time_passes,
"lifetime resolution",
|| middle::resolve_lifetime::krate(sess,
&hir_map,
&def_map.borrow()))?;
&resolutions.def_map.borrow()))?;
time(time_passes,
"looking for entry point",
@ -831,17 +863,18 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
time(time_passes,
"static item recursion checking",
|| static_recursion::check_crate(sess, &def_map.borrow(), &hir_map))?;
|| static_recursion::check_crate(sess, &resolutions.def_map.borrow(), &hir_map))?;
let index = stability::Index::new(&hir_map);
let trait_map = resolutions.trait_map;
TyCtxt::create_and_enter(sess,
arenas,
def_map,
resolutions.def_map,
named_region_map,
hir_map,
freevars,
maybe_unused_trait_imports,
resolutions.freevars,
resolutions.maybe_unused_trait_imports,
region_map,
lang_items,
index,

View File

@ -469,6 +469,8 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
control.after_write_deps.callback = box move |state| {
pretty::print_after_write_deps(state.session,
state.ast_map.unwrap(),
state.analysis.unwrap(),
state.resolutions.unwrap(),
state.input,
&state.expanded_crate.take().unwrap(),
state.crate_name.unwrap(),

View File

@ -15,7 +15,8 @@ pub use self::PpSourceMode::*;
pub use self::PpMode::*;
use self::NodesMatchingUII::*;
use {driver, abort_on_err};
use abort_on_err;
use driver::{self, Resolutions};
use rustc::dep_graph::DepGraph;
use rustc::ty::{self, TyCtxt};
@ -25,7 +26,6 @@ use rustc::session::Session;
use rustc::session::config::Input;
use rustc_borrowck as borrowck;
use rustc_borrowck::graphviz as borrowck_dot;
use rustc_resolve as resolve;
use rustc_mir::pretty::write_mir_pretty;
use rustc_mir::graphviz::write_mir_graphviz;
@ -202,6 +202,8 @@ impl PpSourceMode {
fn call_with_pp_support_hir<'tcx, A, B, F>(&self,
sess: &'tcx Session,
ast_map: &hir_map::Map<'tcx>,
analysis: &ty::CrateAnalysis,
resolutions: &Resolutions,
arenas: &'tcx ty::CtxtArenas<'tcx>,
id: &str,
payload: B,
@ -228,9 +230,10 @@ impl PpSourceMode {
PpmTyped => {
abort_on_err(driver::phase_3_run_analysis_passes(sess,
ast_map.clone(),
analysis.clone(),
resolutions.clone(),
arenas,
id,
resolve::MakeGlobMap::No,
|tcx, _, _, _| {
let annotation = TypedAnnotation {
tcx: tcx,
@ -811,6 +814,8 @@ pub fn print_after_parsing(sess: &Session,
pub fn print_after_write_deps<'tcx, 'a: 'tcx>(sess: &'a Session,
ast_map: &hir_map::Map<'tcx>,
analysis: &ty::CrateAnalysis,
resolutions: &Resolutions,
input: &Input,
krate: &ast::Crate,
crate_name: &str,
@ -822,7 +827,8 @@ pub fn print_after_write_deps<'tcx, 'a: 'tcx>(sess: &'a Session,
let _ignore = dep_graph.in_ignore();
if ppm.needs_analysis() {
print_with_analysis(sess, ast_map, crate_name, arenas, ppm, opt_uii, ofile);
print_with_analysis(sess, ast_map, analysis, resolutions,
crate_name, arenas, ppm, opt_uii, ofile);
return;
}
@ -853,6 +859,8 @@ pub fn print_after_write_deps<'tcx, 'a: 'tcx>(sess: &'a Session,
let out: &mut Write = &mut out;
s.call_with_pp_support_hir(sess,
ast_map,
analysis,
resolutions,
arenas,
crate_name,
box out,
@ -874,6 +882,8 @@ pub fn print_after_write_deps<'tcx, 'a: 'tcx>(sess: &'a Session,
let out: &mut Write = &mut out;
s.call_with_pp_support_hir(sess,
ast_map,
analysis,
resolutions,
arenas,
crate_name,
(out,uii),
@ -914,6 +924,8 @@ pub fn print_after_write_deps<'tcx, 'a: 'tcx>(sess: &'a Session,
// Instead, we call that function ourselves.
fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
ast_map: &hir_map::Map<'tcx>,
analysis: &ty::CrateAnalysis,
resolutions: &Resolutions,
crate_name: &str,
arenas: &'tcx ty::CtxtArenas<'tcx>,
ppm: PpMode,
@ -931,9 +943,10 @@ fn print_with_analysis<'tcx, 'a: 'tcx>(sess: &'a Session,
abort_on_err(driver::phase_3_run_analysis_passes(sess,
ast_map.clone(),
analysis.clone(),
resolutions.clone(),
arenas,
crate_name,
resolve::MakeGlobMap::No,
|tcx, mir_map, _, _| {
match ppm {
PpmMir | PpmMirCFG => {

View File

@ -13,7 +13,7 @@
use driver;
use rustc::dep_graph::DepGraph;
use rustc_lint;
use rustc_resolve as resolve;
use rustc_resolve::MakeGlobMap;
use rustc::middle::lang_items;
use rustc::middle::free_region::FreeRegionMap;
use rustc::middle::region::{self, CodeExtent};
@ -40,7 +40,6 @@ use syntax::errors::{Level, RenderSpan};
use syntax::parse::token;
use syntax::feature_gate::UnstableFeatures;
use rustc::hir::lowering::{lower_crate, LoweringContext};
use rustc::hir;
struct Env<'a, 'tcx: 'a> {
@ -123,26 +122,28 @@ fn test_env<F>(source_string: &str,
let krate = driver::assign_node_ids(&sess, krate);
let defs = &RefCell::new(hir_map::collect_definitions(&krate));
LocalCrateReader::new(&sess, &cstore, defs, &krate, "test_crate").read_crates(&dep_graph);
let lcx = LoweringContext::new(&sess, Some(&krate), defs);
let _ignore = dep_graph.in_ignore();
let mut hir_forest = &mut hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph.clone());
let (_, resolutions, mut hir_forest) = {
let (defs, dep_graph) = (&mut *defs.borrow_mut(), dep_graph.clone());
driver::lower_and_resolve(&sess, "test-crate", defs, &krate, dep_graph, MakeGlobMap::No)
};
let arenas = ty::CtxtArenas::new();
let ast_map = hir_map::map_crate(hir_forest, defs);
let ast_map = hir_map::map_crate(&mut hir_forest, defs);
// run just enough stuff to build a tcx:
let lang_items = lang_items::collect_language_items(&sess, &ast_map);
let resolve::CrateMap { def_map, freevars, maybe_unused_trait_imports, .. } =
resolve::resolve_crate(&sess, &ast_map, resolve::MakeGlobMap::No);
let named_region_map = resolve_lifetime::krate(&sess, &ast_map, &def_map.borrow());
let named_region_map = resolve_lifetime::krate(&sess, &ast_map, &resolutions.def_map.borrow());
let region_map = region::resolve_crate(&sess, &ast_map);
let index = stability::Index::new(&ast_map);
TyCtxt::create_and_enter(&sess,
&arenas,
def_map,
resolutions.def_map,
named_region_map.unwrap(),
ast_map,
freevars,
maybe_unused_trait_imports,
resolutions.freevars,
resolutions.maybe_unused_trait_imports,
region_map,
lang_items,
index,

View File

@ -57,7 +57,7 @@ use rustc_serialize::{Encodable, EncoderHelpers};
#[cfg(test)] use syntax::parse;
#[cfg(test)] use syntax::ast::NodeId;
#[cfg(test)] use rustc::hir::print as pprust;
#[cfg(test)] use rustc::hir::lowering::{lower_item, LoweringContext};
#[cfg(test)] use rustc::hir::lowering::{lower_item, LoweringContext, DummyResolver};
struct DecodeContext<'a, 'b, 'tcx: 'a> {
tcx: &'a TyCtxt<'tcx>,
@ -1325,6 +1325,14 @@ fn mk_ctxt() -> parse::ParseSess {
parse::ParseSess::new()
}
#[cfg(test)]
fn with_testing_context<T, F: FnOnce(LoweringContext) -> T>(f: F) -> T {
let assigner = FakeNodeIdAssigner;
let mut resolver = DummyResolver;
let lcx = LoweringContext::new(&assigner, None, &mut resolver);
f(lcx)
}
#[cfg(test)]
fn roundtrip(in_item: hir::Item) {
let mut wr = Cursor::new(Vec::new());
@ -1338,34 +1346,34 @@ fn roundtrip(in_item: hir::Item) {
#[test]
fn test_basic() {
let cx = mk_ctxt();
let fnia = FakeNodeIdAssigner;
let lcx = LoweringContext::testing_context(&fnia);
roundtrip(lower_item(&lcx, &quote_item!(&cx,
fn foo() {}
).unwrap()));
with_testing_context(|lcx| {
roundtrip(lower_item(&lcx, &quote_item!(&cx,
fn foo() {}
).unwrap()));
});
}
#[test]
fn test_smalltalk() {
let cx = mk_ctxt();
let fnia = FakeNodeIdAssigner;
let lcx = LoweringContext::testing_context(&fnia);
roundtrip(lower_item(&lcx, &quote_item!(&cx,
fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed.
).unwrap()));
with_testing_context(|lcx| {
roundtrip(lower_item(&lcx, &quote_item!(&cx,
fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed.
).unwrap()));
});
}
#[test]
fn test_more() {
let cx = mk_ctxt();
let fnia = FakeNodeIdAssigner;
let lcx = LoweringContext::testing_context(&fnia);
roundtrip(lower_item(&lcx, &quote_item!(&cx,
fn foo(x: usize, y: usize) -> usize {
let z = x + y;
return z;
}
).unwrap()));
with_testing_context(|lcx| {
roundtrip(lower_item(&lcx, &quote_item!(&cx,
fn foo(x: usize, y: usize) -> usize {
let z = x + y;
return z;
}
).unwrap()));
});
}
#[test]
@ -1377,21 +1385,22 @@ fn test_simplification() {
return alist {eq_fn: eq_int, data: Vec::new()};
}
).unwrap();
let fnia = FakeNodeIdAssigner;
let lcx = LoweringContext::testing_context(&fnia);
let hir_item = lower_item(&lcx, &item);
let item_in = InlinedItemRef::Item(&hir_item);
let item_out = simplify_ast(item_in);
let item_exp = InlinedItem::Item(P(lower_item(&lcx, &quote_item!(&cx,
fn new_int_alist<B>() -> alist<isize, B> {
return alist {eq_fn: eq_int, data: Vec::new()};
let cx = mk_ctxt();
with_testing_context(|lcx| {
let hir_item = lower_item(&lcx, &item);
let item_in = InlinedItemRef::Item(&hir_item);
let item_out = simplify_ast(item_in);
let item_exp = InlinedItem::Item(P(lower_item(&lcx, &quote_item!(&cx,
fn new_int_alist<B>() -> alist<isize, B> {
return alist {eq_fn: eq_int, data: Vec::new()};
}
).unwrap())));
match (item_out, item_exp) {
(InlinedItem::Item(item_out), InlinedItem::Item(item_exp)) => {
assert!(pprust::item_to_string(&item_out) ==
pprust::item_to_string(&item_exp));
}
_ => bug!()
}
).unwrap())));
match (item_out, item_exp) {
(InlinedItem::Item(item_out), InlinedItem::Item(item_exp)) => {
assert!(pprust::item_to_string(&item_out) ==
pprust::item_to_string(&item_exp));
}
_ => bug!()
}
});
}

View File

@ -29,18 +29,15 @@ use rustc::ty::{self, VariantKind};
use syntax::ast::{Name, NodeId};
use syntax::attr::AttrMetaMethods;
use syntax::parse::token::keywords;
use syntax::parse::token::{self, keywords};
use syntax::codemap::{Span, DUMMY_SP};
use rustc::hir;
use rustc::hir::{Block, DeclItem};
use rustc::hir::{ForeignItem, ForeignItemFn, ForeignItemStatic};
use rustc::hir::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
use rustc::hir::{ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl};
use rustc::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse};
use rustc::hir::{PathListIdent, PathListMod, StmtDecl};
use rustc::hir::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
use rustc::hir::intravisit::{self, Visitor};
use syntax::ast::{Block, Crate, DeclKind};
use syntax::ast::{ForeignItem, ForeignItemKind, Item, ItemKind};
use syntax::ast::{Mutability, PathListItemKind};
use syntax::ast::{SelfKind, Stmt, StmtKind, TraitItemKind};
use syntax::ast::{Variant, ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
use syntax::visit::{self, Visitor};
trait ToNameBinding<'a> {
fn to_name_binding(self) -> NameBinding<'a>;
@ -58,14 +55,14 @@ impl<'a> ToNameBinding<'a> for (Def, Span, ty::Visibility) {
}
}
impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
impl<'b> Resolver<'b> {
/// Constructs the reduced graph for the entire crate.
pub fn build_reduced_graph(&mut self, krate: &hir::Crate) {
pub fn build_reduced_graph(&mut self, krate: &Crate) {
let mut visitor = BuildReducedGraphVisitor {
parent: self.graph_root,
resolver: self,
};
intravisit::walk_crate(&mut visitor, krate);
visit::walk_crate(&mut visitor, krate);
}
/// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined.
@ -85,9 +82,9 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
fn block_needs_anonymous_module(&mut self, block: &Block) -> bool {
fn is_item(statement: &hir::Stmt) -> bool {
if let StmtDecl(ref declaration, _) = statement.node {
if let DeclItem(_) = declaration.node {
fn is_item(statement: &Stmt) -> bool {
if let StmtKind::Decl(ref declaration, _) = statement.node {
if let DeclKind::Item(_) = declaration.node {
return true;
}
}
@ -98,7 +95,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
block.stmts.iter().any(is_item)
}
fn sanity_check_import(&self, view_path: &hir::ViewPath, id: NodeId) {
fn sanity_check_import(&self, view_path: &ViewPath, id: NodeId) {
let path = match view_path.node {
ViewPathSimple(_, ref path) |
ViewPathGlob (ref path) |
@ -131,13 +128,13 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
/// Constructs the reduced graph for one item.
fn build_reduced_graph_for_item(&mut self, item: &Item, parent_ref: &mut Module<'b>) {
let parent = *parent_ref;
let name = item.name;
let name = item.ident.name;
let sp = item.span;
self.current_module = parent;
let vis = self.resolve_visibility(&item.vis);
match item.node {
ItemUse(ref view_path) => {
ItemKind::Use(ref view_path) => {
// Extract and intern the module part of the path. For
// globs and lists, the path is found directly in the AST;
// for simple paths we have to munge the path a little.
@ -175,21 +172,20 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
ResolutionError::SelfImportsOnlyAllowedWithin);
}
let subclass = ImportDirectiveSubclass::single(binding, source_name);
let subclass = ImportDirectiveSubclass::single(binding.name, source_name);
let span = view_path.span;
parent.add_import_directive(module_path, subclass, span, item.id, vis);
self.unresolved_imports += 1;
}
ViewPathList(_, ref source_items) => {
// Make sure there's at most one `mod` import in the list.
let mod_spans = source_items.iter()
.filter_map(|item| {
match item.node {
PathListMod { .. } => Some(item.span),
_ => None,
}
})
.collect::<Vec<Span>>();
let mod_spans = source_items.iter().filter_map(|item| {
match item.node {
PathListItemKind::Mod { .. } => Some(item.span),
_ => None,
}
}).collect::<Vec<Span>>();
if mod_spans.len() > 1 {
let mut e = resolve_struct_error(self,
mod_spans[0],
@ -202,9 +198,9 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
for source_item in source_items {
let (module_path, name, rename) = match source_item.node {
PathListIdent { name, rename, .. } =>
(module_path.clone(), name, rename.unwrap_or(name)),
PathListMod { rename, .. } => {
PathListItemKind::Ident { name, rename, .. } =>
(module_path.clone(), name.name, rename.unwrap_or(name).name),
PathListItemKind::Mod { rename, .. } => {
let name = match module_path.last() {
Some(name) => *name,
None => {
@ -218,7 +214,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
};
let module_path = module_path.split_last().unwrap().1;
let rename = rename.unwrap_or(name);
let rename = rename.map(|i| i.name).unwrap_or(name);
(module_path.to_vec(), name, rename)
}
};
@ -237,7 +233,7 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
}
ItemExternCrate(_) => {
ItemKind::ExternCrate(_) => {
// n.b. we don't need to look at the path option here, because cstore already
// did
if let Some(crate_id) = self.session.cstore.extern_mod_stmt_cnum(item.id) {
@ -254,76 +250,77 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
}
ItemMod(..) => {
ItemKind::Mod(..) => {
let parent_link = ModuleParentLink(parent, name);
let def = Def::Mod(self.ast_map.local_def_id(item.id));
let def = Def::Mod(self.definitions.local_def_id(item.id));
let module = self.new_module(parent_link, Some(def), false);
self.define(parent, name, TypeNS, (module, sp, vis));
self.module_map.insert(item.id, module);
*parent_ref = module;
}
ItemForeignMod(..) => {}
ItemKind::ForeignMod(..) => {}
// These items live in the value namespace.
ItemStatic(_, m, _) => {
let mutbl = m == hir::MutMutable;
let def = Def::Static(self.ast_map.local_def_id(item.id), mutbl);
ItemKind::Static(_, m, _) => {
let mutbl = m == Mutability::Mutable;
let def = Def::Static(self.definitions.local_def_id(item.id), mutbl);
self.define(parent, name, ValueNS, (def, sp, vis));
}
ItemConst(_, _) => {
let def = Def::Const(self.ast_map.local_def_id(item.id));
ItemKind::Const(_, _) => {
let def = Def::Const(self.definitions.local_def_id(item.id));
self.define(parent, name, ValueNS, (def, sp, vis));
}
ItemFn(_, _, _, _, _, _) => {
let def = Def::Fn(self.ast_map.local_def_id(item.id));
ItemKind::Fn(_, _, _, _, _, _) => {
let def = Def::Fn(self.definitions.local_def_id(item.id));
self.define(parent, name, ValueNS, (def, sp, vis));
}
// These items live in the type namespace.
ItemTy(..) => {
let def = Def::TyAlias(self.ast_map.local_def_id(item.id));
ItemKind::Ty(..) => {
let def = Def::TyAlias(self.definitions.local_def_id(item.id));
self.define(parent, name, TypeNS, (def, sp, vis));
}
ItemEnum(ref enum_definition, _) => {
ItemKind::Enum(ref enum_definition, _) => {
let parent_link = ModuleParentLink(parent, name);
let def = Def::Enum(self.ast_map.local_def_id(item.id));
let def = Def::Enum(self.definitions.local_def_id(item.id));
let module = self.new_module(parent_link, Some(def), false);
self.define(parent, name, TypeNS, (module, sp, vis));
for variant in &(*enum_definition).variants {
let item_def_id = self.ast_map.local_def_id(item.id);
let item_def_id = self.definitions.local_def_id(item.id);
self.build_reduced_graph_for_variant(variant, item_def_id, module, vis);
}
}
// These items live in both the type and value namespaces.
ItemStruct(ref struct_def, _) => {
ItemKind::Struct(ref struct_def, _) => {
// Define a name in the type namespace.
let def = Def::Struct(self.ast_map.local_def_id(item.id));
let def = Def::Struct(self.definitions.local_def_id(item.id));
self.define(parent, name, TypeNS, (def, sp, vis));
// If this is a newtype or unit-like struct, define a name
// in the value namespace as well
if !struct_def.is_struct() {
let def = Def::Struct(self.ast_map.local_def_id(struct_def.id()));
let def = Def::Struct(self.definitions.local_def_id(struct_def.id()));
self.define(parent, name, ValueNS, (def, sp, vis));
}
// Record the def ID and fields of this struct.
let field_names = struct_def.fields().iter().map(|field| {
let field_names = struct_def.fields().iter().enumerate().map(|(index, field)| {
self.resolve_visibility(&field.vis);
field.name
field.ident.map(|ident| ident.name)
.unwrap_or_else(|| token::intern(&index.to_string()))
}).collect();
let item_def_id = self.ast_map.local_def_id(item.id);
let item_def_id = self.definitions.local_def_id(item.id);
self.structs.insert(item_def_id, field_names);
}
ItemDefaultImpl(_, _) | ItemImpl(..) => {}
ItemKind::DefaultImpl(_, _) | ItemKind::Impl(..) => {}
ItemTrait(_, _, _, ref items) => {
let def_id = self.ast_map.local_def_id(item.id);
ItemKind::Trait(_, _, _, ref items) => {
let def_id = self.definitions.local_def_id(item.id);
// Add all the items within to a new module.
let parent_link = ModuleParentLink(parent, name);
@ -333,22 +330,23 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
// Add the names of all the items to the trait info.
for item in items {
let item_def_id = self.ast_map.local_def_id(item.id);
let item_def_id = self.definitions.local_def_id(item.id);
let mut is_static_method = false;
let (def, ns) = match item.node {
hir::ConstTraitItem(..) => (Def::AssociatedConst(item_def_id), ValueNS),
hir::MethodTraitItem(ref sig, _) => {
is_static_method = sig.explicit_self.node == hir::SelfStatic;
TraitItemKind::Const(..) => (Def::AssociatedConst(item_def_id), ValueNS),
TraitItemKind::Method(ref sig, _) => {
is_static_method = sig.explicit_self.node == SelfKind::Static;
(Def::Method(item_def_id), ValueNS)
}
hir::TypeTraitItem(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
TraitItemKind::Type(..) => (Def::AssociatedTy(def_id, item_def_id), TypeNS),
};
self.define(module_parent, item.name, ns, (def, item.span, vis));
self.define(module_parent, item.ident.name, ns, (def, item.span, vis));
self.trait_item_map.insert((item.name, def_id), is_static_method);
self.trait_item_map.insert((item.ident.name, def_id), is_static_method);
}
}
ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"),
}
}
@ -359,16 +357,16 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
item_id: DefId,
parent: Module<'b>,
vis: ty::Visibility) {
let name = variant.node.name;
let name = variant.node.name.name;
if variant.node.data.is_struct() {
// Not adding fields for variants as they are not accessed with a self receiver
let variant_def_id = self.ast_map.local_def_id(variant.node.data.id());
let variant_def_id = self.definitions.local_def_id(variant.node.data.id());
self.structs.insert(variant_def_id, Vec::new());
}
// Variants are always treated as importable to allow them to be glob used.
// All variants are defined in both type and value namespaces as future-proofing.
let def = Def::Variant(item_id, self.ast_map.local_def_id(variant.node.data.id()));
let def = Def::Variant(item_id, self.definitions.local_def_id(variant.node.data.id()));
self.define(parent, name, ValueNS, (def, variant.span, vis));
self.define(parent, name, TypeNS, (def, variant.span, vis));
}
@ -377,14 +375,14 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
fn build_reduced_graph_for_foreign_item(&mut self,
foreign_item: &ForeignItem,
parent: Module<'b>) {
let name = foreign_item.name;
let name = foreign_item.ident.name;
let def = match foreign_item.node {
ForeignItemFn(..) => {
Def::Fn(self.ast_map.local_def_id(foreign_item.id))
ForeignItemKind::Fn(..) => {
Def::Fn(self.definitions.local_def_id(foreign_item.id))
}
ForeignItemStatic(_, m) => {
Def::Static(self.ast_map.local_def_id(foreign_item.id), m)
ForeignItemKind::Static(_, m) => {
Def::Static(self.definitions.local_def_id(foreign_item.id), m)
}
};
self.current_module = parent;
@ -526,20 +524,16 @@ impl<'b, 'tcx:'b> Resolver<'b, 'tcx> {
}
}
struct BuildReducedGraphVisitor<'a, 'b: 'a, 'tcx: 'b> {
resolver: &'a mut Resolver<'b, 'tcx>,
struct BuildReducedGraphVisitor<'a, 'b: 'a> {
resolver: &'a mut Resolver<'b>,
parent: Module<'b>,
}
impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
fn visit_nested_item(&mut self, item: hir::ItemId) {
self.visit_item(self.resolver.ast_map.expect_item(item.id))
}
impl<'a, 'b, 'v> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b> {
fn visit_item(&mut self, item: &Item) {
let old_parent = self.parent;
self.resolver.build_reduced_graph_for_item(item, &mut self.parent);
intravisit::walk_item(self, item);
visit::walk_item(self, item);
self.parent = old_parent;
}
@ -550,7 +544,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
fn visit_block(&mut self, block: &Block) {
let old_parent = self.parent;
self.resolver.build_reduced_graph_for_block(block, &mut self.parent);
intravisit::walk_block(self, block);
visit::walk_block(self, block);
self.parent = old_parent;
}
}

View File

@ -25,33 +25,31 @@ use Resolver;
use Namespace::{TypeNS, ValueNS};
use rustc::lint;
use syntax::ast;
use syntax::ast::{self, ViewPathGlob, ViewPathList, ViewPathSimple};
use syntax::visit::{self, Visitor};
use syntax::codemap::{Span, DUMMY_SP};
use rustc::hir;
use rustc::hir::{ViewPathGlob, ViewPathList, ViewPathSimple};
use rustc::hir::intravisit::Visitor;
struct UnusedImportCheckVisitor<'a, 'b: 'a, 'tcx: 'b> {
resolver: &'a mut Resolver<'b, 'tcx>,
struct UnusedImportCheckVisitor<'a, 'b: 'a> {
resolver: &'a mut Resolver<'b>,
}
// Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver.
impl<'a, 'b, 'tcx:'b> Deref for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
type Target = Resolver<'b, 'tcx>;
impl<'a, 'b> Deref for UnusedImportCheckVisitor<'a, 'b> {
type Target = Resolver<'b>;
fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> {
fn deref<'c>(&'c self) -> &'c Resolver<'b> {
&*self.resolver
}
}
impl<'a, 'b, 'tcx:'b> DerefMut for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> {
impl<'a, 'b> DerefMut for UnusedImportCheckVisitor<'a, 'b> {
fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> {
&mut *self.resolver
}
}
impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> {
// We have information about whether `use` (import) directives are actually
// used now. If an import is not used at all, we signal a lint error.
fn check_import(&mut self, id: ast::NodeId, span: Span) {
@ -73,18 +71,19 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
}
}
impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
fn visit_item(&mut self, item: &hir::Item) {
impl<'a, 'b, 'v> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b> {
fn visit_item(&mut self, item: &ast::Item) {
visit::walk_item(self, item);
// Ignore is_public import statements because there's no way to be sure
// whether they're used or not. Also ignore imports with a dummy span
// because this means that they were generated in some fashion by the
// compiler and we don't need to consider them.
if item.vis == hir::Public || item.span.source_equal(&DUMMY_SP) {
if item.vis == ast::Visibility::Public || item.span.source_equal(&DUMMY_SP) {
return;
}
match item.node {
hir::ItemExternCrate(_) => {
ast::ItemKind::ExternCrate(_) => {
if let Some(crate_num) = self.session.cstore.extern_mod_stmt_cnum(item.id) {
if !self.used_crates.contains(&crate_num) {
self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES,
@ -94,7 +93,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
}
}
}
hir::ItemUse(ref p) => {
ast::ItemKind::Use(ref p) => {
match p.node {
ViewPathSimple(_, _) => {
self.check_import(item.id, p.span)
@ -115,7 +114,7 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
}
}
pub fn check_crate(resolver: &mut Resolver, krate: &hir::Crate) {
pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) {
let mut visitor = UnusedImportCheckVisitor { resolver: resolver };
krate.visit_all_items(&mut visitor);
visit::walk_crate(&mut visitor, krate);
}

File diff suppressed because it is too large Load Diff

View File

@ -344,11 +344,11 @@ struct ImportResolvingError<'a> {
help: String,
}
struct ImportResolver<'a, 'b: 'a, 'tcx: 'b> {
resolver: &'a mut Resolver<'b, 'tcx>,
struct ImportResolver<'a, 'b: 'a> {
resolver: &'a mut Resolver<'b>,
}
impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
impl<'a, 'b:'a> ImportResolver<'a, 'b> {
// Import resolution
//
// This is a fixed-point algorithm. We resolve imports until our efforts
@ -608,7 +608,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
None => value_result.success().and_then(NameBinding::def).unwrap(),
};
let path_resolution = PathResolution { base_def: def, depth: 0 };
self.resolver.def_map.borrow_mut().insert(directive.id, path_resolution);
self.resolver.def_map.insert(directive.id, path_resolution);
debug!("(resolving single import) successfully resolved import");
return Success(());
@ -653,11 +653,8 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
// Record the destination of this import
if let Some(did) = target_module.def_id() {
self.resolver.def_map.borrow_mut().insert(directive.id,
PathResolution {
base_def: Def::Mod(did),
depth: 0,
});
let resolution = PathResolution { base_def: Def::Mod(did), depth: 0 };
self.resolver.def_map.insert(directive.id, resolution);
}
debug!("(resolving glob import) successfully resolved import");
@ -703,7 +700,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
if reexports.len() > 0 {
if let Some(def_id) = module.def_id() {
let node_id = self.resolver.ast_map.as_local_node_id(def_id).unwrap();
let node_id = self.resolver.definitions.as_local_node_id(def_id).unwrap();
self.resolver.export_map.insert(node_id, reexports);
}
}

View File

@ -20,7 +20,6 @@ use rustc::hir::map as hir_map;
use rustc::lint;
use rustc_trans::back::link;
use rustc_resolve as resolve;
use rustc::hir::lowering::{lower_crate, LoweringContext};
use rustc_metadata::cstore::CStore;
use rustc_metadata::creader::LocalCrateReader;
@ -156,18 +155,22 @@ pub fn run_core(search_paths: SearchPaths,
let defs = &RefCell::new(hir_map::collect_definitions(&krate));
LocalCrateReader::new(&sess, &cstore, &defs, &krate, &name).read_crates(&dep_graph);
let lcx = LoweringContext::new(&sess, Some(&krate), defs);
// Lower ast -> hir.
let mut hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate), dep_graph);
// Lower ast -> hir and resolve.
let (analysis, resolutions, mut hir_forest) = {
let defs = &mut *defs.borrow_mut();
driver::lower_and_resolve(&sess, &name, defs, &krate, dep_graph, resolve::MakeGlobMap::No)
};
let arenas = ty::CtxtArenas::new();
let hir_map = hir_map::map_crate(&mut hir_forest, defs);
abort_on_err(driver::phase_3_run_analysis_passes(&sess,
hir_map,
analysis,
resolutions,
&arenas,
&name,
resolve::MakeGlobMap::No,
|tcx, _, analysis, result| {
// Return if the driver hit an err (in `result`)
if let Err(_) = result {

View File

@ -28,7 +28,7 @@ use rustc::hir::map as hir_map;
use rustc::session::{self, config};
use rustc::session::config::{get_unstable_features_setting, OutputType};
use rustc::session::search_paths::{SearchPaths, PathKind};
use rustc::hir::lowering::{lower_crate, LoweringContext};
use rustc::hir::lowering::{lower_crate, LoweringContext, DummyResolver};
use rustc_back::dynamic_lib::DynamicLibrary;
use rustc_back::tempdir::TempDir;
use rustc_driver::{driver, Compilation};
@ -97,7 +97,8 @@ pub fn run(input: &str,
let dep_graph = DepGraph::new(false);
let defs = &RefCell::new(hir_map::collect_definitions(&krate));
let lcx = LoweringContext::new(&sess, Some(&krate), defs);
let mut dummy_resolver = DummyResolver;
let lcx = LoweringContext::new(&sess, Some(&krate), &mut dummy_resolver);
let krate = lower_crate(&lcx, &krate);
let opts = scrape_test_config(&krate);

View File

@ -551,6 +551,44 @@ impl fmt::Debug for Pat {
}
}
impl Pat {
pub fn walk<F>(&self, it: &mut F) -> bool
where F: FnMut(&Pat) -> bool
{
if !it(self) {
return false;
}
match self.node {
PatKind::Ident(_, _, Some(ref p)) => p.walk(it),
PatKind::Struct(_, ref fields, _) => {
fields.iter().all(|field| field.node.pat.walk(it))
}
PatKind::TupleStruct(_, Some(ref s)) | PatKind::Tup(ref s) => {
s.iter().all(|p| p.walk(it))
}
PatKind::Box(ref s) | PatKind::Ref(ref s, _) => {
s.walk(it)
}
PatKind::Vec(ref before, ref slice, ref after) => {
before.iter().all(|p| p.walk(it)) &&
slice.iter().all(|p| p.walk(it)) &&
after.iter().all(|p| p.walk(it))
}
PatKind::Wild |
PatKind::Lit(_) |
PatKind::Range(_, _) |
PatKind::Ident(_, _, _) |
PatKind::TupleStruct(..) |
PatKind::Path(..) |
PatKind::QPath(_, _) |
PatKind::Mac(_) => {
true
}
}
}
}
/// A single field in a struct pattern
///
/// Patterns like the fields of Foo `{ x, ref y, ref mut z }`

View File

@ -16,7 +16,6 @@ fn bar(foo: i32) {}
mod submod {
pub static answer: i32 = 42;
//~^ NOTE static variable defined here
}
use self::submod::answer;

View File

@ -34,7 +34,6 @@ use rustc::ty;
use rustc::session::config::{self, basic_options, build_configuration, Input, Options};
use rustc::session::build_session;
use rustc_driver::{driver, abort_on_err};
use rustc::hir::lowering::{lower_crate, LoweringContext};
use rustc_resolve::MakeGlobMap;
use rustc_metadata::creader::LocalCrateReader;
use rustc_metadata::cstore::CStore;
@ -243,14 +242,16 @@ fn compile_program(input: &str, sysroot: PathBuf)
let krate = driver::assign_node_ids(&sess, krate);
let defs = RefCell::new(ast_map::collect_definitions(&krate));
LocalCrateReader::new(&sess, &cstore, &defs, &krate, &id).read_crates(&dep_graph);
let lcx = LoweringContext::new(&sess, Some(&krate), &defs);
let mut hir_forest = ast_map::Forest::new(lower_crate(&lcx, &krate), dep_graph);
let (analysis, resolutions, mut hir_forest) = {
let defs = &mut *defs.borrow_mut();
driver::lower_and_resolve(&sess, &id, defs, &krate, dep_graph, MakeGlobMap::No)
};
let arenas = ty::CtxtArenas::new();
let ast_map = ast_map::map_crate(&mut hir_forest, &defs);
abort_on_err(driver::phase_3_run_analysis_passes(
&sess, ast_map, &arenas, &id,
MakeGlobMap::No, |tcx, mir_map, analysis, _| {
&sess, ast_map, analysis, resolutions, &arenas, &id,
|tcx, mir_map, analysis, _| {
let trans = driver::phase_4_translate_to_llvm(tcx, mir_map.unwrap(), analysis);

View File

@ -14,3 +14,5 @@
fn bar /* 62#0 */() { let x /* 59#2 */ = 1; y /* 61#4 */ + x /* 59#5 */ }
fn y /* 61#0 */() { }

View File

@ -20,3 +20,5 @@ fn bar() {
let x = 1;
foo!(x)
}
fn y() {}