Precompute ancestors when checking privacy

Precompute ancestors of the old error node set so that check for private
types and traits in public interfaces can in constant time determine if
the current item has any descendants in the old error set.

No functional changes intended.
This commit is contained in:
Tomasz Miąsko 2021-01-30 00:00:00 +00:00
parent fd20a8be0d
commit b01976aa26

View File

@ -1822,41 +1822,18 @@ impl DefIdVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'tcx> {
} }
} }
struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { struct PrivateItemsInPublicInterfacesVisitor<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
has_pub_restricted: bool, has_pub_restricted: bool,
old_error_set: &'a HirIdSet, old_error_set_ancestry: HirIdSet,
} }
impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { impl<'tcx> PrivateItemsInPublicInterfacesVisitor<'tcx> {
fn check( fn check(
&self, &self,
item_id: hir::HirId, item_id: hir::HirId,
required_visibility: ty::Visibility, required_visibility: ty::Visibility,
) -> SearchInterfaceForPrivateItemsVisitor<'tcx> { ) -> SearchInterfaceForPrivateItemsVisitor<'tcx> {
let mut has_old_errors = false;
// Slow path taken only if there any errors in the crate.
for &id in self.old_error_set {
// Walk up the nodes until we find `item_id` (or we hit a root).
let mut id = id;
loop {
if id == item_id {
has_old_errors = true;
break;
}
let parent = self.tcx.hir().get_parent_node(id);
if parent == id {
break;
}
id = parent;
}
if has_old_errors {
break;
}
}
SearchInterfaceForPrivateItemsVisitor { SearchInterfaceForPrivateItemsVisitor {
tcx: self.tcx, tcx: self.tcx,
item_id, item_id,
@ -1864,7 +1841,7 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
span: self.tcx.hir().span(item_id), span: self.tcx.hir().span(item_id),
required_visibility, required_visibility,
has_pub_restricted: self.has_pub_restricted, has_pub_restricted: self.has_pub_restricted,
has_old_errors, has_old_errors: self.old_error_set_ancestry.contains(&item_id),
in_assoc_ty: false, in_assoc_ty: false,
} }
} }
@ -1890,7 +1867,7 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
} }
} }
impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> { impl<'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'tcx> {
type Map = Map<'tcx>; type Map = Map<'tcx>;
fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
@ -2114,11 +2091,22 @@ fn check_private_in_public(tcx: TyCtxt<'_>, krate: CrateNum) {
pub_restricted_visitor.has_pub_restricted pub_restricted_visitor.has_pub_restricted
}; };
let mut old_error_set_ancestry = HirIdSet::default();
for mut id in visitor.old_error_set.iter().copied() {
loop {
if !old_error_set_ancestry.insert(id) {
break;
}
let parent = tcx.hir().get_parent_node(id);
if parent == id {
break;
}
id = parent;
}
}
// Check for private types and traits in public interfaces. // Check for private types and traits in public interfaces.
let mut visitor = PrivateItemsInPublicInterfacesVisitor { let mut visitor =
tcx, PrivateItemsInPublicInterfacesVisitor { tcx, has_pub_restricted, old_error_set_ancestry };
has_pub_restricted,
old_error_set: &visitor.old_error_set,
};
krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor)); krate.visit_all_item_likes(&mut DeepVisitor::new(&mut visitor));
} }