mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-10 14:02:57 +00:00
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:
commit
a4d2424cc3
@ -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
|
||||
}
|
||||
|
@ -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());
|
||||
|
@ -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>,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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(),
|
||||
|
@ -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 => {
|
||||
|
@ -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,
|
||||
|
@ -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, "e_item!(&cx,
|
||||
fn foo() {}
|
||||
).unwrap()));
|
||||
with_testing_context(|lcx| {
|
||||
roundtrip(lower_item(&lcx, "e_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, "e_item!(&cx,
|
||||
fn foo() -> isize { 3 + 4 } // first smalltalk program ever executed.
|
||||
).unwrap()));
|
||||
with_testing_context(|lcx| {
|
||||
roundtrip(lower_item(&lcx, "e_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, "e_item!(&cx,
|
||||
fn foo(x: usize, y: usize) -> usize {
|
||||
let z = x + y;
|
||||
return z;
|
||||
}
|
||||
).unwrap()));
|
||||
with_testing_context(|lcx| {
|
||||
roundtrip(lower_item(&lcx, "e_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, "e_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, "e_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!()
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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 }`
|
||||
|
@ -16,7 +16,6 @@ fn bar(foo: i32) {}
|
||||
|
||||
mod submod {
|
||||
pub static answer: i32 = 42;
|
||||
//~^ NOTE static variable defined here
|
||||
}
|
||||
|
||||
use self::submod::answer;
|
||||
|
@ -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);
|
||||
|
||||
|
@ -14,3 +14,5 @@
|
||||
|
||||
|
||||
fn bar /* 62#0 */() { let x /* 59#2 */ = 1; y /* 61#4 */ + x /* 59#5 */ }
|
||||
|
||||
fn y /* 61#0 */() { }
|
||||
|
@ -20,3 +20,5 @@ fn bar() {
|
||||
let x = 1;
|
||||
foo!(x)
|
||||
}
|
||||
|
||||
fn y() {}
|
||||
|
Loading…
Reference in New Issue
Block a user