Skip to content

Perform name resolution before and during ast->hir lowering #33443

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
May 10, 2016
161 changes: 91 additions & 70 deletions src/librustc/hir/lowering.rs

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/librustc/hir/map/definitions.rs
Original file line number Diff line number Diff line change
@@ -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());
1 change: 1 addition & 0 deletions src/librustc/hir/mod.rs
Original file line number Diff line number Diff line change
@@ -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>,
1 change: 1 addition & 0 deletions src/librustc/ty/mod.rs
Original file line number Diff line number Diff line change
@@ -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,
109 changes: 71 additions & 38 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
@@ -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,
2 changes: 2 additions & 0 deletions src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
@@ -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(),
23 changes: 18 additions & 5 deletions src/librustc_driver/pretty.rs
Original file line number Diff line number Diff line change
@@ -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 => {
23 changes: 12 additions & 11 deletions src/librustc_driver/test.rs
Original file line number Diff line number Diff line change
@@ -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,
79 changes: 44 additions & 35 deletions src/librustc_metadata/astencode.rs
Original file line number Diff line number Diff line change
@@ -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!()
}
});
}
156 changes: 75 additions & 81 deletions src/librustc_resolve/build_reduced_graph.rs

Large diffs are not rendered by default.

37 changes: 18 additions & 19 deletions src/librustc_resolve/check_unused.rs
Original file line number Diff line number Diff line change
@@ -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);
}
576 changes: 303 additions & 273 deletions src/librustc_resolve/lib.rs

Large diffs are not rendered by default.

17 changes: 7 additions & 10 deletions src/librustc_resolve/resolve_imports.rs
Original file line number Diff line number Diff line change
@@ -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);
}
}
13 changes: 8 additions & 5 deletions src/librustdoc/core.rs
Original file line number Diff line number Diff line change
@@ -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 {
5 changes: 3 additions & 2 deletions src/librustdoc/test.rs
Original file line number Diff line number Diff line change
@@ -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);
38 changes: 38 additions & 0 deletions src/libsyntax/ast.rs
Original file line number Diff line number Diff line change
@@ -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 }`
1 change: 0 additions & 1 deletion src/test/compile-fail/issue-23716.rs
Original file line number Diff line number Diff line change
@@ -16,7 +16,6 @@ fn bar(foo: i32) {}

mod submod {
pub static answer: i32 = 42;
//~^ NOTE static variable defined here
}

use self::submod::answer;
11 changes: 6 additions & 5 deletions src/test/run-make/execution-engine/test.rs
Original file line number Diff line number Diff line change
@@ -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);

2 changes: 2 additions & 0 deletions src/test/run-make/pretty-expanded-hygiene/input.pp.rs
Original file line number Diff line number Diff line change
@@ -14,3 +14,5 @@


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

fn y /* 61#0 */() { }
2 changes: 2 additions & 0 deletions src/test/run-make/pretty-expanded-hygiene/input.rs
Original file line number Diff line number Diff line change
@@ -20,3 +20,5 @@ fn bar() {
let x = 1;
foo!(x)
}

fn y() {}