diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 25ccfb8d6bc..f10760f89f7 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, DefMap, PathResolution}; use std::collections::BTreeMap; use std::iter; @@ -63,19 +64,25 @@ 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: Option>, +} + +pub trait Resolver { + fn resolve_generated_global_path(&mut self, path: &hir::Path, is_value: bool) -> Def; + + fn def_map(&mut self) -> &mut DefMap; + // We must keep the set of definitions up to date as we add nodes that weren't in the AST. + fn definitions(&mut self) -> &mut Definitions; } 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,8 +97,8 @@ impl<'a, 'hir> LoweringContext<'a> { LoweringContext { crate_root: crate_root, id_assigner: id_assigner, - definitions: Some(defs), parent_def: Cell::new(None), + resolver: Some(RefCell::new(resolver)), } } @@ -101,8 +108,8 @@ impl<'a, 'hir> LoweringContext<'a> { LoweringContext { crate_root: None, id_assigner: id_assigner, - definitions: None, parent_def: Cell::new(None), + resolver: None, } } @@ -120,7 +127,7 @@ impl<'a, 'hir> LoweringContext<'a> { } fn with_parent_def T>(&self, parent_id: NodeId, f: F) -> T { - if self.definitions.is_none() { + if self.resolver.is_none() { // This should only be used for testing. return f(); } @@ -134,8 +141,22 @@ impl<'a, 'hir> LoweringContext<'a> { } fn get_def(&self, id: NodeId) -> DefIndex { - let defs = self.definitions.unwrap().borrow(); - defs.opt_def_index(id).unwrap() + let mut resolver = self.resolver.as_ref().unwrap().borrow_mut(); + resolver.definitions().opt_def_index(id).unwrap() + } + + fn record_def(&self, id: NodeId, def: Def) { + if let Some(ref resolver) = self.resolver { + resolver.borrow_mut().def_map().insert(id, PathResolution { base_def: def, depth: 0 }); + } + } + + fn resolve_generated_global_path(&self, path: &hir::Path, is_value: bool) -> Def { + if let Some(ref resolver) = self.resolver { + resolver.borrow_mut().resolve_generated_global_path(path, is_value) + } else { + Def::Err + } } } @@ -999,7 +1020,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 +1031,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 +1065,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], @@ -1489,6 +1510,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 = { @@ -1496,7 +1521,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, @@ -1520,13 +1545,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P { 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 = { @@ -1550,13 +1569,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()); @@ -1583,7 +1599,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) @@ -1592,11 +1608,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) }; @@ -1606,8 +1623,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); @@ -1747,8 +1763,13 @@ 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); + if let Some(ref resolver) = lctx.resolver { + let def_id = resolver.borrow_mut().definitions().local_def_id(binding); + lctx.record_def(expr.id, Def::Local(def_id, binding)); + } + expr } fn expr_mut_addr_of(lctx: &LoweringContext, span: Span, e: P, @@ -1758,7 +1779,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.resolve_generated_global_path(&path, true); + let expr = expr(lctx, path.span, hir::ExprPath(None, path), attrs); + lctx.record_def(expr.id, def); + expr } fn expr_match(lctx: &LoweringContext, @@ -1787,7 +1811,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.resolve_generated_global_path(&path, false); + let expr = expr(lctx, sp, hir::ExprStruct(path, fields, e), attrs); + lctx.record_def(expr.id, def); + expr + } fn expr(lctx: &LoweringContext, span: Span, node: hir::Expr_, @@ -1806,12 +1834,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, @@ -1821,7 +1850,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 { @@ -1871,12 +1900,15 @@ fn pat_enum(lctx: &LoweringContext, path: hir::Path, subpats: hir::HirVec>) -> P { + let def = lctx.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.record_def(pat.id, def); + pat } fn pat_ident(lctx: &LoweringContext, span: Span, ident: hir::Ident) -> P { @@ -1897,11 +1929,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)); + if let Some(ref resolver) = lctx.resolver { + let def_index = + resolver.borrow_mut().definitions() + .create_def_with_parent(lctx.parent_def.get(), + pat.id, + DefPathData::Binding(ident.name)); + lctx.record_def(pat.id, Def::Local(DefId::local(def_index), pat.id)); } pat diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index efe899a78fd..ebb6cf709ce 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -154,12 +154,19 @@ pub fn compile_input(sess: &Session, "early lint checks", || lint::check_ast_crate(sess, &expanded_crate)); - let (analysis, resolutions) = { - resolve::with_resolver(sess, &defs.borrow(), control.make_glob_map, |mut resolver| { + let (analysis, resolutions, mut hir_forest) = { + let defs = &mut *defs.borrow_mut(); + resolve::with_resolver(sess, defs, control.make_glob_map, |mut resolver| { time(sess.time_passes(), "name resolution", || { resolve::resolve_crate(&mut resolver, &expanded_crate); }); + // Lower ast -> hir. + let hir_forest = time(sess.time_passes(), "lowering ast -> hir", || { + let lcx = LoweringContext::new(sess, Some(&expanded_crate), &mut resolver); + hir_map::Forest::new(lower_crate(&lcx, &expanded_crate), dep_graph) + }); + (ty::CrateAnalysis { export_map: resolver.export_map, access_levels: AccessLevels::default(), @@ -171,17 +178,10 @@ pub fn compile_input(sess: &Session, freevars: resolver.freevars, trait_map: resolver.trait_map, maybe_unused_trait_imports: resolver.maybe_unused_trait_imports, - }) + }, hir_forest) }) }; - // 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)); - // Discard MTWT tables that aren't required past lowering to HIR. if !keep_mtwt_tables(sess) { syntax::ext::mtwt::clear_tables(); @@ -190,6 +190,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)); diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs index 2ed35cdd0ad..8f1fa2f7aa8 100644 --- a/src/librustc_resolve/lib.rs +++ b/src/librustc_resolve/lib.rs @@ -44,7 +44,7 @@ use self::BareIdentifierPatternResolution::*; use self::ParentLink::*; use rustc::hir::map::Definitions; -use rustc::hir::{PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr}; +use rustc::hir::{self, PrimTy, TyBool, TyChar, TyFloat, TyInt, TyUint, TyStr}; use rustc::session::Session; use rustc::lint; use rustc::hir::def::*; @@ -962,7 +962,7 @@ impl PrimitiveTypeTable { pub struct Resolver<'a> { session: &'a Session, - definitions: &'a Definitions, + definitions: &'a mut Definitions, graph_root: Module<'a>, @@ -1082,9 +1082,49 @@ impl<'a> ty::NodeIdTree for Resolver<'a> { } } +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 def_map(&mut self) -> &mut DefMap { + &mut self.def_map + } + fn definitions(&mut self) -> &mut Definitions { + 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, - definitions: &'a Definitions, + definitions: &'a mut Definitions, make_glob_map: MakeGlobMap, arenas: &'a ResolverArenas<'a>) -> Resolver<'a> { @@ -2721,19 +2761,12 @@ impl<'a> Resolver<'a> { /// Invariant: This must be called only during main resolution, not during /// import resolution. - fn resolve_crate_relative_path(&mut self, - span: Span, - segments: &[ast::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; @@ -2762,7 +2795,7 @@ impl<'a> Resolver<'a> { } } - 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); @@ -3588,7 +3621,7 @@ pub fn resolve_crate<'a, 'b>(resolver: &'b mut Resolver<'a>, krate: &'b Crate) { } pub fn with_resolver<'a, T, F>(session: &'a Session, - definitions: &'a Definitions, + definitions: &'a mut Definitions, make_glob_map: MakeGlobMap, f: F) -> T where F: for<'b> FnOnce(Resolver<'b>) -> T,