diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 0876e609396..0026412013c 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -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>, // 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>, + 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) + 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>(&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 { }; // let placer = ; - 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 { }; // 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 { // 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 { 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 { 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 { 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 { 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() { ... }` let into_iter_expr = { @@ -1548,13 +1553,10 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { // `{ 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 { 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 { // 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 { 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 { - expr_path(lctx, path_ident(span, id), attrs) + attrs: ThinAttributes, binding: NodeId) -> P { + 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, @@ -1756,7 +1765,10 @@ fn expr_mut_addr_of(lctx: &LoweringContext, span: Span, e: P, fn expr_path(lctx: &LoweringContext, path: hir::Path, attrs: ThinAttributes) -> P { - 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, e: Option>, attrs: ThinAttributes) -> P { - 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, 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) -> P { @@ -1869,12 +1886,15 @@ fn pat_enum(lctx: &LoweringContext, path: hir::Path, subpats: hir::HirVec>) -> P { + 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 { @@ -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 } diff --git a/src/librustc/hir/map/definitions.rs b/src/librustc/hir/map/definitions.rs index a2f0f30b62c..358301ab404 100644 --- a/src/librustc/hir/map/definitions.rs +++ b/src/librustc/hir/map/definitions.rs @@ -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 { if def_id.krate == LOCAL_CRATE { assert!(def_id.index.as_usize() < self.data.len()); diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index 68e3e742d03..97c43883819 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -1639,6 +1639,7 @@ pub type FreevarMap = NodeMap>; pub type CaptureModeMap = NodeMap; +#[derive(Clone)] pub struct TraitCandidate { pub def_id: DefId, pub import_id: Option, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 174f626498b..700ed62f216 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -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, diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index e791a351252..e72204e5e22 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -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, + 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 where F: FnOnce(&TyCtxt<'tcx>, Option>, 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, diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index 299a20c1a0d..4da36be94e0 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -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(), diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 30f943bd9a4..8d8984000c7 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -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 => { diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index d546db086b5..869bbb723ef 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -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(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, diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 2d6a043e34a..56f6a3f7b14 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -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: 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() -> alist { - 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() -> alist { + 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!() - } + }); } diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs index f5e72195bc3..f56b22f9248 100644 --- a/src/librustc_resolve/build_reduced_graph.rs +++ b/src/librustc_resolve/build_reduced_graph.rs @@ -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::>(); + let mod_spans = source_items.iter().filter_map(|item| { + match item.node { + PathListItemKind::Mod { .. } => Some(item.span), + _ => None, + } + }).collect::>(); + 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; } } diff --git a/src/librustc_resolve/check_unused.rs b/src/librustc_resolve/check_unused.rs index e213a51fb38..64347d7b84d 100644 --- a/src/librustc_resolve/check_unused.rs +++ b/src/librustc_resolve/check_unused.rs @@ -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); } diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index e3c2a9300ba..7ab77ff2616 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -43,18 +43,18 @@ use self::AssocItemResolveResult::*; use self::BareIdentifierPatternResolution::*; use self::ParentLink::*; -use rustc::dep_graph::DepNode; -use rustc::hir::map as hir_map; +use rustc::hir::map::Definitions; +use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr}; use rustc::session::Session; use rustc::lint; use rustc::hir::def::*; use rustc::hir::def_id::DefId; -use rustc::hir::pat_util::pat_bindings; use rustc::ty; use rustc::ty::subst::{ParamSpace, FnSpace, TypeSpace}; use rustc::hir::{Freevar, FreevarMap, TraitCandidate, TraitMap, GlobMap}; use rustc::util::nodemap::{NodeMap, NodeSet, FnvHashMap, FnvHashSet}; +use syntax::ext::mtwt; use syntax::ast::{self, FloatTy}; use syntax::ast::{CRATE_NODE_ID, Name, NodeId, CrateNum, IntTy, UintTy}; use syntax::codemap::{self, Span, Pos}; @@ -62,23 +62,12 @@ use syntax::errors::DiagnosticBuilder; use syntax::parse::token::{self, keywords}; use syntax::util::lev_distance::find_best_match_for_name; -use rustc::hir::intravisit::{self, FnKind, Visitor}; -use rustc::hir; -use rustc::hir::{Arm, BindByRef, BindByValue, BindingMode, Block}; -use rustc::hir::Crate; -use rustc::hir::{Expr, ExprAgain, ExprBreak, ExprField}; -use rustc::hir::{ExprLoop, ExprWhile, ExprMethodCall}; -use rustc::hir::{ExprPath, ExprStruct, FnDecl}; -use rustc::hir::{ForeignItemFn, ForeignItemStatic, Generics}; -use rustc::hir::{ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate}; -use rustc::hir::{ItemFn, ItemForeignMod, ItemImpl, ItemMod, ItemStatic, ItemDefaultImpl}; -use rustc::hir::{ItemStruct, ItemTrait, ItemTy, ItemUse}; -use rustc::hir::Local; -use rustc::hir::{Pat, PatKind, Path, PrimTy}; -use rustc::hir::{PathSegment, PathParameters}; -use rustc::hir::HirVec; -use rustc::hir::{TraitRef, Ty, TyBool, TyChar, TyFloat, TyInt}; -use rustc::hir::{TyRptr, TyStr, TyUint, TyPath}; +use syntax::visit::{self, FnKind, Visitor}; +use syntax::ast::{Arm, BindingMode, Block, Crate, Expr, ExprKind}; +use syntax::ast::{FnDecl, ForeignItem, ForeignItemKind, Generics}; +use syntax::ast::{Item, ItemKind, ImplItem, ImplItemKind}; +use syntax::ast::{Local, Pat, PatKind, Path}; +use syntax::ast::{PathSegment, PathParameters, TraitItemKind, TraitRef, Ty, TyKind}; use std::collections::{HashMap, HashSet}; use std::cell::{Cell, RefCell}; @@ -143,7 +132,7 @@ enum ResolutionError<'a> { /// error E0416: identifier is bound more than once in the same pattern IdentifierBoundMoreThanOnceInSamePattern(&'a str), /// error E0417: static variables cannot be referenced in a pattern - StaticVariableReference(DefId, Option), + StaticVariableReference(&'a NameBinding<'a>), /// error E0418: is not an enum variant, struct or const NotAnEnumVariantStructOrConst(&'a str), /// error E0419: unresolved enum variant, struct or const @@ -195,16 +184,16 @@ enum UnresolvedNameContext<'a> { Other, } -fn resolve_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>, - span: syntax::codemap::Span, - resolution_error: ResolutionError<'b>) { +fn resolve_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>, + span: syntax::codemap::Span, + resolution_error: ResolutionError<'c>) { resolve_struct_error(resolver, span, resolution_error).emit(); } -fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>, - span: syntax::codemap::Span, - resolution_error: ResolutionError<'b>) - -> DiagnosticBuilder<'a> { +fn resolve_struct_error<'b, 'a: 'b, 'c>(resolver: &'b Resolver<'a>, + span: syntax::codemap::Span, + resolution_error: ResolutionError<'c>) + -> DiagnosticBuilder<'a> { if !resolver.emit_errors { return resolver.session.diagnostic().struct_dummy(); } @@ -341,22 +330,15 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>, "identifier `{}` is bound more than once in the same pattern", identifier) } - ResolutionError::StaticVariableReference(did, name) => { + ResolutionError::StaticVariableReference(binding) => { let mut err = struct_span_err!(resolver.session, span, E0417, "static variables cannot be referenced in a \ pattern, use a `const` instead"); - if let Some(sp) = resolver.ast_map.span_if_local(did) { - err.span_note(sp, "static variable defined here"); - } - if let Some(name) = name { - if let Some(binding) = resolver.current_module - .resolve_name_in_lexical_scope(name, ValueNS) { - if binding.is_import() { - err.span_note(binding.span, "static variable imported here"); - } - } + if binding.span != codemap::DUMMY_SP { + let participle = if binding.is_import() { "imported" } else { "defined" }; + err.span_note(binding.span, &format!("static variable {} here", participle)); } err } @@ -422,13 +404,13 @@ fn resolve_struct_error<'b, 'a: 'b, 'tcx: 'a>(resolver: &'b Resolver<'a, 'tcx>, UnresolvedNameContext::Other => { } // no help available UnresolvedNameContext::PathIsMod(parent) => { err.help(&match parent.map(|parent| &parent.node) { - Some(&ExprField(_, ident)) => { + Some(&ExprKind::Field(_, ident)) => { format!("To reference an item from the `{module}` module, \ use `{module}::{ident}`", module = path, ident = ident.node) } - Some(&ExprMethodCall(ident, _, _)) => { + Some(&ExprKind::MethodCall(ident, _, _)) => { format!("To call a function from the `{module}` module, \ use `{module}::{ident}(..)`", module = path, @@ -526,10 +508,7 @@ pub enum Namespace { ValueNS, } -impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { - fn visit_nested_item(&mut self, item: hir::ItemId) { - self.visit_item(self.ast_map.expect_item(item.id)) - } +impl<'a, 'v> Visitor<'v> for Resolver<'a> { fn visit_item(&mut self, item: &Item) { self.resolve_item(item); } @@ -551,7 +530,7 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { fn visit_generics(&mut self, generics: &Generics) { self.resolve_generics(generics); } - fn visit_poly_trait_ref(&mut self, tref: &hir::PolyTraitRef, m: &hir::TraitBoundModifier) { + fn visit_poly_trait_ref(&mut self, tref: &ast::PolyTraitRef, m: &ast::TraitBoundModifier) { match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) { Ok(def) => self.record_def(tref.trait_ref.ref_id, def), Err(_) => { @@ -559,10 +538,10 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { self.record_def(tref.trait_ref.ref_id, err_path_resolution()) } } - intravisit::walk_poly_trait_ref(self, tref, m); + visit::walk_poly_trait_ref(self, tref, m); } fn visit_variant(&mut self, - variant: &hir::Variant, + variant: &ast::Variant, generics: &Generics, item_id: ast::NodeId) { if let Some(ref dis_expr) = variant.node.disr_expr { @@ -572,22 +551,22 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { }); } - // `intravisit::walk_variant` without the discriminant expression. + // `visit::walk_variant` without the discriminant expression. self.visit_variant_data(&variant.node.data, variant.node.name, generics, item_id, variant.span); } - fn visit_foreign_item(&mut self, foreign_item: &hir::ForeignItem) { + fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) { let type_parameters = match foreign_item.node { - ForeignItemFn(_, ref generics) => { + ForeignItemKind::Fn(_, ref generics) => { HasTypeParameters(generics, FnSpace, ItemRibKind) } - ForeignItemStatic(..) => NoTypeParameters, + ForeignItemKind::Static(..) => NoTypeParameters, }; self.with_type_parameter_rib(type_parameters, |this| { - intravisit::walk_foreign_item(this, foreign_item); + visit::walk_foreign_item(this, foreign_item); }); } fn visit_fn(&mut self, @@ -597,16 +576,16 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Resolver<'a, 'tcx> { _: Span, node_id: NodeId) { let rib_kind = match function_kind { - FnKind::ItemFn(_, generics, _, _, _, _, _) => { + FnKind::ItemFn(_, generics, _, _, _, _) => { self.visit_generics(generics); ItemRibKind } - FnKind::Method(_, sig, _, _) => { + FnKind::Method(_, sig, _) => { self.visit_generics(&sig.generics); self.visit_explicit_self(&sig.explicit_self); MethodRibKind } - FnKind::Closure(_) => ClosureRibKind(node_id), + FnKind::Closure => ClosureRibKind(node_id), }; self.resolve_function(rib_kind, declaration, block); } @@ -646,17 +625,17 @@ enum FallbackSuggestion { } #[derive(Copy, Clone)] -enum TypeParameters<'tcx, 'a> { +enum TypeParameters<'a, 'b> { NoTypeParameters, HasTypeParameters(// Type parameters. - &'a Generics, + &'b Generics, // Identifies the things that these parameters // were declared on (type, fn, etc) ParamSpace, // The kind of the rib used for type parameters. - RibKind<'tcx>), + RibKind<'a>), } // The rib kind controls the translation of local @@ -757,10 +736,6 @@ impl<'a> LexicalScopeBinding<'a> { } } - fn def(self) -> Def { - self.local_def().def - } - fn module(self) -> Option> { match self { LexicalScopeBinding::Item(binding) => binding.module(), @@ -975,10 +950,10 @@ impl PrimitiveTypeTable { } /// The main resolver class. -pub struct Resolver<'a, 'tcx: 'a> { +pub struct Resolver<'a> { session: &'a Session, - ast_map: &'a hir_map::Map<'tcx>, + definitions: &'a mut Definitions, graph_root: Module<'a>, @@ -1011,11 +986,11 @@ pub struct Resolver<'a, 'tcx: 'a> { // The idents for the primitive types. primitive_type_table: PrimitiveTypeTable, - def_map: RefCell, - freevars: FreevarMap, + pub def_map: DefMap, + pub freevars: FreevarMap, freevars_seen: NodeMap>, - export_map: ExportMap, - trait_map: TraitMap, + pub export_map: ExportMap, + pub trait_map: TraitMap, // A map from nodes to modules, both normal (`mod`) modules and anonymous modules. // Anonymous modules are pseudo-modules that are implicitly created around items @@ -1038,14 +1013,14 @@ pub struct Resolver<'a, 'tcx: 'a> { // so as to avoid printing duplicate errors emit_errors: bool, - make_glob_map: bool, + pub make_glob_map: bool, // Maps imports to the names of items actually imported (this actually maps // all imports, but only glob imports are actually interesting). - glob_map: GlobMap, + pub glob_map: GlobMap, used_imports: HashSet<(NodeId, Namespace)>, used_crates: HashSet, - maybe_unused_trait_imports: NodeSet, + pub maybe_unused_trait_imports: NodeSet, privacy_errors: Vec>, @@ -1083,9 +1058,9 @@ impl<'a> ResolverArenas<'a> { } } -impl<'a, 'tcx> ty::NodeIdTree for Resolver<'a, 'tcx> { +impl<'a> ty::NodeIdTree for Resolver<'a> { fn is_descendant_of(&self, node: NodeId, ancestor: NodeId) -> bool { - let ancestor = self.ast_map.local_def_id(ancestor); + let ancestor = self.definitions.local_def_id(ancestor); let mut module = *self.module_map.get(&node).unwrap(); while module.def_id() != Some(ancestor) { let module_parent = match self.get_nearest_normal_module_parent(module) { @@ -1098,13 +1073,54 @@ impl<'a, 'tcx> ty::NodeIdTree for Resolver<'a, 'tcx> { } } -impl<'a, 'tcx> Resolver<'a, 'tcx> { +impl<'a> hir::lowering::Resolver for Resolver<'a> { + fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def { + let namespace = if is_value { ValueNS } else { TypeNS }; + match self.resolve_crate_relative_path(path.span, &path.segments, namespace) { + Ok(binding) => binding.def().unwrap(), + Err(true) => Def::Err, + Err(false) => { + let path_name = &format!("{}", path); + let error = + ResolutionError::UnresolvedName(path_name, "", UnresolvedNameContext::Other); + resolve_error(self, path.span, error); + Def::Err + } + } + } + + fn record_resolution(&mut self, id: NodeId, def: Def) { + self.def_map.insert(id, PathResolution { base_def: def, depth: 0 }); + } + + fn definitions(&mut self) -> Option<&mut Definitions> { + Some(self.definitions) + } +} + +trait Named { + fn name(&self) -> Name; +} + +impl Named for ast::PathSegment { + fn name(&self) -> Name { + self.identifier.name + } +} + +impl Named for hir::PathSegment { + fn name(&self) -> Name { + self.identifier.name + } +} + +impl<'a> Resolver<'a> { fn new(session: &'a Session, - ast_map: &'a hir_map::Map<'tcx>, + definitions: &'a mut Definitions, make_glob_map: MakeGlobMap, arenas: &'a ResolverArenas<'a>) - -> Resolver<'a, 'tcx> { - let root_def_id = ast_map.local_def_id(CRATE_NODE_ID); + -> Resolver<'a> { + let root_def_id = definitions.local_def_id(CRATE_NODE_ID); let graph_root = ModuleS::new(NoParentLink, Some(Def::Mod(root_def_id)), false, arenas); let graph_root = arenas.alloc_module(graph_root); @@ -1114,7 +1130,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Resolver { session: session, - ast_map: ast_map, + definitions: definitions, // The outermost module has def ID 0; this is not reflected in the // AST. @@ -1135,7 +1151,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { primitive_type_table: PrimitiveTypeTable::new(), - def_map: RefCell::new(NodeMap()), + def_map: NodeMap(), freevars: NodeMap(), freevars_seen: NodeMap(), export_map: NodeMap(), @@ -1337,7 +1353,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // This is not a crate-relative path. We resolve the // first component of the path in the current lexical // scope and then proceed to resolve below that. - let ident = hir::Ident::from_name(module_path[0]); + let ident = ast::Ident::with_empty_ctxt(module_path[0]); match self.resolve_ident_in_lexical_scope(ident, TypeNS, true) .and_then(LexicalScopeBinding::module) { None => return Failed(None), @@ -1379,11 +1395,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Invariant: This must only be called during main resolution, not during /// import resolution. fn resolve_ident_in_lexical_scope(&mut self, - ident: hir::Ident, + ident: ast::Ident, ns: Namespace, record_used: bool) -> Option> { - let name = match ns { ValueNS => ident.name, TypeNS => ident.unhygienic_name }; + let name = match ns { ValueNS => mtwt::resolve(ident), TypeNS => ident.name }; // Walk backwards up the ribs in scope. for i in (0 .. self.get_ribs(ns).len()).rev() { @@ -1396,7 +1412,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } if let ModuleRibKind(module) = self.get_ribs(ns)[i].kind { - let name = ident.unhygienic_name; + let name = ident.name; let item = self.resolve_name_in_module(module, name, ns, true, record_used); if let Success(binding) = item { // The ident resolves to an item. @@ -1565,77 +1581,76 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None } - fn resolve_crate(&mut self, krate: &hir::Crate) { + fn resolve_crate(&mut self, krate: &Crate) { debug!("(resolving crate) starting"); self.current_module = self.graph_root; - intravisit::walk_crate(self, krate); + visit::walk_crate(self, krate); } fn resolve_item(&mut self, item: &Item) { - let name = item.name; + let name = item.ident.name; debug!("(resolving item) resolving {}", name); match item.node { - ItemEnum(_, ref generics) | - ItemTy(_, ref generics) | - ItemStruct(_, ref generics) => { + ItemKind::Enum(_, ref generics) | + ItemKind::Ty(_, ref generics) | + ItemKind::Struct(_, ref generics) => { self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind), - |this| intravisit::walk_item(this, item)); + |this| visit::walk_item(this, item)); } - ItemFn(_, _, _, _, ref generics, _) => { + ItemKind::Fn(_, _, _, _, ref generics, _) => { self.with_type_parameter_rib(HasTypeParameters(generics, FnSpace, ItemRibKind), - |this| intravisit::walk_item(this, item)); + |this| visit::walk_item(this, item)); } - ItemDefaultImpl(_, ref trait_ref) => { + ItemKind::DefaultImpl(_, ref trait_ref) => { self.with_optional_trait_ref(Some(trait_ref), |_, _| {}); } - ItemImpl(_, _, ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => { + ItemKind::Impl(_, _, ref generics, ref opt_trait_ref, ref self_type, ref impl_items) => self.resolve_implementation(generics, opt_trait_ref, &self_type, item.id, - impl_items); - } + impl_items), - ItemTrait(_, ref generics, ref bounds, ref trait_items) => { + ItemKind::Trait(_, ref generics, ref bounds, ref trait_items) => { // Create a new rib for the trait-wide type parameters. self.with_type_parameter_rib(HasTypeParameters(generics, TypeSpace, ItemRibKind), |this| { - let local_def_id = this.ast_map.local_def_id(item.id); + let local_def_id = this.definitions.local_def_id(item.id); this.with_self_rib(Def::SelfTy(Some(local_def_id), None), |this| { this.visit_generics(generics); walk_list!(this, visit_ty_param_bound, bounds); for trait_item in trait_items { match trait_item.node { - hir::ConstTraitItem(_, ref default) => { + TraitItemKind::Const(_, ref default) => { // Only impose the restrictions of // ConstRibKind if there's an actual constant // expression in a provided default. if default.is_some() { this.with_constant_rib(|this| { - intravisit::walk_trait_item(this, trait_item) + visit::walk_trait_item(this, trait_item) }); } else { - intravisit::walk_trait_item(this, trait_item) + visit::walk_trait_item(this, trait_item) } } - hir::MethodTraitItem(ref sig, _) => { + TraitItemKind::Method(ref sig, _) => { let type_parameters = HasTypeParameters(&sig.generics, FnSpace, MethodRibKind); this.with_type_parameter_rib(type_parameters, |this| { - intravisit::walk_trait_item(this, trait_item) + visit::walk_trait_item(this, trait_item) }); } - hir::TypeTraitItem(..) => { + TraitItemKind::Type(..) => { this.with_type_parameter_rib(NoTypeParameters, |this| { - intravisit::walk_trait_item(this, trait_item) + visit::walk_trait_item(this, trait_item) }); } }; @@ -1644,21 +1659,21 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } - ItemMod(_) | ItemForeignMod(_) => { + ItemKind::Mod(_) | ItemKind::ForeignMod(_) => { self.with_scope(item.id, |this| { - intravisit::walk_item(this, item); + visit::walk_item(this, item); }); } - ItemConst(..) | ItemStatic(..) => { + ItemKind::Const(..) | ItemKind::Static(..) => { self.with_constant_rib(|this| { - intravisit::walk_item(this, item); + visit::walk_item(this, item); }); } - ItemUse(ref view_path) => { + ItemKind::Use(ref view_path) => { match view_path.node { - hir::ViewPathList(ref prefix, ref items) => { + ast::ViewPathList(ref prefix, ref items) => { // Resolve prefix of an import with empty braces (issue #28388) if items.is_empty() && !prefix.segments.is_empty() { match self.resolve_crate_relative_path(prefix.span, @@ -1683,9 +1698,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - ItemExternCrate(_) => { + ItemKind::ExternCrate(_) => { // do nothing, these are just around to be encoded } + + ItemKind::Mac(_) => panic!("unexpanded macro in resolve!"), } } @@ -1697,7 +1714,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut function_type_rib = Rib::new(rib_kind); let mut seen_bindings = HashSet::new(); for (index, type_parameter) in generics.ty_params.iter().enumerate() { - let name = type_parameter.name; + let name = type_parameter.ident.name; debug!("with_type_parameter_rib: {}", type_parameter.id); if seen_bindings.contains(&name) { @@ -1708,7 +1725,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { seen_bindings.insert(name); // plain insert (no renaming) - let def_id = self.ast_map.local_def_id(type_parameter.id); + let def_id = self.definitions.local_def_id(type_parameter.id); let def = Def::TyParam(space, index as u32, def_id, name); function_type_rib.bindings.insert(name, def); } @@ -1761,7 +1778,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { debug!("(resolving function) recorded argument"); } - intravisit::walk_fn_ret_ty(self, &declaration.output); + visit::walk_fn_ret_ty(self, &declaration.output); // Resolve the function body. self.visit_block(block); @@ -1838,9 +1855,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_generics(&mut self, generics: &Generics) { for predicate in &generics.where_clause.predicates { match predicate { - &hir::WherePredicate::BoundPredicate(_) | - &hir::WherePredicate::RegionPredicate(_) => {} - &hir::WherePredicate::EqPredicate(ref eq_pred) => { + &ast::WherePredicate::BoundPredicate(_) | + &ast::WherePredicate::RegionPredicate(_) => {} + &ast::WherePredicate::EqPredicate(ref eq_pred) => { self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS).and_then(|path_res| { if let PathResolution { base_def: Def::TyParam(..), .. } = path_res { Ok(self.record_def(eq_pred.id, path_res)) @@ -1856,7 +1873,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } } - intravisit::walk_generics(self, generics); + visit::walk_generics(self, generics); } fn with_current_self_type(&mut self, self_type: &Ty, f: F) -> T @@ -1885,7 +1902,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } else { self.record_def(trait_ref.ref_id, err_path_resolution()); } - intravisit::walk_trait_ref(self, trait_ref); + visit::walk_trait_ref(self, trait_ref); } let original_trait_ref = replace(&mut self.current_trait_ref, new_val); let result = f(self, new_id); @@ -1929,20 +1946,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { for impl_item in impl_items { this.resolve_visibility(&impl_item.vis); match impl_item.node { - hir::ImplItemKind::Const(..) => { + ImplItemKind::Const(..) => { // If this is a trait impl, ensure the const // exists in trait - this.check_trait_item(impl_item.name, + this.check_trait_item(impl_item.ident.name, impl_item.span, |n, s| ResolutionError::ConstNotMemberOfTrait(n, s)); this.with_constant_rib(|this| { - intravisit::walk_impl_item(this, impl_item); + visit::walk_impl_item(this, impl_item); }); } - hir::ImplItemKind::Method(ref sig, _) => { + ImplItemKind::Method(ref sig, _) => { // If this is a trait impl, ensure the method // exists in trait - this.check_trait_item(impl_item.name, + this.check_trait_item(impl_item.ident.name, impl_item.span, |n, s| ResolutionError::MethodNotMemberOfTrait(n, s)); @@ -1953,18 +1970,19 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { FnSpace, MethodRibKind); this.with_type_parameter_rib(type_parameters, |this| { - intravisit::walk_impl_item(this, impl_item); + visit::walk_impl_item(this, impl_item); }); } - hir::ImplItemKind::Type(ref ty) => { + ImplItemKind::Type(ref ty) => { // If this is a trait impl, ensure the type // exists in trait - this.check_trait_item(impl_item.name, + this.check_trait_item(impl_item.ident.name, impl_item.span, |n, s| ResolutionError::TypeNotMemberOfTrait(n, s)); this.visit_ty(ty); } + ImplItemKind::Macro(_) => panic!("unexpanded macro in resolve!"), } } }); @@ -2002,16 +2020,22 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // that expands into an or-pattern where one 'x' was from the // user and one 'x' came from the macro. fn binding_mode_map(&mut self, pat: &Pat) -> BindingMap { - let mut result = HashMap::new(); - pat_bindings(&self.def_map, pat, |binding_mode, _id, sp, path1| { - let name = path1.node; - result.insert(name, - BindingInfo { - span: sp, - binding_mode: binding_mode, - }); + let mut binding_map = HashMap::new(); + + pat.walk(&mut |pat| { + if let PatKind::Ident(binding_mode, ident, ref sub_pat) = pat.node { + if sub_pat.is_some() || match self.def_map.get(&pat.id) { + Some(&PathResolution { base_def: Def::Local(..), .. }) => true, + _ => false, + } { + let binding_info = BindingInfo { span: ident.span, binding_mode: binding_mode }; + binding_map.insert(mtwt::resolve(ident.node), binding_info); + } + } + true }); - return result; + + binding_map } // check that all of the arms in an or-pattern have exactly the @@ -2086,7 +2110,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } // Descend into the block. - intravisit::walk_block(self, block); + visit::walk_block(self, block); // Move back up. self.current_module = orig_module; @@ -2099,7 +2123,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn resolve_type(&mut self, ty: &Ty) { match ty.node { - TyPath(ref maybe_qself, ref path) => { + TyKind::Path(ref maybe_qself, ref path) => { let resolution = match self.resolve_possibly_assoc_item(ty.id, maybe_qself.as_ref(), path, @@ -2107,7 +2131,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // `::a::b::c` is resolved by typeck alone. TypecheckRequired => { // Resolve embedded types. - intravisit::walk_ty(self, ty); + visit::walk_ty(self, ty); return; } ResolveAttempt(resolution) => resolution, @@ -2176,7 +2200,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { _ => {} } // Resolve embedded types. - intravisit::walk_ty(self, ty); + visit::walk_ty(self, ty); } fn resolve_pattern(&mut self, @@ -2186,7 +2210,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // pattern that binds them bindings_list: &mut HashMap) { let pat_id = pattern.id; - pattern.walk(|pattern| { + pattern.walk(&mut |pattern| { match pattern.node { PatKind::Ident(binding_mode, ref path1, ref at_rhs) => { // The meaning of PatKind::Ident with no type parameters @@ -2200,7 +2224,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let const_ok = mode == RefutableMode && at_rhs.is_none(); let ident = path1.node; - let renamed = ident.name; + let renamed = mtwt::resolve(ident); match self.resolve_bare_identifier_pattern(ident, pattern.span) { FoundStructOrEnumVariant(def) if const_ok => { @@ -2246,7 +2270,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { BareIdentifierPatternUnresolved => { debug!("(resolving pattern) binding `{}`", renamed); - let def_id = self.ast_map.local_def_id(pattern.id); + let def_id = self.definitions.local_def_id(pattern.id); let def = Def::Local(def_id, pattern.id); // Record the definition so that later passes @@ -2319,11 +2343,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Def::Variant(..) | Def::Const(..) => { self.record_def(pattern.id, path_res); } - Def::Static(did, _) => { - resolve_error(&self, - path.span, - ResolutionError::StaticVariableReference( - did, None)); + Def::Static(..) => { + let segments = &path.segments; + let binding = if path.global { + self.resolve_crate_relative_path(path.span, segments, ValueNS) + } else { + self.resolve_module_relative_path(path.span, segments, ValueNS) + }.unwrap(); + + let error = ResolutionError::StaticVariableReference(binding); + resolve_error(self, path.span, error); self.record_def(pattern.id, err_path_resolution()); } _ => { @@ -2365,7 +2394,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { ); self.record_def(pattern.id, err_path_resolution()); } - intravisit::walk_path(self, path); + visit::walk_path(self, path); } PatKind::QPath(ref qself, ref path) => { @@ -2385,7 +2414,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .name; let traits = self.get_traits_containing_item(const_name); self.trait_map.insert(pattern.id, traits); - intravisit::walk_pat(self, pattern); + visit::walk_pat(self, pattern); return true; } ResolveAttempt(resolution) => resolution, @@ -2419,7 +2448,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { .as_str())); self.record_def(pattern.id, err_path_resolution()); } - intravisit::walk_pat(self, pattern); + visit::walk_pat(self, pattern); } PatKind::Struct(ref path, _, _) => { @@ -2438,11 +2467,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.record_def(pattern.id, err_path_resolution()); } } - intravisit::walk_path(self, path); + visit::walk_path(self, path); } PatKind::Lit(_) | PatKind::Range(..) => { - intravisit::walk_pat(self, pattern); + visit::walk_pat(self, pattern); } _ => { @@ -2453,19 +2482,20 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { }); } - fn resolve_bare_identifier_pattern(&mut self, ident: hir::Ident, span: Span) + fn resolve_bare_identifier_pattern(&mut self, ident: ast::Ident, span: Span) -> BareIdentifierPatternResolution { - match self.resolve_ident_in_lexical_scope(ident, ValueNS, true) - .map(LexicalScopeBinding::def) { - Some(def @ Def::Variant(..)) | Some(def @ Def::Struct(..)) => { - FoundStructOrEnumVariant(def) - } - Some(def @ Def::Const(..)) | Some(def @ Def::AssociatedConst(..)) => { - FoundConst(def, ident.unhygienic_name) - } - Some(Def::Static(did, _)) => { - resolve_error(self, span, ResolutionError::StaticVariableReference( - did, Some(ident.unhygienic_name))); + let binding = match self.resolve_ident_in_lexical_scope(ident, ValueNS, true) { + Some(LexicalScopeBinding::Item(binding)) => binding, + _ => return BareIdentifierPatternUnresolved, + }; + let def = binding.def().unwrap(); + + match def { + Def::Variant(..) | Def::Struct(..) => FoundStructOrEnumVariant(def), + Def::Const(..) | Def::AssociatedConst(..) => FoundConst(def, ident.name), + Def::Static(..) => { + let error = ResolutionError::StaticVariableReference(binding); + resolve_error(self, span, error); BareIdentifierPatternUnresolved } _ => BareIdentifierPatternUnresolved, @@ -2475,7 +2505,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Handles paths that may refer to associated items fn resolve_possibly_assoc_item(&mut self, id: NodeId, - maybe_qself: Option<&hir::QSelf>, + maybe_qself: Option<&ast::QSelf>, path: &Path, namespace: Namespace) -> AssocItemResolveResult { @@ -2536,7 +2566,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None | Some(LocalDef{def: Def::Mod(..), ..}) if namespace == TypeNS => this.primitive_type_table .primitive_types - .get(&last_ident.unhygienic_name) + .get(&last_ident.name) .map_or(def, |prim_ty| Some(LocalDef::from_def(Def::PrimTy(*prim_ty)))), _ => def } @@ -2577,11 +2607,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Resolve a single identifier fn resolve_identifier(&mut self, - identifier: hir::Ident, + identifier: ast::Ident, namespace: Namespace, record_used: bool) -> Option { - if identifier.unhygienic_name == keywords::Invalid.name() { + if identifier.name == keywords::Invalid.name() { return Some(LocalDef::from_def(Def::Err)); } @@ -2609,7 +2639,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } ClosureRibKind(function_id) => { let prev_def = def; - let node_def_id = self.ast_map.local_def_id(node_id); + let node_def_id = self.definitions.local_def_id(node_id); let seen = self.freevars_seen .entry(function_id) @@ -2681,7 +2711,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // resolve a "module-relative" path, e.g. a::b::c fn resolve_module_relative_path(&mut self, span: Span, - segments: &[hir::PathSegment], + segments: &[ast::PathSegment], namespace: Namespace) -> Result<&'a NameBinding<'a>, bool /* true if an error was reported */> { @@ -2723,19 +2753,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { /// Invariant: This must be called only during main resolution, not during /// import resolution. - fn resolve_crate_relative_path(&mut self, - span: Span, - segments: &[hir::PathSegment], - namespace: Namespace) - -> Result<&'a NameBinding<'a>, - bool /* true if an error was reported */> { - let module_path = segments.split_last() - .unwrap() - .1 - .iter() - .map(|ps| ps.identifier.name) - .collect::>(); - + fn resolve_crate_relative_path(&mut self, span: Span, segments: &[T], namespace: Namespace) + -> Result<&'a NameBinding<'a>, + bool /* true if an error was reported */> + where T: Named, + { + let module_path = segments.split_last().unwrap().1.iter().map(T::name).collect::>(); let root_module = self.graph_root; let containing_module; @@ -2764,7 +2787,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - let name = segments.last().unwrap().identifier.name; + let name = segments.last().unwrap().name(); let result = self.resolve_name_in_module(containing_module, name, namespace, false, true); result.success().map(|binding| { self.check_privacy(name, binding, span); @@ -2784,8 +2807,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion { fn extract_node_id(t: &Ty) -> Option { match t.node { - TyPath(None, _) => Some(t.id), - TyRptr(_, ref mut_ty) => extract_node_id(&mut_ty.ty), + TyKind::Path(None, _) => Some(t.id), + TyKind::Rptr(_, ref mut_ty) => extract_node_id(&mut_ty.ty), // This doesn't handle the remaining `Ty` variants as they are not // that commonly the self_type, it might be interesting to provide // support for those in future. @@ -2795,7 +2818,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(node_id) = self.current_self_type.as_ref().and_then(extract_node_id) { // Look for a field with the same name in the current self_type. - match self.def_map.borrow().get(&node_id).map(|d| d.full_def()) { + match self.def_map.get(&node_id).map(|d| d.full_def()) { Some(Def::Enum(did)) | Some(Def::TyAlias(did)) | Some(Def::Struct(did)) | @@ -2843,6 +2866,18 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } SuggestionType::NotFound } + fn resolve_labeled_block(&mut self, label: Option, id: NodeId, block: &Block) { + if let Some(label) = label { + let (label, def) = (mtwt::resolve(label), Def::Label(id)); + self.with_label_rib(|this| { + this.label_ribs.last_mut().unwrap().bindings.insert(label, def); + this.visit_block(block); + }); + } else { + self.visit_block(block); + } + } + fn resolve_expr(&mut self, expr: &Expr, parent: Option<&Expr>) { // First, record candidate traits for this expression if it could // result in the invocation of a method call. @@ -2851,7 +2886,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Next, resolve the node. match expr.node { - ExprPath(ref maybe_qself, ref path) => { + ExprKind::Path(ref maybe_qself, ref path) => { let resolution = match self.resolve_possibly_assoc_item(expr.id, maybe_qself.as_ref(), path, @@ -2861,7 +2896,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let method_name = path.segments.last().unwrap().identifier.name; let traits = self.get_traits_containing_item(method_name); self.trait_map.insert(expr.id, traits); - intravisit::walk_expr(self, expr); + visit::walk_expr(self, expr); return; } ResolveAttempt(resolution) => resolution, @@ -3003,10 +3038,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - intravisit::walk_expr(self, expr); + visit::walk_expr(self, expr); } - ExprStruct(ref path, _, _) => { + ExprKind::Struct(ref path, _, _) => { // Resolve the path to the structure it goes to. We don't // check to ensure that the path is actually a structure; that // is checked later during typeck. @@ -3025,24 +3060,24 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - intravisit::walk_expr(self, expr); + visit::walk_expr(self, expr); } - ExprLoop(_, Some(label)) | ExprWhile(_, _, Some(label)) => { + ExprKind::Loop(_, Some(label)) | ExprKind::While(_, _, Some(label)) => { self.with_label_rib(|this| { let def = Def::Label(expr.id); { let rib = this.label_ribs.last_mut().unwrap(); - rib.bindings.insert(label.name, def); + rib.bindings.insert(mtwt::resolve(label), def); } - intravisit::walk_expr(this, expr); + visit::walk_expr(this, expr); }) } - ExprBreak(Some(label)) | ExprAgain(Some(label)) => { - match self.search_label(label.node.name) { + ExprKind::Break(Some(label)) | ExprKind::Again(Some(label)) => { + match self.search_label(mtwt::resolve(label.node)) { None => { self.record_def(expr.id, err_path_resolution()); resolve_error(self, @@ -3062,10 +3097,42 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } } - ExprField(ref subexpression, _) => { + + ExprKind::IfLet(ref pattern, ref subexpression, ref if_block, ref optional_else) => { + self.visit_expr(subexpression); + + self.value_ribs.push(Rib::new(NormalRibKind)); + self.resolve_pattern(pattern, RefutableMode, &mut HashMap::new()); + self.visit_block(if_block); + self.value_ribs.pop(); + + optional_else.as_ref().map(|expr| self.visit_expr(expr)); + } + + ExprKind::WhileLet(ref pattern, ref subexpression, ref block, label) => { + self.visit_expr(subexpression); + self.value_ribs.push(Rib::new(NormalRibKind)); + self.resolve_pattern(pattern, RefutableMode, &mut HashMap::new()); + + self.resolve_labeled_block(label, expr.id, block); + + self.value_ribs.pop(); + } + + ExprKind::ForLoop(ref pattern, ref subexpression, ref block, label) => { + self.visit_expr(subexpression); + self.value_ribs.push(Rib::new(NormalRibKind)); + self.resolve_pattern(pattern, LocalIrrefutableMode, &mut HashMap::new()); + + self.resolve_labeled_block(label, expr.id, block); + + self.value_ribs.pop(); + } + + ExprKind::Field(ref subexpression, _) => { self.resolve_expr(subexpression, Some(expr)); } - ExprMethodCall(_, ref types, ref arguments) => { + ExprKind::MethodCall(_, ref types, ref arguments) => { let mut arguments = arguments.iter(); self.resolve_expr(arguments.next().unwrap(), Some(expr)); for argument in arguments { @@ -3077,25 +3144,25 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } _ => { - intravisit::walk_expr(self, expr); + visit::walk_expr(self, expr); } } } fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) { match expr.node { - ExprField(_, name) => { + ExprKind::Field(_, name) => { // FIXME(#6890): Even though you can't treat a method like a // field, we need to add any trait methods we find that match // the field name so that we can do some nice error reporting // later on in typeck. - let traits = self.get_traits_containing_item(name.node); + let traits = self.get_traits_containing_item(name.node.name); self.trait_map.insert(expr.id, traits); } - ExprMethodCall(name, _, _) => { + ExprKind::MethodCall(name, _, _) => { debug!("(recording candidate traits for expr) recording traits for {}", expr.id); - let traits = self.get_traits_containing_item(name.node); + let traits = self.get_traits_containing_item(name.node.name); self.trait_map.insert(expr.id, traits); } _ => { @@ -3205,7 +3272,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if let Some(def) = name_binding.def() { if name == lookup_name && ns == namespace && filter_fn(def) { // create the path - let ident = hir::Ident::from_name(name); + let ident = ast::Ident::with_empty_ctxt(name); let params = PathParameters::none(); let segment = PathSegment { identifier: ident, @@ -3214,7 +3281,6 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let span = name_binding.span; let mut segms = path_segments.clone(); segms.push(segment); - let segms = HirVec::from_vec(segms); let path = Path { span: span, global: true, @@ -3240,7 +3306,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { NoParentLink => path_segments.clone(), ModuleParentLink(_, name) => { let mut paths = path_segments.clone(); - let ident = hir::Ident::from_name(name); + let ident = ast::Ident::with_empty_ctxt(name); let params = PathParameters::none(); let segm = PathSegment { identifier: ident, @@ -3269,12 +3335,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) { debug!("(recording def) recording {:?} for {}", resolution, node_id); - if let Some(prev_res) = self.def_map.borrow_mut().insert(node_id, resolution) { - let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP); - span_bug!(span, - "path resolved multiple times ({:?} before, {:?} now)", - prev_res, - resolution); + if let Some(prev_res) = self.def_map.insert(node_id, resolution) { + panic!("path resolved multiple times ({:?} before, {:?} now)", prev_res, resolution); } } @@ -3283,8 +3345,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { pat_binding_mode: BindingMode, descr: &str) { match pat_binding_mode { - BindByValue(_) => {} - BindByRef(..) => { + BindingMode::ByValue(_) => {} + BindingMode::ByRef(..) => { resolve_error(self, pat.span, ResolutionError::CannotUseRefBindingModeWith(descr)); @@ -3292,15 +3354,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { } } - fn resolve_visibility(&mut self, vis: &hir::Visibility) -> ty::Visibility { + fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility { let (path, id) = match *vis { - hir::Public => return ty::Visibility::Public, - hir::Visibility::Crate => return ty::Visibility::Restricted(ast::CRATE_NODE_ID), - hir::Visibility::Restricted { ref path, id } => (path, id), - hir::Inherited => { + ast::Visibility::Public => return ty::Visibility::Public, + ast::Visibility::Crate(_) => return ty::Visibility::Restricted(ast::CRATE_NODE_ID), + ast::Visibility::Restricted { ref path, id } => (path, id), + ast::Visibility::Inherited => { let current_module = self.get_nearest_normal_module_parent_or_self(self.current_module); - let id = self.ast_map.as_local_node_id(current_module.def_id().unwrap()).unwrap(); + let id = + self.definitions.as_local_node_id(current_module.def_id().unwrap()).unwrap(); return ty::Visibility::Restricted(id); } }; @@ -3310,8 +3373,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Success(module) => { let def = module.def.unwrap(); let path_resolution = PathResolution { base_def: def, depth: 0 }; - self.def_map.borrow_mut().insert(id, path_resolution); - ty::Visibility::Restricted(self.ast_map.as_local_node_id(def.def_id()).unwrap()) + self.def_map.insert(id, path_resolution); + ty::Visibility::Restricted(self.definitions.as_local_node_id(def.def_id()).unwrap()) } Failed(Some((span, msg))) => { self.session.span_err(span, &format!("failed to resolve module path. {}", msg)); @@ -3331,7 +3394,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { fn is_accessible(&self, vis: ty::Visibility) -> bool { let current_module = self.get_nearest_normal_module_parent_or_self(self.current_module); - let node_id = self.ast_map.as_local_node_id(current_module.def_id().unwrap()).unwrap(); + let node_id = self.definitions.as_local_node_id(current_module.def_id().unwrap()).unwrap(); vis.is_accessible_from(node_id, self) } @@ -3525,15 +3588,6 @@ fn err_path_resolution() -> PathResolution { } -pub struct CrateMap { - pub def_map: RefCell, - pub freevars: FreevarMap, - pub maybe_unused_trait_imports: NodeSet, - pub export_map: ExportMap, - pub trait_map: TraitMap, - pub glob_map: Option, -} - #[derive(PartialEq,Copy, Clone)] pub enum MakeGlobMap { Yes, @@ -3541,10 +3595,7 @@ pub enum MakeGlobMap { } /// Entry point to crate resolution. -pub fn resolve_crate<'a, 'tcx>(session: &'a Session, - ast_map: &'a hir_map::Map<'tcx>, - make_glob_map: MakeGlobMap) - -> CrateMap { +pub fn resolve_crate<'a, 'b>(resolver: &'b mut Resolver<'a>, krate: &'b Crate) { // Currently, we ignore the name resolution data structures for // the purposes of dependency tracking. Instead we will run name // resolution and include its output in the hash of each item, @@ -3552,45 +3603,24 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session, // reflects not just its contents but the results of name // resolution on those contents. Hopefully we'll push this back at // some point. - let _task = ast_map.dep_graph.in_task(DepNode::Resolve); - - let krate = ast_map.krate(); - let arenas = Resolver::arenas(); - let mut resolver = create_resolver(session, ast_map, krate, make_glob_map, &arenas); - - resolver.resolve_crate(krate); - - check_unused::check_crate(&mut resolver, krate); - resolver.report_privacy_errors(); - - CrateMap { - def_map: resolver.def_map, - freevars: resolver.freevars, - maybe_unused_trait_imports: resolver.maybe_unused_trait_imports, - export_map: resolver.export_map, - trait_map: resolver.trait_map, - glob_map: if resolver.make_glob_map { - Some(resolver.glob_map) - } else { - None - }, - } -} - -/// Builds a name resolution walker. -fn create_resolver<'a, 'tcx>(session: &'a Session, - ast_map: &'a hir_map::Map<'tcx>, - krate: &'a Crate, - make_glob_map: MakeGlobMap, - arenas: &'a ResolverArenas<'a>) - -> Resolver<'a, 'tcx> { - let mut resolver = Resolver::new(session, ast_map, make_glob_map, arenas); resolver.build_reduced_graph(krate); + resolve_imports::resolve_imports(resolver); + resolver.resolve_crate(krate); - resolve_imports::resolve_imports(&mut resolver); + check_unused::check_crate(resolver, krate); + resolver.report_privacy_errors(); +} - resolver +pub fn with_resolver<'a, T, F>(session: &'a Session, + definitions: &'a mut Definitions, + make_glob_map: MakeGlobMap, + f: F) -> T + where F: for<'b> FnOnce(Resolver<'b>) -> T, +{ + let arenas = Resolver::arenas(); + let resolver = Resolver::new(session, definitions, make_glob_map, &arenas); + f(resolver) } __build_diagnostic_array! { librustc_resolve, DIAGNOSTICS } diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs index e37dd4cbc6e..9bd16117f9a 100644 --- a/src/librustc_resolve/resolve_imports.rs +++ b/src/librustc_resolve/resolve_imports.rs @@ -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); } } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 0b3a0c19dac..e5fc84037ce 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -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 { diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs index 81fd1128afa..fc548924e29 100644 --- a/src/librustdoc/test.rs +++ b/src/librustdoc/test.rs @@ -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); diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index bf1c305e206..d1ad330c58c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -551,6 +551,44 @@ impl fmt::Debug for Pat { } } +impl Pat { + pub fn walk(&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 }` diff --git a/src/test/compile-fail/issue-23716.rs b/src/test/compile-fail/issue-23716.rs index c54f901199b..31604e2fdd3 100644 --- a/src/test/compile-fail/issue-23716.rs +++ b/src/test/compile-fail/issue-23716.rs @@ -16,7 +16,6 @@ fn bar(foo: i32) {} mod submod { pub static answer: i32 = 42; - //~^ NOTE static variable defined here } use self::submod::answer; diff --git a/src/test/run-make/execution-engine/test.rs b/src/test/run-make/execution-engine/test.rs index b9a45c09626..98412c08df5 100644 --- a/src/test/run-make/execution-engine/test.rs +++ b/src/test/run-make/execution-engine/test.rs @@ -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); diff --git a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs index c241241e18b..0717af98b30 100644 --- a/src/test/run-make/pretty-expanded-hygiene/input.pp.rs +++ b/src/test/run-make/pretty-expanded-hygiene/input.pp.rs @@ -14,3 +14,5 @@ fn bar /* 62#0 */() { let x /* 59#2 */ = 1; y /* 61#4 */ + x /* 59#5 */ } + +fn y /* 61#0 */() { } diff --git a/src/test/run-make/pretty-expanded-hygiene/input.rs b/src/test/run-make/pretty-expanded-hygiene/input.rs index 56783b56099..422fbdb0884 100644 --- a/src/test/run-make/pretty-expanded-hygiene/input.rs +++ b/src/test/run-make/pretty-expanded-hygiene/input.rs @@ -20,3 +20,5 @@ fn bar() { let x = 1; foo!(x) } + +fn y() {}