From d79ad36cf5c8f11e37001a090abae5ff94fbab1b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 20 Feb 2017 21:18:16 -0500 Subject: [PATCH] walk the bodies "in order" by traversing the crate Otherwise the errors from borrowck come out in an unpredictable order. --- src/librustc/dep_graph/visit.rs | 28 ++++++++++++++++++++++++--- src/librustc/hir/map/mod.rs | 29 ++++++++++++++++------------ src/test/ui/span/mut-arg-hint.stderr | 16 +++++++-------- 3 files changed, 50 insertions(+), 23 deletions(-) diff --git a/src/librustc/dep_graph/visit.rs b/src/librustc/dep_graph/visit.rs index f807437750d0..0d10049bc1e4 100644 --- a/src/librustc/dep_graph/visit.rs +++ b/src/librustc/dep_graph/visit.rs @@ -11,6 +11,7 @@ use hir; use hir::def_id::DefId; use hir::itemlikevisit::ItemLikeVisitor; +use hir::intravisit::{self, NestedVisitorMap, Visitor}; use ty::TyCtxt; use super::dep_node::DepNode; @@ -78,9 +79,30 @@ pub fn visit_all_item_likes_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx> pub fn visit_all_bodies_in_krate<'a, 'tcx, C>(tcx: TyCtxt<'a, 'tcx, 'tcx>, callback: C) where C: Fn(/* body_owner */ DefId, /* body id */ hir::BodyId), { + // NB: we use a visitor here rather than walking the keys of the + // hashmap so as to ensure we visit the bodies "in order". + let krate = tcx.hir.krate(); - for body_id in krate.bodies.keys().cloned() { - let body_owner_def_id = tcx.hir.body_owner_def_id(body_id); - callback(body_owner_def_id, body_id); + intravisit::walk_crate(&mut V { tcx, callback }, krate); + + struct V<'a, 'tcx: 'a, C> { + tcx: TyCtxt<'a, 'tcx, 'tcx>, + callback: C + } + + impl<'a, 'tcx, C> Visitor<'tcx> for V<'a, 'tcx, C> + where C: Fn(/* body_owner */ DefId, /* body id */ hir::BodyId), + { + fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { + NestedVisitorMap::All(&self.tcx.hir) + } + + fn visit_body(&mut self, body: &'tcx hir::Body) { + let body_id = body.id(); + let body_owner_def_id = self.tcx.hir.body_owner_def_id(body_id); + (self.callback)(body_owner_def_id, body_id); + + intravisit::walk_body(self, body); + } } } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 20b4d8d8a8f0..5d074903b2b9 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -168,43 +168,48 @@ impl<'hir> MapEntry<'hir> { }) } - fn is_body_owner(self, node_id: NodeId) -> bool { + fn associated_body(self) -> Option { match self { EntryItem(_, item) => { match item.node { ItemConst(_, body) | ItemStatic(.., body) | - ItemFn(_, _, _, _, _, body) => body.node_id == node_id, - _ => false + ItemFn(_, _, _, _, _, body) => Some(body), + _ => None, } } EntryTraitItem(_, item) => { match item.node { TraitItemKind::Const(_, Some(body)) | - TraitItemKind::Method(_, TraitMethod::Provided(body)) => { - body.node_id == node_id - } - _ => false + TraitItemKind::Method(_, TraitMethod::Provided(body)) => Some(body), + _ => None } } EntryImplItem(_, item) => { match item.node { ImplItemKind::Const(_, body) | - ImplItemKind::Method(_, body) => body.node_id == node_id, - _ => false + ImplItemKind::Method(_, body) => Some(body), + _ => None, } } EntryExpr(_, expr) => { match expr.node { - ExprClosure(.., body, _) => body.node_id == node_id, - _ => false + ExprClosure(.., body, _) => Some(body), + _ => None, } } - _ => false + _ => None + } + } + + fn is_body_owner(self, node_id: NodeId) -> bool { + match self.associated_body() { + Some(b) => b.node_id == node_id, + None => false, } } } diff --git a/src/test/ui/span/mut-arg-hint.stderr b/src/test/ui/span/mut-arg-hint.stderr index e4ed06221471..01364c071440 100644 --- a/src/test/ui/span/mut-arg-hint.stderr +++ b/src/test/ui/span/mut-arg-hint.stderr @@ -1,11 +1,3 @@ -error: cannot borrow immutable borrowed content `*a` as mutable - --> $DIR/mut-arg-hint.rs:18:5 - | -17 | pub fn foo<'a>(mut a: &'a String) { - | ---------- use `&'a mut String` here to make mutable -18 | a.push_str("foo"); - | ^ cannot borrow as mutable - error: cannot borrow immutable borrowed content `*a` as mutable --> $DIR/mut-arg-hint.rs:13:9 | @@ -14,6 +6,14 @@ error: cannot borrow immutable borrowed content `*a` as mutable 13 | a.push_str("bar"); | ^ cannot borrow as mutable +error: cannot borrow immutable borrowed content `*a` as mutable + --> $DIR/mut-arg-hint.rs:18:5 + | +17 | pub fn foo<'a>(mut a: &'a String) { + | ---------- use `&'a mut String` here to make mutable +18 | a.push_str("foo"); + | ^ cannot borrow as mutable + error: cannot borrow immutable borrowed content `*a` as mutable --> $DIR/mut-arg-hint.rs:25:9 |