diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs index 94da10d33f8..b5a6ba3555d 100644 --- a/src/librustc/hir/intravisit.rs +++ b/src/librustc/hir/intravisit.rs @@ -67,6 +67,14 @@ impl<'a> FnKind<'a> { } } +/// Specifies what nested things a visitor wants to visit. Currently there are +/// two modes: `OnlyBodies` descends into item bodies, but not into nested +/// items; `All` descends into item bodies and nested items. +pub enum NestedVisitMode { + OnlyBodies, + All +} + /// Each method of the Visitor trait is a hook to be potentially /// overridden. Each method's default implementation recursively visits /// the substructure of the input via the corresponding `walk` method; @@ -102,7 +110,7 @@ pub trait Visitor<'v> : Sized { /// `panic!()`. This way, if a new `visit_nested_XXX` variant is /// added in the future, we will see the panic in your code and /// fix it appropriately. - fn nested_visit_map(&mut self) -> Option<&Map<'v>> { + fn nested_visit_map(&mut self) -> Option<(&Map<'v>, NestedVisitMode)> { None } @@ -116,7 +124,7 @@ pub trait Visitor<'v> : Sized { /// but cannot supply a `Map`; see `nested_visit_map` for advice. #[allow(unused_variables)] fn visit_nested_item(&mut self, id: ItemId) { - let opt_item = self.nested_visit_map() + let opt_item = map_for_item(self) .map(|map| map.expect_item(id.id)); if let Some(item) = opt_item { self.visit_item(item); @@ -128,13 +136,25 @@ pub trait Visitor<'v> : Sized { /// method. #[allow(unused_variables)] fn visit_nested_impl_item(&mut self, id: ImplItemId) { - let opt_item = self.nested_visit_map() + let opt_item = map_for_item(self) .map(|map| map.impl_item(id)); if let Some(item) = opt_item { self.visit_impl_item(item); } } + /// Invoked to visit the body of a function, method or closure. Like + /// visit_nested_item, does nothing by default unless you override + /// `nested_visit_map` to return `Some(_)`, in which case it will walk the + /// body. + fn visit_body(&mut self, id: ExprId) { + let opt_expr = map_for_body(self) + .map(|map| map.expr(id)); + if let Some(expr) = opt_expr { + self.visit_expr(expr); + } + } + /// Visit the top-level item and (optionally) nested items / impl items. See /// `visit_nested_item` for details. fn visit_item(&mut self, i: &'v Item) { @@ -200,7 +220,7 @@ pub trait Visitor<'v> : Sized { fn visit_where_predicate(&mut self, predicate: &'v WherePredicate) { walk_where_predicate(self, predicate) } - fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: &'v Expr, s: Span, id: NodeId) { + fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, b: ExprId, s: Span, id: NodeId) { walk_fn(self, fk, fd, b, s, id) } fn visit_trait_item(&mut self, ti: &'v TraitItem) { @@ -279,6 +299,19 @@ pub trait Visitor<'v> : Sized { } } +fn map_for_body<'v, V: Visitor<'v>>(visitor: &mut V) -> Option<&Map<'v>> { + visitor.nested_visit_map().map(|(map, _mode)| map) +} + +fn map_for_item<'v, V: Visitor<'v>>(visitor: &mut V) -> Option<&Map<'v>> { + visitor.nested_visit_map().and_then(|(map, mode)| { + match mode { + NestedVisitMode::OnlyBodies => None, + NestedVisitMode::All => Some(map) + } + }) +} + pub fn walk_opt_name<'v, V: Visitor<'v>>(visitor: &mut V, span: Span, opt_name: Option) { if let Some(name) = opt_name { visitor.visit_name(span, name); @@ -363,7 +396,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { visitor.visit_ty(typ); visitor.visit_expr(expr); } - ItemFn(ref declaration, unsafety, constness, abi, ref generics, ref body) => { + ItemFn(ref declaration, unsafety, constness, abi, ref generics, body_id) => { visitor.visit_fn(FnKind::ItemFn(item.name, generics, unsafety, @@ -372,7 +405,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) { &item.vis, &item.attrs), declaration, - body, + body_id, item.span, item.id) } @@ -697,13 +730,25 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<' pub fn walk_fn<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<'v>, function_declaration: &'v FnDecl, - function_body: &'v Expr, + body_id: ExprId, _span: Span, id: NodeId) { visitor.visit_id(id); walk_fn_decl(visitor, function_declaration); walk_fn_kind(visitor, function_kind); - visitor.visit_expr(function_body) + visitor.visit_body(body_id) +} + +pub fn walk_fn_with_body<'v, V: Visitor<'v>>(visitor: &mut V, + function_kind: FnKind<'v>, + function_declaration: &'v FnDecl, + body: &'v Expr, + _span: Span, + id: NodeId) { + visitor.visit_id(id); + walk_fn_decl(visitor, function_declaration); + walk_fn_kind(visitor, function_kind); + visitor.visit_expr(body) } pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v TraitItem) { @@ -720,13 +765,13 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai visitor.visit_generics(&sig.generics); walk_fn_decl(visitor, &sig.decl); } - MethodTraitItem(ref sig, Some(ref body)) => { + MethodTraitItem(ref sig, Some(body_id)) => { visitor.visit_fn(FnKind::Method(trait_item.name, sig, None, &trait_item.attrs), &sig.decl, - body, + body_id, trait_item.span, trait_item.id); } @@ -752,13 +797,13 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt visitor.visit_ty(ty); visitor.visit_expr(expr); } - ImplItemKind::Method(ref sig, ref body) => { + ImplItemKind::Method(ref sig, body_id) => { visitor.visit_fn(FnKind::Method(impl_item.name, sig, Some(&impl_item.vis), &impl_item.attrs), &sig.decl, - body, + body_id, impl_item.span, impl_item.id); } @@ -883,7 +928,7 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) { visitor.visit_expr(subexpression); walk_list!(visitor, visit_arm, arms); } - ExprClosure(_, ref function_declaration, ref body, _fn_decl_span) => { + ExprClosure(_, ref function_declaration, body, _fn_decl_span) => { visitor.visit_fn(FnKind::Closure(&expression.attrs), function_declaration, body, @@ -998,13 +1043,14 @@ impl IdRange { } -pub struct IdRangeComputingVisitor { - pub result: IdRange, +pub struct IdRangeComputingVisitor<'a, 'ast: 'a> { + result: IdRange, + map: &'a map::Map<'ast>, } -impl IdRangeComputingVisitor { - pub fn new() -> IdRangeComputingVisitor { - IdRangeComputingVisitor { result: IdRange::max() } +impl<'a, 'ast> IdRangeComputingVisitor<'a, 'ast> { + pub fn new(map: &'a map::Map<'ast>) -> IdRangeComputingVisitor<'a, 'ast> { + IdRangeComputingVisitor { result: IdRange::max(), map: map } } pub fn result(&self) -> IdRange { @@ -1012,20 +1058,25 @@ impl IdRangeComputingVisitor { } } -impl<'v> Visitor<'v> for IdRangeComputingVisitor { +impl<'a, 'ast> Visitor<'ast> for IdRangeComputingVisitor<'a, 'ast> { + fn nested_visit_map(&mut self) -> Option<(&Map<'ast>, NestedVisitMode)> { + Some((&self.map, NestedVisitMode::OnlyBodies)) + } + fn visit_id(&mut self, id: NodeId) { self.result.add(id); } } /// Computes the id range for a single fn body, ignoring nested items. -pub fn compute_id_range_for_fn_body(fk: FnKind, - decl: &FnDecl, - body: &Expr, - sp: Span, - id: NodeId) - -> IdRange { - let mut visitor = IdRangeComputingVisitor::new(); - visitor.visit_fn(fk, decl, body, sp, id); +pub fn compute_id_range_for_fn_body<'v>(fk: FnKind<'v>, + decl: &'v FnDecl, + body: &'v Expr, + sp: Span, + id: NodeId, + map: &map::Map<'v>) + -> IdRange { + let mut visitor = IdRangeComputingVisitor::new(map); + walk_fn_with_body(&mut visitor, fk, decl, body, sp, id); visitor.result() } diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index 7ea870e4300..ccf94e0b803 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -845,12 +845,14 @@ impl<'a> LoweringContext<'a> { } ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => { let body = self.lower_block(body); + let body = self.expr_block(body, ThinVec::new()); + let body_id = self.record_expr(body); hir::ItemFn(self.lower_fn_decl(decl), self.lower_unsafety(unsafety), self.lower_constness(constness), abi, self.lower_generics(generics), - P(self.expr_block(body, ThinVec::new()))) + body_id) } ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)), ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)), @@ -917,7 +919,8 @@ impl<'a> LoweringContext<'a> { hir::MethodTraitItem(this.lower_method_sig(sig), body.as_ref().map(|x| { let body = this.lower_block(x); - P(this.expr_block(body, ThinVec::new())) + let expr = this.expr_block(body, ThinVec::new()); + this.record_expr(expr) })) } TraitItemKind::Type(ref bounds, ref default) => { @@ -945,8 +948,9 @@ impl<'a> LoweringContext<'a> { } ImplItemKind::Method(ref sig, ref body) => { let body = this.lower_block(body); - hir::ImplItemKind::Method(this.lower_method_sig(sig), - P(this.expr_block(body, ThinVec::new()))) + let expr = this.expr_block(body, ThinVec::new()); + let expr_id = this.record_expr(expr); + hir::ImplItemKind::Method(this.lower_method_sig(sig), expr_id) } ImplItemKind::Type(ref ty) => hir::ImplItemKind::Type(this.lower_ty(ty)), ImplItemKind::Macro(..) => panic!("Shouldn't exist any more"), @@ -1395,9 +1399,10 @@ impl<'a> LoweringContext<'a> { } ExprKind::Closure(capture_clause, ref decl, ref body, fn_decl_span) => { self.with_parent_def(e.id, |this| { + let expr = this.lower_expr(body); hir::ExprClosure(this.lower_capture_clause(capture_clause), this.lower_fn_decl(decl), - P(this.lower_expr(body)), + this.record_expr(expr), fn_decl_span) }) } diff --git a/src/librustc/hir/map/blocks.rs b/src/librustc/hir/map/blocks.rs index 325a90ea91e..0adeb90e697 100644 --- a/src/librustc/hir/map/blocks.rs +++ b/src/librustc/hir/map/blocks.rs @@ -48,7 +48,7 @@ pub trait MaybeFnLike { fn is_fn_like(&self) -> bool; } /// Components shared by fn-like things (fn items, methods, closures). pub struct FnParts<'a> { pub decl: &'a FnDecl, - pub body: &'a Expr, + pub body: ast::ExprId, pub kind: FnKind<'a>, pub span: Span, pub id: NodeId, @@ -115,7 +115,7 @@ struct ItemFnParts<'a> { abi: abi::Abi, vis: &'a ast::Visibility, generics: &'a ast::Generics, - body: &'a Expr, + body: ast::ExprId, id: NodeId, span: Span, attrs: &'a [Attribute], @@ -125,14 +125,14 @@ struct ItemFnParts<'a> { /// for use when implementing FnLikeNode operations. struct ClosureParts<'a> { decl: &'a FnDecl, - body: &'a Expr, + body: ast::ExprId, id: NodeId, span: Span, attrs: &'a [Attribute], } impl<'a> ClosureParts<'a> { - fn new(d: &'a FnDecl, b: &'a Expr, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self { + fn new(d: &'a FnDecl, b: ast::ExprId, id: NodeId, s: Span, attrs: &'a [Attribute]) -> Self { ClosureParts { decl: d, body: b, @@ -172,9 +172,9 @@ impl<'a> FnLikeNode<'a> { } } - pub fn body(self) -> &'a Expr { - self.handle(|i: ItemFnParts<'a>| &*i.body, - |_, _, _: &'a ast::MethodSig, _, body: &'a ast::Expr, _, _| body, + pub fn body(self) -> ast::ExprId { + self.handle(|i: ItemFnParts<'a>| i.body, + |_, _, _: &'a ast::MethodSig, _, body: ast::ExprId, _, _| body, |c: ClosureParts<'a>| c.body) } @@ -215,7 +215,7 @@ impl<'a> FnLikeNode<'a> { Name, &'a ast::MethodSig, Option<&'a ast::Visibility>, - &'a ast::Expr, + ast::ExprId, Span, &'a [Attribute]) -> A, @@ -223,13 +223,13 @@ impl<'a> FnLikeNode<'a> { { match self.node { map::NodeItem(i) => match i.node { - ast::ItemFn(ref decl, unsafety, constness, abi, ref generics, ref block) => + ast::ItemFn(ref decl, unsafety, constness, abi, ref generics, block) => item_fn(ItemFnParts { id: i.id, name: i.name, decl: &decl, unsafety: unsafety, - body: &block, + body: block, generics: generics, abi: abi, vis: &i.vis, @@ -240,14 +240,14 @@ impl<'a> FnLikeNode<'a> { _ => bug!("item FnLikeNode that is not fn-like"), }, map::NodeTraitItem(ti) => match ti.node { - ast::MethodTraitItem(ref sig, Some(ref body)) => { + ast::MethodTraitItem(ref sig, Some(body)) => { method(ti.id, ti.name, sig, None, body, ti.span, &ti.attrs) } _ => bug!("trait method FnLikeNode that is not fn-like"), }, map::NodeImplItem(ii) => { match ii.node { - ast::ImplItemKind::Method(ref sig, ref body) => { + ast::ImplItemKind::Method(ref sig, body) => { method(ii.id, ii.name, sig, Some(&ii.vis), body, ii.span, &ii.attrs) } _ => { @@ -256,8 +256,8 @@ impl<'a> FnLikeNode<'a> { } } map::NodeExpr(e) => match e.node { - ast::ExprClosure(_, ref decl, ref block, _fn_decl_span) => - closure(ClosureParts::new(&decl, &block, e.id, e.span, &e.attrs)), + ast::ExprClosure(_, ref decl, block, _fn_decl_span) => + closure(ClosureParts::new(&decl, block, e.id, e.span, &e.attrs)), _ => bug!("expr FnLikeNode that is not fn-like"), }, _ => bug!("other FnLikeNode that is not fn-like"), diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs index 26fd2b736a4..6033278575d 100644 --- a/src/librustc/hir/map/collector.rs +++ b/src/librustc/hir/map/collector.rs @@ -10,7 +10,8 @@ use super::*; -use hir::intravisit::Visitor; +use hir::*; +use hir::intravisit::{Visitor, NestedVisitMode}; use hir::def_id::DefId; use middle::cstore::InlinedItem; use std::iter::repeat; @@ -91,7 +92,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { /// deep walking so that we walk nested items in the context of /// their outer items. - fn nested_visit_map(&mut self) -> Option<&map::Map<'ast>> { + fn nested_visit_map(&mut self) -> Option<(&map::Map<'ast>, NestedVisitMode)> { panic!("visit_nested_xxx must be manually implemented in this visitor") } @@ -106,6 +107,10 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { self.visit_impl_item(self.krate.impl_item(item_id)) } + fn visit_body(&mut self, id: ExprId) { + self.visit_expr(self.krate.expr(id)) + } + fn visit_item(&mut self, i: &'ast Item) { debug!("visit_item: {:?}", i); @@ -209,7 +214,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> { } fn visit_fn(&mut self, fk: intravisit::FnKind<'ast>, fd: &'ast FnDecl, - b: &'ast Expr, s: Span, id: NodeId) { + b: ExprId, s: Span, id: NodeId) { assert_eq!(self.parent_node, id); intravisit::walk_fn(self, fk, fd, b, s, id); } diff --git a/src/librustc/hir/map/def_collector.rs b/src/librustc/hir/map/def_collector.rs index a08060e7927..a6d7c79e346 100644 --- a/src/librustc/hir/map/def_collector.rs +++ b/src/librustc/hir/map/def_collector.rs @@ -327,6 +327,12 @@ impl<'a> visit::Visitor for DefCollector<'a> { // We walk the HIR rather than the AST when reading items from metadata. impl<'ast> intravisit::Visitor<'ast> for DefCollector<'ast> { + fn visit_body(&mut self, id: hir::ExprId) { + if let Some(krate) = self.hir_crate { + self.visit_expr(krate.expr(id)); + } + } + fn visit_item(&mut self, i: &'ast hir::Item) { debug!("visit_item: {:?}", i); diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index b9763e6ea0d..7ef98fcce7e 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -655,6 +655,10 @@ impl<'ast> Map<'ast> { } } + pub fn expr(&self, id: ExprId) -> &'ast Expr { + self.expect_expr(id.node_id()) + } + /// Returns the name associated with the given NodeId's AST. pub fn name(&self, id: NodeId) -> Name { match self.get(id) { diff --git a/src/librustc/hir/mod.rs b/src/librustc/hir/mod.rs index eda8e34516e..f66e6788ee7 100644 --- a/src/librustc/hir/mod.rs +++ b/src/librustc/hir/mod.rs @@ -460,6 +460,10 @@ impl Crate { visitor.visit_impl_item(impl_item); } } + + pub fn expr(&self, id: ExprId) -> &Expr { + &self.exprs[&id] + } } /// A macro definition, in this crate or imported from another. @@ -925,7 +929,7 @@ pub enum Expr_ { /// A closure (for example, `move |a, b, c| {a + b + c}`). /// /// The final span is the span of the argument block `|...|` - ExprClosure(CaptureClause, P, P, Span), + ExprClosure(CaptureClause, P, ExprId, Span), /// A block (`{ ... }`) ExprBlock(P), @@ -1079,7 +1083,7 @@ pub enum TraitItem_ { /// must contain a value) ConstTraitItem(P, Option>), /// A method with an optional body - MethodTraitItem(MethodSig, Option>), + MethodTraitItem(MethodSig, Option), /// An associated type with (possibly empty) bounds and optional concrete /// type TypeTraitItem(TyParamBounds, Option>), @@ -1112,7 +1116,7 @@ pub enum ImplItemKind { /// of the expression Const(P, P), /// A method implementation with the given signature and body - Method(MethodSig, P), + Method(MethodSig, ExprId), /// An associated type Type(P), } @@ -1557,7 +1561,7 @@ pub enum Item_ { /// A `const` item ItemConst(P, P), /// A function declaration - ItemFn(P, Unsafety, Constness, Abi, Generics, P), + ItemFn(P, Unsafety, Constness, Abi, Generics, ExprId), /// A module ItemMod(Mod), /// An external module diff --git a/src/librustc/hir/print.rs b/src/librustc/hir/print.rs index 31a85391193..74920b13280 100644 --- a/src/librustc/hir/print.rs +++ b/src/librustc/hir/print.rs @@ -644,6 +644,15 @@ impl<'a> State<'a> { } } + pub fn print_expr_id(&mut self, expr_id: &hir::ExprId) -> io::Result<()> { + if let Some(krate) = self.krate { + let expr = &krate.exprs[expr_id]; + self.print_expr(expr) + } else { + Ok(()) + } + } + /// Pretty-print an item pub fn print_item(&mut self, item: &hir::Item) -> io::Result<()> { self.hardbreak_if_not_bol()?; @@ -729,7 +738,7 @@ impl<'a> State<'a> { word(&mut self.s, " ")?; self.end()?; // need to close a box self.end()?; // need to close a box - self.print_expr(&body)?; + self.print_expr_id(body)?; } hir::ItemMod(ref _mod) => { self.head(&visibility_qualified(&item.vis, "mod"))?; @@ -1020,7 +1029,7 @@ impl<'a> State<'a> { self.nbsp()?; self.end()?; // need to close a box self.end()?; // need to close a box - self.print_expr(body)?; + self.print_expr_id(body)?; } else { word(&mut self.s, ";")?; } @@ -1065,7 +1074,7 @@ impl<'a> State<'a> { self.nbsp()?; self.end()?; // need to close a box self.end()?; // need to close a box - self.print_expr(body)?; + self.print_expr_id(body)?; } hir::ImplItemKind::Type(ref ty) => { self.print_associated_type(ii.name, None, Some(ty))?; @@ -1432,7 +1441,7 @@ impl<'a> State<'a> { space(&mut self.s)?; // this is a bare expression - self.print_expr(body)?; + self.print_expr_id(body)?; self.end()?; // need to close a box // a box will be closed by print_expr, but we didn't want an overall diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs index 41c8d413486..799c7e0cc84 100644 --- a/src/librustc/lint/context.rs +++ b/src/librustc/lint/context.rs @@ -719,10 +719,10 @@ impl<'a, 'tcx> LateContext<'a, 'tcx> { } } - fn visit_ids(&mut self, f: F) - where F: FnOnce(&mut IdVisitor) + fn visit_ids<'b, F: 'b>(&'b mut self, f: F) + where F: FnOnce(&mut IdVisitor<'b, 'a, 'tcx>) { - let mut v = IdVisitor { + let mut v = IdVisitor::<'b, 'a, 'tcx> { cx: self }; f(&mut v); @@ -791,8 +791,8 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { /// Because lints are scoped lexically, we want to walk nested /// items in the context of the outer item, so enable /// deep-walking. - fn nested_visit_map(&mut self) -> Option<&hir::map::Map<'tcx>> { - Some(&self.tcx.map) + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, hir_visit::NestedVisitMode)> { + Some((&self.tcx.map, hir_visit::NestedVisitMode::All)) } fn visit_item(&mut self, it: &'tcx hir::Item) { @@ -835,9 +835,10 @@ impl<'a, 'tcx> hir_visit::Visitor<'tcx> for LateContext<'a, 'tcx> { } fn visit_fn(&mut self, fk: hir_visit::FnKind<'tcx>, decl: &'tcx hir::FnDecl, - body: &'tcx hir::Expr, span: Span, id: ast::NodeId) { + body_id: hir::ExprId, span: Span, id: ast::NodeId) { + let body = self.tcx.map.expr(body_id); run_lints!(self, check_fn, late_passes, fk, decl, body, span, id); - hir_visit::walk_fn(self, fk, decl, body, span, id); + hir_visit::walk_fn(self, fk, decl, body_id, span, id); run_lints!(self, check_fn_post, late_passes, fk, decl, body, span, id); } @@ -1107,7 +1108,11 @@ struct IdVisitor<'a, 'b: 'a, 'tcx: 'a+'b> { } // Output any lints that were previously added to the session. -impl<'a, 'b, 'tcx, 'v> hir_visit::Visitor<'v> for IdVisitor<'a, 'b, 'tcx> { +impl<'a, 'b, 'tcx> hir_visit::Visitor<'tcx> for IdVisitor<'a, 'b, 'tcx> { + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, hir_visit::NestedVisitMode)> { + Some((&self.cx.tcx.map, hir_visit::NestedVisitMode::OnlyBodies)) + } + fn visit_id(&mut self, id: ast::NodeId) { if let Some(lints) = self.cx.sess().lints.borrow_mut().remove(&id) { debug!("LateContext::visit_id: id={:?} lints={:?}", id, lints); @@ -1117,12 +1122,12 @@ impl<'a, 'b, 'tcx, 'v> hir_visit::Visitor<'v> for IdVisitor<'a, 'b, 'tcx> { } } - fn visit_trait_item(&mut self, _ti: &hir::TraitItem) { + fn visit_trait_item(&mut self, _ti: &'tcx hir::TraitItem) { // Do not recurse into trait or impl items automatically. These are // processed separately by calling hir_visit::walk_trait_item() } - fn visit_impl_item(&mut self, _ii: &hir::ImplItem) { + fn visit_impl_item(&mut self, _ii: &'tcx hir::ImplItem) { // See visit_trait_item() } } diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 618e2b05f13..575ac9773a7 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -15,7 +15,7 @@ use dep_graph::DepNode; use hir::map as ast_map; use hir::{self, PatKind}; -use hir::intravisit::{self, Visitor}; +use hir::intravisit::{self, Visitor, NestedVisitMode}; use hir::itemlikevisit::ItemLikeVisitor; use middle::privacy; @@ -175,7 +175,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } } - fn visit_node(&mut self, node: &ast_map::Node) { + fn visit_node(&mut self, node: &ast_map::Node<'tcx>) { let had_extern_repr = self.struct_has_extern_repr; self.struct_has_extern_repr = false; let had_inherited_pub_visibility = self.inherited_pub_visibility; @@ -220,9 +220,12 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { } } -impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for MarkSymbolVisitor<'a, 'tcx> { + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, NestedVisitMode)> { + Some((&self.tcx.map, NestedVisitMode::OnlyBodies)) + } - fn visit_variant_data(&mut self, def: &hir::VariantData, _: ast::Name, + fn visit_variant_data(&mut self, def: &'tcx hir::VariantData, _: ast::Name, _: &hir::Generics, _: ast::NodeId, _: syntax_pos::Span) { let has_extern_repr = self.struct_has_extern_repr; let inherited_pub_visibility = self.inherited_pub_visibility; @@ -234,7 +237,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { intravisit::walk_struct_def(self, def); } - fn visit_expr(&mut self, expr: &hir::Expr) { + fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { hir::ExprPath(ref qpath @ hir::QPath::TypeRelative(..)) => { let def = self.tcx.tables().qpath_def(qpath, expr.id); @@ -255,7 +258,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { intravisit::walk_expr(self, expr); } - fn visit_arm(&mut self, arm: &hir::Arm) { + fn visit_arm(&mut self, arm: &'tcx hir::Arm) { if arm.pats.len() == 1 { let variants = arm.pats[0].necessary_variants(); @@ -271,7 +274,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { } } - fn visit_pat(&mut self, pat: &hir::Pat) { + fn visit_pat(&mut self, pat: &'tcx hir::Pat) { match pat.node { PatKind::Struct(hir::QPath::Resolved(_, ref path), ref fields, _) => { self.handle_field_pattern_match(pat, path.def, fields); @@ -288,8 +291,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MarkSymbolVisitor<'a, 'tcx> { self.ignore_non_const_paths = false; } - fn visit_path(&mut self, path: &hir::Path, id: ast::NodeId) { - self.handle_definition(id, path.def); + fn visit_path(&mut self, path: &'tcx hir::Path, id: ast::NodeId) { + self.lookup_and_handle_definition(id); intravisit::walk_path(self, path); } } @@ -507,8 +510,8 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { /// on inner functions when the outer function is already getting /// an error. We could do this also by checking the parents, but /// this is how the code is setup and it seems harmless enough. - fn nested_visit_map(&mut self) -> Option<&hir::map::Map<'tcx>> { - Some(&self.tcx.map) + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, NestedVisitMode)> { + Some((&self.tcx.map, NestedVisitMode::All)) } fn visit_item(&mut self, item: &'tcx hir::Item) { @@ -562,12 +565,12 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { } intravisit::walk_expr(self, expr) } - hir::ImplItemKind::Method(_, ref body) => { + hir::ImplItemKind::Method(_, body_id) => { if !self.symbol_is_live(impl_item.id, None) { self.warn_dead_code(impl_item.id, impl_item.span, impl_item.name, "method"); } - intravisit::walk_expr(self, body) + self.visit_body(body_id) } hir::ImplItemKind::Type(..) => {} } @@ -576,10 +579,12 @@ impl<'a, 'tcx> Visitor<'tcx> for DeadVisitor<'a, 'tcx> { // Overwrite so that we don't warn the trait item itself. fn visit_trait_item(&mut self, trait_item: &'tcx hir::TraitItem) { match trait_item.node { - hir::ConstTraitItem(_, Some(ref body))| - hir::MethodTraitItem(_, Some(ref body)) => { + hir::ConstTraitItem(_, Some(ref body)) => { intravisit::walk_expr(self, body) } + hir::MethodTraitItem(_, Some(body_id)) => { + self.visit_body(body_id) + } hir::ConstTraitItem(_, None) | hir::MethodTraitItem(_, None) | hir::TypeTraitItem(..) => {} diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 1313a3504c0..57735b91ac5 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -21,7 +21,7 @@ use syntax::ast; use syntax_pos::Span; use hir::{self, PatKind}; use hir::def::Def; -use hir::intravisit::{self, FnKind, Visitor}; +use hir::intravisit::{self, FnKind, Visitor, NestedVisitMode}; #[derive(Copy, Clone)] struct UnsafeContext { @@ -92,9 +92,13 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> { } } -impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { - fn visit_fn(&mut self, fn_kind: FnKind<'v>, fn_decl: &'v hir::FnDecl, - block: &'v hir::Expr, span: Span, id: ast::NodeId) { +impl<'a, 'tcx> Visitor<'tcx> for EffectCheckVisitor<'a, 'tcx> { + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, NestedVisitMode)> { + Some((&self.tcx.map, NestedVisitMode::OnlyBodies)) + } + + fn visit_fn(&mut self, fn_kind: FnKind<'tcx>, fn_decl: &'tcx hir::FnDecl, + body_id: hir::ExprId, span: Span, id: ast::NodeId) { let (is_item_fn, is_unsafe_fn) = match fn_kind { FnKind::ItemFn(_, _, unsafety, ..) => @@ -111,12 +115,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { self.unsafe_context = UnsafeContext::new(SafeContext) } - intravisit::walk_fn(self, fn_kind, fn_decl, block, span, id); + intravisit::walk_fn(self, fn_kind, fn_decl, body_id, span, id); self.unsafe_context = old_unsafe_context } - fn visit_block(&mut self, block: &hir::Block) { + fn visit_block(&mut self, block: &'tcx hir::Block) { let old_unsafe_context = self.unsafe_context; match block.rules { hir::UnsafeBlock(source) => { @@ -155,7 +159,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { self.unsafe_context = old_unsafe_context } - fn visit_expr(&mut self, expr: &hir::Expr) { + fn visit_expr(&mut self, expr: &'tcx hir::Expr) { match expr.node { hir::ExprMethodCall(..) => { let method_call = MethodCall::expr(expr.id); @@ -212,7 +216,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { intravisit::walk_expr(self, expr); } - fn visit_pat(&mut self, pat: &hir::Pat) { + fn visit_pat(&mut self, pat: &'tcx hir::Pat) { if let PatKind::Struct(_, ref fields, _) = pat.node { if let ty::TyAdt(adt, ..) = self.tcx.tables().pat_ty(pat).sty { if adt.is_union() { diff --git a/src/librustc/middle/entry.rs b/src/librustc/middle/entry.rs index 65aedae347a..e927843a984 100644 --- a/src/librustc/middle/entry.rs +++ b/src/librustc/middle/entry.rs @@ -47,6 +47,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for EntryContext<'a, 'tcx> { find_item(item, self, at_root); } + fn visit_impl_item(&mut self, _impl_item: &'tcx ImplItem) { // entry fn is never an impl item } diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 0014d17abb7..5673ec05cf9 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -19,7 +19,7 @@ use ty::layout::{LayoutError, Pointer, SizeSkeleton}; use syntax::abi::Abi::RustIntrinsic; use syntax::ast; use syntax_pos::Span; -use hir::intravisit::{self, Visitor, FnKind}; +use hir::intravisit::{self, Visitor, FnKind, NestedVisitMode}; use hir; pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { @@ -34,7 +34,7 @@ struct ItemVisitor<'a, 'tcx: 'a> { } impl<'a, 'tcx> ItemVisitor<'a, 'tcx> { - fn visit_const(&mut self, item_id: ast::NodeId, expr: &hir::Expr) { + fn visit_const(&mut self, item_id: ast::NodeId, expr: &'tcx hir::Expr) { let param_env = ty::ParameterEnvironment::for_item(self.tcx, item_id); self.tcx.infer_ctxt(None, Some(param_env), Reveal::All).enter(|infcx| { let mut visitor = ExprVisitor { @@ -116,9 +116,13 @@ impl<'a, 'gcx, 'tcx> ExprVisitor<'a, 'gcx, 'tcx> { } } -impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for ItemVisitor<'a, 'tcx> { + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, NestedVisitMode)> { + Some((&self.tcx.map, NestedVisitMode::OnlyBodies)) + } + // const, static and N in [T; N]. - fn visit_expr(&mut self, expr: &hir::Expr) { + fn visit_expr(&mut self, expr: &'tcx hir::Expr) { self.tcx.infer_ctxt(None, None, Reveal::All).enter(|infcx| { let mut visitor = ExprVisitor { infcx: &infcx @@ -127,7 +131,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> { }); } - fn visit_trait_item(&mut self, item: &hir::TraitItem) { + fn visit_trait_item(&mut self, item: &'tcx hir::TraitItem) { if let hir::ConstTraitItem(_, Some(ref expr)) = item.node { self.visit_const(item.id, expr); } else { @@ -135,7 +139,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> { } } - fn visit_impl_item(&mut self, item: &hir::ImplItem) { + fn visit_impl_item(&mut self, item: &'tcx hir::ImplItem) { if let hir::ImplItemKind::Const(_, ref expr) = item.node { self.visit_const(item.id, expr); } else { @@ -143,8 +147,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> { } } - fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl, - b: &'v hir::Expr, s: Span, id: ast::NodeId) { + fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, + b: hir::ExprId, s: Span, id: ast::NodeId) { if let FnKind::Closure(..) = fk { span_bug!(s, "intrinsicck: closure outside of function") } @@ -158,8 +162,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> { } } -impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'gcx, 'tcx> { - fn visit_expr(&mut self, expr: &hir::Expr) { +impl<'a, 'gcx, 'tcx> Visitor<'gcx> for ExprVisitor<'a, 'gcx, 'tcx> { + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'gcx>, NestedVisitMode)> { + Some((&self.infcx.tcx.map, NestedVisitMode::OnlyBodies)) + } + + fn visit_expr(&mut self, expr: &'gcx hir::Expr) { let def = if let hir::ExprPath(ref qpath) = expr.node { self.infcx.tcx.tables().qpath_def(qpath, expr.id) } else { diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs index eb00238492e..ca28f1dae29 100644 --- a/src/librustc/middle/liveness.rs +++ b/src/librustc/middle/liveness.rs @@ -128,7 +128,7 @@ use syntax_pos::Span; use hir::Expr; use hir; use hir::print::{expr_to_string, block_to_string}; -use hir::intravisit::{self, Visitor, FnKind}; +use hir::intravisit::{self, Visitor, FnKind, NestedVisitMode}; /// For use with `propagate_through_loop`. enum LoopKind<'a> { @@ -182,14 +182,17 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt) -> String { } } -impl<'a, 'tcx, 'v> Visitor<'v> for IrMaps<'a, 'tcx> { - fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v hir::FnDecl, - b: &'v hir::Expr, s: Span, id: NodeId) { +impl<'a, 'tcx> Visitor<'tcx> for IrMaps<'a, 'tcx> { + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, NestedVisitMode)> { + Some((&self.tcx.map, NestedVisitMode::OnlyBodies)) + } + fn visit_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, + b: hir::ExprId, s: Span, id: NodeId) { visit_fn(self, fk, fd, b, s, id); } - fn visit_local(&mut self, l: &hir::Local) { visit_local(self, l); } - fn visit_expr(&mut self, ex: &Expr) { visit_expr(self, ex); } - fn visit_arm(&mut self, a: &hir::Arm) { visit_arm(self, a); } + fn visit_local(&mut self, l: &'tcx hir::Local) { visit_local(self, l); } + fn visit_expr(&mut self, ex: &'tcx Expr) { visit_expr(self, ex); } + fn visit_arm(&mut self, a: &'tcx hir::Arm) { visit_arm(self, a); } } pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { @@ -348,28 +351,31 @@ impl<'a, 'tcx> IrMaps<'a, 'tcx> { } } -impl<'a, 'tcx, 'v> Visitor<'v> for Liveness<'a, 'tcx> { - fn visit_fn(&mut self, _: FnKind<'v>, _: &'v hir::FnDecl, - _: &'v hir::Expr, _: Span, _: NodeId) { +impl<'a, 'tcx> Visitor<'tcx> for Liveness<'a, 'tcx> { + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, NestedVisitMode)> { + Some((&self.ir.tcx.map, NestedVisitMode::OnlyBodies)) + } + fn visit_fn(&mut self, _: FnKind<'tcx>, _: &'tcx hir::FnDecl, + _: hir::ExprId, _: Span, _: NodeId) { // do not check contents of nested fns } - fn visit_local(&mut self, l: &hir::Local) { + fn visit_local(&mut self, l: &'tcx hir::Local) { check_local(self, l); } - fn visit_expr(&mut self, ex: &Expr) { + fn visit_expr(&mut self, ex: &'tcx Expr) { check_expr(self, ex); } - fn visit_arm(&mut self, a: &hir::Arm) { + fn visit_arm(&mut self, a: &'tcx hir::Arm) { check_arm(self, a); } } -fn visit_fn(ir: &mut IrMaps, - fk: FnKind, - decl: &hir::FnDecl, - body: &hir::Expr, - sp: Span, - id: ast::NodeId) { +fn visit_fn<'a, 'tcx: 'a>(ir: &mut IrMaps<'a, 'tcx>, + fk: FnKind<'tcx>, + decl: &'tcx hir::FnDecl, + body_id: hir::ExprId, + sp: Span, + id: ast::NodeId) { debug!("visit_fn"); // swap in a new set of IR maps for this function body: @@ -387,7 +393,7 @@ fn visit_fn(ir: &mut IrMaps, // gather up the various local variables, significant expressions, // and so forth: - intravisit::walk_fn(&mut fn_maps, fk, decl, body, sp, id); + intravisit::walk_fn(&mut fn_maps, fk, decl, body_id, sp, id); // Special nodes and variables: // - exit_ln represents the end of the fn, either by return or panic @@ -400,6 +406,8 @@ fn visit_fn(ir: &mut IrMaps, clean_exit_var: fn_maps.add_variable(CleanExit) }; + let body = ir.tcx.map.expr(body_id); + // compute liveness let mut lsets = Liveness::new(&mut fn_maps, specials); let entry_ln = lsets.compute(body); @@ -410,7 +418,7 @@ fn visit_fn(ir: &mut IrMaps, lsets.warn_about_unused_args(decl, entry_ln); } -fn visit_local(ir: &mut IrMaps, local: &hir::Local) { +fn visit_local<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, local: &'tcx hir::Local) { local.pat.each_binding(|_, p_id, sp, path1| { debug!("adding local variable {}", p_id); let name = path1.node; @@ -423,7 +431,7 @@ fn visit_local(ir: &mut IrMaps, local: &hir::Local) { intravisit::walk_local(ir, local); } -fn visit_arm(ir: &mut IrMaps, arm: &hir::Arm) { +fn visit_arm<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, arm: &'tcx hir::Arm) { for pat in &arm.pats { pat.each_binding(|bm, p_id, sp, path1| { debug!("adding local variable {} from match with bm {:?}", @@ -439,7 +447,7 @@ fn visit_arm(ir: &mut IrMaps, arm: &hir::Arm) { intravisit::walk_arm(ir, arm); } -fn visit_expr(ir: &mut IrMaps, expr: &Expr) { +fn visit_expr<'a, 'tcx>(ir: &mut IrMaps<'a, 'tcx>, expr: &'tcx Expr) { match expr.node { // live nodes required for uses or definitions of variables: hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { @@ -923,7 +931,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { self.propagate_through_expr(&e, succ) } - hir::ExprClosure(.., ref blk, _) => { + hir::ExprClosure(.., blk_id, _) => { debug!("{} is an ExprClosure", expr_to_string(expr)); @@ -932,7 +940,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { loop. The next-node for a continue is the top of this loop. */ let node = self.live_node(expr.id, expr.span); - self.with_loop_nodes(blk.id, succ, node, |this| { + self.with_loop_nodes(blk_id.node_id(), succ, node, |this| { // the construction of a closure itself is not important, // but we have to consider the closed over variables. @@ -1354,7 +1362,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { // _______________________________________________________________________ // Checking for error conditions -fn check_local(this: &mut Liveness, local: &hir::Local) { +fn check_local<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, local: &'tcx hir::Local) { match local.init { Some(_) => { this.warn_about_unused_or_dead_vars_in_pat(&local.pat); @@ -1369,7 +1377,7 @@ fn check_local(this: &mut Liveness, local: &hir::Local) { intravisit::walk_local(this, local); } -fn check_arm(this: &mut Liveness, arm: &hir::Arm) { +fn check_arm<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, arm: &'tcx hir::Arm) { // only consider the first pattern; any later patterns must have // the same bindings, and we also consider the first pattern to be // the "authoritative" set of ids @@ -1379,7 +1387,7 @@ fn check_arm(this: &mut Liveness, arm: &hir::Arm) { intravisit::walk_arm(this, arm); } -fn check_expr(this: &mut Liveness, expr: &Expr) { +fn check_expr<'a, 'tcx>(this: &mut Liveness<'a, 'tcx>, expr: &'tcx Expr) { match expr.node { hir::ExprAssign(ref l, _) => { this.check_lvalue(&l); @@ -1469,7 +1477,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { } } - fn check_lvalue(&mut self, expr: &Expr) { + fn check_lvalue(&mut self, expr: &'tcx Expr) { match expr.node { hir::ExprPath(hir::QPath::Resolved(_, ref path)) => { if let Def::Local(def_id) = path.def { diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 8d3e734f8c3..4c3b102e540 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -705,7 +705,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { }; match fn_expr.node { - hir::ExprClosure(.., ref body, _) => body.id, + hir::ExprClosure(.., body_id, _) => body_id.node_id(), _ => bug!() } }; diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index b17d41e0fa5..f8a1b109d9d 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -28,7 +28,7 @@ use syntax::abi::Abi; use syntax::ast; use syntax::attr; use hir; -use hir::intravisit::Visitor; +use hir::intravisit::{Visitor, NestedVisitMode}; use hir::itemlikevisit::ItemLikeVisitor; use hir::intravisit; @@ -88,8 +88,12 @@ struct ReachableContext<'a, 'tcx: 'a> { any_library: bool, } -impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> { - fn visit_expr(&mut self, expr: &hir::Expr) { +impl<'a, 'tcx> Visitor<'tcx> for ReachableContext<'a, 'tcx> { + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, NestedVisitMode)> { + Some((&self.tcx.map, NestedVisitMode::OnlyBodies)) + } + + fn visit_expr(&mut self, expr: &'tcx hir::Expr) { let def = match expr.node { hir::ExprPath(ref qpath) => { Some(self.tcx.tables().qpath_def(qpath, expr.id)) @@ -216,7 +220,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { } } - fn propagate_node(&mut self, node: &ast_map::Node, + fn propagate_node(&mut self, node: &ast_map::Node<'tcx>, search_item: ast::NodeId) { if !self.any_library { // If we are building an executable, only explicitly extern @@ -244,9 +248,9 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { match *node { ast_map::NodeItem(item) => { match item.node { - hir::ItemFn(.., ref body) => { + hir::ItemFn(.., body) => { if item_might_be_inlined(&item) { - self.visit_expr(body); + self.visit_body(body); } } @@ -274,10 +278,12 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::MethodTraitItem(_, None) => { // Keep going, nothing to get exported } - hir::ConstTraitItem(_, Some(ref body)) | - hir::MethodTraitItem(_, Some(ref body)) => { + hir::ConstTraitItem(_, Some(ref body)) => { self.visit_expr(body); } + hir::MethodTraitItem(_, Some(body_id)) => { + self.visit_body(body_id); + } hir::TypeTraitItem(..) => {} } } @@ -286,10 +292,10 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { hir::ImplItemKind::Const(_, ref expr) => { self.visit_expr(&expr); } - hir::ImplItemKind::Method(ref sig, ref body) => { + hir::ImplItemKind::Method(ref sig, body) => { let did = self.tcx.map.get_parent_did(search_item); if method_might_be_inlined(self.tcx, sig, impl_item, did) { - self.visit_expr(body) + self.visit_body(body) } } hir::ImplItemKind::Type(_) => {} diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 0dbde2d21ca..49a2b4f17ed 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -31,7 +31,7 @@ use syntax::ast::{self, NodeId}; use syntax_pos::Span; use hir; -use hir::intravisit::{self, Visitor, FnKind}; +use hir::intravisit::{self, Visitor, FnKind, NestedVisitMode}; use hir::{Block, Item, FnDecl, Arm, Pat, PatKind, Stmt, Expr, Local}; #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, @@ -302,7 +302,7 @@ pub struct Context { parent: CodeExtent } -struct RegionResolutionVisitor<'a> { +struct RegionResolutionVisitor<'ast: 'a, 'a> { sess: &'a Session, // Generated maps: @@ -310,6 +310,8 @@ struct RegionResolutionVisitor<'a> { cx: Context, + map: &'a ast_map::Map<'ast>, + /// `terminating_scopes` is a set containing the ids of each /// statement, or conditional/repeating expression. These scopes /// are calling "terminating scopes" because, when attempting to @@ -660,7 +662,7 @@ fn record_var_lifetime(visitor: &mut RegionResolutionVisitor, } } -fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &hir::Block) { +fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, blk: &'tcx hir::Block) { debug!("resolve_block(blk.id={:?})", blk.id); let prev_cx = visitor.cx; @@ -731,7 +733,7 @@ fn resolve_block(visitor: &mut RegionResolutionVisitor, blk: &hir::Block) { visitor.cx = prev_cx; } -fn resolve_arm(visitor: &mut RegionResolutionVisitor, arm: &hir::Arm) { +fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, arm: &'tcx hir::Arm) { visitor.terminating_scopes.insert(arm.body.id); if let Some(ref expr) = arm.guard { @@ -741,7 +743,7 @@ fn resolve_arm(visitor: &mut RegionResolutionVisitor, arm: &hir::Arm) { intravisit::walk_arm(visitor, arm); } -fn resolve_pat(visitor: &mut RegionResolutionVisitor, pat: &hir::Pat) { +fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, pat: &'tcx hir::Pat) { visitor.new_node_extent(pat.id); // If this is a binding then record the lifetime of that binding. @@ -752,7 +754,7 @@ fn resolve_pat(visitor: &mut RegionResolutionVisitor, pat: &hir::Pat) { intravisit::walk_pat(visitor, pat); } -fn resolve_stmt(visitor: &mut RegionResolutionVisitor, stmt: &hir::Stmt) { +fn resolve_stmt<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, stmt: &'tcx hir::Stmt) { let stmt_id = stmt.node.id(); debug!("resolve_stmt(stmt.id={:?})", stmt_id); @@ -770,7 +772,7 @@ fn resolve_stmt(visitor: &mut RegionResolutionVisitor, stmt: &hir::Stmt) { visitor.cx.parent = prev_parent; } -fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &hir::Expr) { +fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, expr: &'tcx hir::Expr) { debug!("resolve_expr(expr.id={:?})", expr.id); let expr_extent = visitor.new_node_extent_with_dtor(expr.id); @@ -848,7 +850,7 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor, expr: &hir::Expr) { visitor.cx = prev_cx; } -fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) { +fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, local: &'tcx hir::Local) { debug!("resolve_local(local.id={:?},local.init={:?})", local.id,local.init.is_some()); @@ -1063,7 +1065,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor, local: &hir::Local) { } } -fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &hir::Item) { +fn resolve_item<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, item: &'tcx hir::Item) { // Items create a new outer block scope as far as we're concerned. let prev_cx = visitor.cx; let prev_ts = mem::replace(&mut visitor.terminating_scopes, NodeSet()); @@ -1078,38 +1080,38 @@ fn resolve_item(visitor: &mut RegionResolutionVisitor, item: &hir::Item) { visitor.terminating_scopes = prev_ts; } -fn resolve_fn(visitor: &mut RegionResolutionVisitor, - kind: FnKind, - decl: &hir::FnDecl, - body: &hir::Expr, - sp: Span, - id: ast::NodeId) { +fn resolve_fn<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'tcx, 'a>, + kind: FnKind<'tcx>, + decl: &'tcx hir::FnDecl, + body_id: hir::ExprId, + sp: Span, + id: ast::NodeId) { debug!("region::resolve_fn(id={:?}, \ span={:?}, \ body.id={:?}, \ cx.parent={:?})", id, visitor.sess.codemap().span_to_string(sp), - body.id, + body_id, visitor.cx.parent); visitor.cx.parent = visitor.new_code_extent( - CodeExtentData::CallSiteScope { fn_id: id, body_id: body.id }); + CodeExtentData::CallSiteScope { fn_id: id, body_id: body_id.node_id() }); let fn_decl_scope = visitor.new_code_extent( - CodeExtentData::ParameterScope { fn_id: id, body_id: body.id }); + CodeExtentData::ParameterScope { fn_id: id, body_id: body_id.node_id() }); if let Some(root_id) = visitor.cx.root_id { - visitor.region_maps.record_fn_parent(body.id, root_id); + visitor.region_maps.record_fn_parent(body_id.node_id(), root_id); } let outer_cx = visitor.cx; let outer_ts = mem::replace(&mut visitor.terminating_scopes, NodeSet()); - visitor.terminating_scopes.insert(body.id); + visitor.terminating_scopes.insert(body_id.node_id()); // The arguments and `self` are parented to the fn. visitor.cx = Context { - root_id: Some(body.id), + root_id: Some(body_id.node_id()), parent: ROOT_CODE_EXTENT, var_parent: fn_decl_scope, }; @@ -1119,18 +1121,18 @@ fn resolve_fn(visitor: &mut RegionResolutionVisitor, // The body of the every fn is a root scope. visitor.cx = Context { - root_id: Some(body.id), + root_id: Some(body_id.node_id()), parent: fn_decl_scope, var_parent: fn_decl_scope }; - visitor.visit_expr(body); + visitor.visit_body(body_id); // Restore context we had at the start. visitor.cx = outer_cx; visitor.terminating_scopes = outer_ts; } -impl<'a> RegionResolutionVisitor<'a> { +impl<'ast, 'a> RegionResolutionVisitor<'ast, 'a> { /// Records the current parent (if any) as the parent of `child_scope`. fn new_code_extent(&mut self, child_scope: CodeExtentData) -> CodeExtent { self.region_maps.intern_code_extent(child_scope, self.cx.parent) @@ -1166,42 +1168,46 @@ impl<'a> RegionResolutionVisitor<'a> { } } -impl<'a, 'v> Visitor<'v> for RegionResolutionVisitor<'a> { - fn visit_block(&mut self, b: &Block) { +impl<'ast, 'a> Visitor<'ast> for RegionResolutionVisitor<'ast, 'a> { + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'ast>, NestedVisitMode)> { + Some((&self.map, NestedVisitMode::OnlyBodies)) + } + + fn visit_block(&mut self, b: &'ast Block) { resolve_block(self, b); } - fn visit_item(&mut self, i: &Item) { + fn visit_item(&mut self, i: &'ast Item) { resolve_item(self, i); } - fn visit_impl_item(&mut self, ii: &hir::ImplItem) { + fn visit_impl_item(&mut self, ii: &'ast hir::ImplItem) { intravisit::walk_impl_item(self, ii); self.create_item_scope_if_needed(ii.id); } - fn visit_trait_item(&mut self, ti: &hir::TraitItem) { + fn visit_trait_item(&mut self, ti: &'ast hir::TraitItem) { intravisit::walk_trait_item(self, ti); self.create_item_scope_if_needed(ti.id); } - fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, - b: &'v Expr, s: Span, n: NodeId) { + fn visit_fn(&mut self, fk: FnKind<'ast>, fd: &'ast FnDecl, + b: hir::ExprId, s: Span, n: NodeId) { resolve_fn(self, fk, fd, b, s, n); } - fn visit_arm(&mut self, a: &Arm) { + fn visit_arm(&mut self, a: &'ast Arm) { resolve_arm(self, a); } - fn visit_pat(&mut self, p: &Pat) { + fn visit_pat(&mut self, p: &'ast Pat) { resolve_pat(self, p); } - fn visit_stmt(&mut self, s: &Stmt) { + fn visit_stmt(&mut self, s: &'ast Stmt) { resolve_stmt(self, s); } - fn visit_expr(&mut self, ex: &Expr) { + fn visit_expr(&mut self, ex: &'ast Expr) { resolve_expr(self, ex); } - fn visit_local(&mut self, l: &Local) { + fn visit_local(&mut self, l: &'ast Local) { resolve_local(self, l); } } @@ -1228,6 +1234,7 @@ pub fn resolve_crate(sess: &Session, map: &ast_map::Map) -> RegionMaps { let mut visitor = RegionResolutionVisitor { sess: sess, region_maps: &maps, + map: map, cx: Context { root_id: None, parent: ROOT_CODE_EXTENT, diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index d07062f98a9..7b94f9b32d9 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -34,7 +34,7 @@ use util::nodemap::NodeMap; use rustc_data_structures::fx::FxHashSet; use hir; use hir::print::lifetime_to_string; -use hir::intravisit::{self, Visitor, FnKind}; +use hir::intravisit::{self, Visitor, FnKind, NestedVisitMode}; #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] pub enum DefRegion { @@ -132,8 +132,8 @@ pub fn krate(sess: &Session, impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { // Override the nested functions -- lifetimes follow lexical scope, // so it's convenient to walk the tree in lexical order. - fn nested_visit_map(&mut self) -> Option<&hir::map::Map<'tcx>> { - Some(&self.hir_map) + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, NestedVisitMode)> { + Some((&self.hir_map, NestedVisitMode::All)) } fn visit_item(&mut self, item: &'tcx hir::Item) { @@ -206,7 +206,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { } fn visit_fn(&mut self, fk: FnKind<'tcx>, decl: &'tcx hir::FnDecl, - b: &'tcx hir::Expr, s: Span, fn_id: ast::NodeId) { + b: hir::ExprId, s: Span, fn_id: ast::NodeId) { match fk { FnKind::ItemFn(_, generics, ..) => { self.visit_early_late(fn_id,decl, generics, |this| { @@ -407,7 +407,7 @@ fn signal_shadowing_problem(sess: &Session, name: ast::Name, orig: Original, sha // Adds all labels in `b` to `ctxt.labels_in_fn`, signalling a warning // if one of the label shadows a lifetime or another label. -fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Expr) { +fn extract_labels(ctxt: &mut LifetimeContext, b: hir::ExprId) { struct GatherLabels<'a> { sess: &'a Session, scope: Scope<'a>, @@ -419,7 +419,7 @@ fn extract_labels(ctxt: &mut LifetimeContext, b: &hir::Expr) { scope: ctxt.scope, labels_in_fn: &mut ctxt.labels_in_fn, }; - gather.visit_expr(b); + gather.visit_expr(ctxt.hir_map.expr(b)); return; impl<'v, 'a> Visitor<'v> for GatherLabels<'a> { @@ -497,7 +497,7 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { fn add_scope_and_walk_fn(&mut self, fk: FnKind<'tcx>, fd: &'tcx hir::FnDecl, - fb: &'tcx hir::Expr, + fb: hir::ExprId, _span: Span, fn_id: ast::NodeId) { match fk { @@ -518,8 +518,8 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { // `self.labels_in_fn`. extract_labels(self, fb); - self.with(FnScope { fn_id: fn_id, body_id: fb.id, s: self.scope }, - |_old_scope, this| this.visit_expr(fb)) + self.with(FnScope { fn_id: fn_id, body_id: fb.node_id(), s: self.scope }, + |_old_scope, this| this.visit_body(fb)) } // FIXME(#37666) this works around a limitation in the region inferencer diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs index f5e18e13465..7417509e5b7 100644 --- a/src/librustc/middle/stability.rs +++ b/src/librustc/middle/stability.rs @@ -30,7 +30,7 @@ use util::nodemap::{DefIdMap, FxHashSet, FxHashMap}; use hir; use hir::{Item, Generics, StructField, Variant}; -use hir::intravisit::{self, Visitor}; +use hir::intravisit::{self, Visitor, NestedVisitMode}; use hir::itemlikevisit::DeepVisitor; use std::mem::replace; @@ -234,8 +234,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { /// Because stability levels are scoped lexically, we want to walk /// nested items in the context of the outer item, so enable /// deep-walking. - fn nested_visit_map(&mut self) -> Option<&hir::map::Map<'tcx>> { - Some(&self.tcx.map) + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, NestedVisitMode)> { + Some((&self.tcx.map, NestedVisitMode::All)) } fn visit_item(&mut self, i: &'tcx Item) { @@ -534,6 +534,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { + fn nested_visit_map(&mut self) -> Option<(&hir::map::Map<'tcx>, NestedVisitMode)> { + Some((&self.tcx.map, NestedVisitMode::OnlyBodies)) + } + fn visit_item(&mut self, item: &'tcx hir::Item) { match item.node { hir::ItemExternCrate(_) => { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 844fc58cec3..16f84a1b8aa 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1208,7 +1208,7 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { tcx.construct_parameter_environment( impl_item.span, tcx.map.local_def_id(id), - tcx.region_maps.call_site_extent(id, body.id)) + tcx.region_maps.call_site_extent(id, body.node_id())) } } } @@ -1227,9 +1227,9 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { // Use call-site for extent (unless this is a // trait method with no default; then fallback // to the method id). - let extent = if let Some(ref body) = *body { + let extent = if let Some(body_id) = *body { // default impl: use call_site extent as free_id_outlive bound. - tcx.region_maps.call_site_extent(id, body.id) + tcx.region_maps.call_site_extent(id, body_id.node_id()) } else { // no default impl: use item extent as free_id_outlive bound. tcx.region_maps.item_extent(id) @@ -1243,14 +1243,14 @@ impl<'a, 'tcx> ParameterEnvironment<'tcx> { } Some(ast_map::NodeItem(item)) => { match item.node { - hir::ItemFn(.., ref body) => { + hir::ItemFn(.., body_id) => { // We assume this is a function. let fn_def_id = tcx.map.local_def_id(id); tcx.construct_parameter_environment( item.span, fn_def_id, - tcx.region_maps.call_site_extent(id, body.id)) + tcx.region_maps.call_site_extent(id, body_id.node_id())) } hir::ItemEnum(..) | hir::ItemStruct(..) | diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 5e54e333bb9..f1ffd2b3f09 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -205,7 +205,7 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>, { // Check the body of fn items. let tcx = this.tcx; - let id_range = intravisit::compute_id_range_for_fn_body(fk, decl, body, sp, id); + let id_range = intravisit::compute_id_range_for_fn_body(fk, decl, body, sp, id, &tcx.map); let (all_loans, move_data) = gather_loans::gather_loans_in_fn(this, id, decl, body); diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 806d20c72dc..1434181075f 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -44,7 +44,7 @@ enum TableEntry<'tcx> { impl<'a, 'tcx> EncodeContext<'a, 'tcx> { pub fn encode_inlined_item(&mut self, ii: InlinedItemRef) -> Lazy> { - let mut id_visitor = IdRangeComputingVisitor::new(); + let mut id_visitor = IdRangeComputingVisitor::new(&self.tcx.map); match ii { InlinedItemRef::Item(_, i) => id_visitor.visit_item(i), InlinedItemRef::TraitItem(_, ti) => id_visitor.visit_trait_item(ti),