Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 30 additions & 17 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,18 +338,39 @@ impl TyCtxt<'_> {
self.parent(id.into().to_def_id()).expect_local()
}

pub fn is_descendant_of(self, mut descendant: DefId, ancestor: DefId) -> bool {
if descendant.krate != ancestor.krate {
return false;
/// Compare def-ids based on their position in def-id tree, ancestor def-ids are considered
/// larger than descendant def-ids, and two different def-ids are considered unordered if
/// neither of them is an ancestor of the other.
fn def_id_partial_cmp(self, lhs: DefId, rhs: DefId) -> Option<Ordering> {
// Def-ids from different crates are always unordered.
if lhs.krate != rhs.krate {
return None;
}

while descendant != ancestor {
match self.opt_parent(descendant) {
Some(parent) => descendant = parent,
None => return false,
// Def-ids of parent nodes are always created before def-ids of child nodes
// and have a smaller index, so we only need to search in one direction,
// either from lhs to rhs, or vice versa.
let search = |mut start: DefId, finish: DefId, ord| {
while start.index != finish.index {
match self.opt_parent(start) {
Some(parent) => start.index = parent.index,
None => return None,
}
}
Some(ord)
};
match lhs.index.cmp(&rhs.index) {
Ordering::Equal => Some(Ordering::Equal),
Ordering::Less => search(rhs, lhs, Ordering::Greater),
Ordering::Greater => search(lhs, rhs, Ordering::Less),
}
true
}

pub fn is_descendant_of(self, descendant: DefId, ancestor: DefId) -> bool {
matches!(
self.def_id_partial_cmp(descendant, ancestor),
Some(Ordering::Less | Ordering::Equal)
)
}
}

Expand Down Expand Up @@ -391,15 +412,7 @@ impl<Id: Into<DefId>> Visibility<Id> {
(Visibility::Restricted(_), Visibility::Public) => Some(Ordering::Less),
(Visibility::Restricted(lhs_id), Visibility::Restricted(rhs_id)) => {
let (lhs_id, rhs_id) = (lhs_id.into(), rhs_id.into());
if lhs_id == rhs_id {
Some(Ordering::Equal)
} else if tcx.is_descendant_of(rhs_id, lhs_id) {
Some(Ordering::Greater)
} else if tcx.is_descendant_of(lhs_id, rhs_id) {
Some(Ordering::Less)
} else {
None
}
tcx.def_id_partial_cmp(lhs_id, rhs_id)
}
}
}
Expand Down
Loading