@@ -338,18 +338,39 @@ impl TyCtxt<'_> {
338338 self . parent ( id. into ( ) . to_def_id ( ) ) . expect_local ( )
339339 }
340340
341- pub fn is_descendant_of ( self , mut descendant : DefId , ancestor : DefId ) -> bool {
342- if descendant. krate != ancestor. krate {
343- return false ;
341+ /// Compare def-ids based on their position in def-id tree, ancestor def-ids are considered
342+ /// larger than descendant def-ids, and two different def-ids are considered unordered if
343+ /// neither of them is an ancestor of the other.
344+ fn def_id_partial_cmp ( self , lhs : DefId , rhs : DefId ) -> Option < Ordering > {
345+ // Def-ids from different crates are always unordered.
346+ if lhs. krate != rhs. krate {
347+ return None ;
344348 }
345349
346- while descendant != ancestor {
347- match self . opt_parent ( descendant) {
348- Some ( parent) => descendant = parent,
349- None => return false ,
350+ // Def-ids of parent nodes are always created before def-ids of child nodes
351+ // and have a smaller index, so we only need to search in one direction,
352+ // either from lhs to rhs, or vice versa.
353+ let search = |mut start : DefId , finish : DefId , ord| {
354+ while start. index != finish. index {
355+ match self . opt_parent ( start) {
356+ Some ( parent) => start. index = parent. index ,
357+ None => return None ,
358+ }
350359 }
360+ Some ( ord)
361+ } ;
362+ match lhs. index . cmp ( & rhs. index ) {
363+ Ordering :: Equal => Some ( Ordering :: Equal ) ,
364+ Ordering :: Less => search ( rhs, lhs, Ordering :: Greater ) ,
365+ Ordering :: Greater => search ( lhs, rhs, Ordering :: Less ) ,
351366 }
352- true
367+ }
368+
369+ pub fn is_descendant_of ( self , descendant : DefId , ancestor : DefId ) -> bool {
370+ matches ! (
371+ self . def_id_partial_cmp( descendant, ancestor) ,
372+ Some ( Ordering :: Less | Ordering :: Equal )
373+ )
353374 }
354375}
355376
@@ -391,15 +412,7 @@ impl<Id: Into<DefId>> Visibility<Id> {
391412 ( Visibility :: Restricted ( _) , Visibility :: Public ) => Some ( Ordering :: Less ) ,
392413 ( Visibility :: Restricted ( lhs_id) , Visibility :: Restricted ( rhs_id) ) => {
393414 let ( lhs_id, rhs_id) = ( lhs_id. into ( ) , rhs_id. into ( ) ) ;
394- if lhs_id == rhs_id {
395- Some ( Ordering :: Equal )
396- } else if tcx. is_descendant_of ( rhs_id, lhs_id) {
397- Some ( Ordering :: Greater )
398- } else if tcx. is_descendant_of ( lhs_id, rhs_id) {
399- Some ( Ordering :: Less )
400- } else {
401- None
402- }
415+ tcx. def_id_partial_cmp ( lhs_id, rhs_id)
403416 }
404417 }
405418 }
0 commit comments