@@ -1471,27 +1471,68 @@ impl Type {
14711471 result
14721472 }
14731473
1474- /// Check if two types are "potentially the same".
1474+ pub ( crate ) fn is_borrowed_ref ( & self ) -> bool {
1475+ matches ! ( self , Type :: BorrowedRef { .. } )
1476+ }
1477+
1478+ /// Check if two types are "the same" for documentation purposes.
1479+ ///
14751480 /// This is different from `Eq`, because it knows that things like
14761481 /// `Placeholder` are possible matches for everything.
1477- pub ( crate ) fn is_same ( & self , other : & Self , cache : & Cache ) -> bool {
1478- match ( self , other) {
1482+ ///
1483+ /// This relation is not commutative when generics are involved:
1484+ ///
1485+ /// ```ignore(private)
1486+ /// # // see types/tests.rs:is_same_generic for the real test
1487+ /// use rustdoc::format::cache::Cache;
1488+ /// use rustdoc::clean::types::{Type, PrimitiveType};
1489+ /// let cache = Cache::new(false);
1490+ /// let generic = Type::Generic(rustc_span::symbol::sym::Any);
1491+ /// let unit = Type::Primitive(PrimitiveType::Unit);
1492+ /// assert!(!generic.is_same(&unit, &cache));
1493+ /// assert!(unit.is_same(&generic, &cache));
1494+ /// ```
1495+ ///
1496+ /// An owned type is also the same as its borrowed variants (this is commutative),
1497+ /// but `&T` is not the same as `&mut T`.
1498+ pub ( crate ) fn is_doc_subtype_of ( & self , other : & Self , cache : & Cache ) -> bool {
1499+ // Strip the references so that it can compare the actual types, unless both are references.
1500+ // If both are references, leave them alone and compare the mutabilities later.
1501+ let ( self_cleared, other_cleared) = if !self . is_borrowed_ref ( ) || !other. is_borrowed_ref ( ) {
1502+ ( self . without_borrowed_ref ( ) , other. without_borrowed_ref ( ) )
1503+ } else {
1504+ ( self , other)
1505+ } ;
1506+ match ( self_cleared, other_cleared) {
14791507 // Recursive cases.
14801508 ( Type :: Tuple ( a) , Type :: Tuple ( b) ) => {
1481- a. len ( ) == b. len ( ) && a. iter ( ) . zip ( b) . all ( |( a, b) | a. is_same ( b, cache) )
1509+ a. len ( ) == b. len ( ) && a. iter ( ) . zip ( b) . all ( |( a, b) | a. is_doc_subtype_of ( b, cache) )
14821510 }
1483- ( Type :: Slice ( a) , Type :: Slice ( b) ) => a. is_same ( b, cache) ,
1484- ( Type :: Array ( a, al) , Type :: Array ( b, bl) ) => al == bl && a. is_same ( b, cache) ,
1511+ ( Type :: Slice ( a) , Type :: Slice ( b) ) => a. is_doc_subtype_of ( b, cache) ,
1512+ ( Type :: Array ( a, al) , Type :: Array ( b, bl) ) => al == bl && a. is_doc_subtype_of ( b, cache) ,
14851513 ( Type :: RawPointer ( mutability, type_) , Type :: RawPointer ( b_mutability, b_type_) ) => {
1486- mutability == b_mutability && type_. is_same ( b_type_, cache)
1514+ mutability == b_mutability && type_. is_doc_subtype_of ( b_type_, cache)
14871515 }
14881516 (
14891517 Type :: BorrowedRef { mutability, type_, .. } ,
14901518 Type :: BorrowedRef { mutability : b_mutability, type_ : b_type_, .. } ,
1491- ) => mutability == b_mutability && type_. is_same ( b_type_, cache) ,
1492- // Placeholders and generics are equal to all other types.
1519+ ) => mutability == b_mutability && type_. is_doc_subtype_of ( b_type_, cache) ,
1520+ // Placeholders are equal to all other types.
14931521 ( Type :: Infer , _) | ( _, Type :: Infer ) => true ,
1494- ( Type :: Generic ( _) , _) | ( _, Type :: Generic ( _) ) => true ,
1522+ // Generics match everything on the right, but not on the left.
1523+ // If both sides are generic, this returns true.
1524+ ( _, Type :: Generic ( _) ) => true ,
1525+ ( Type :: Generic ( _) , _) => false ,
1526+ // Paths account for both the path itself and its generics.
1527+ ( Type :: Path { path : a } , Type :: Path { path : b } ) => {
1528+ a. def_id ( ) == b. def_id ( )
1529+ && a. generics ( )
1530+ . zip ( b. generics ( ) )
1531+ . map ( |( ag, bg) | {
1532+ ag. iter ( ) . zip ( bg. iter ( ) ) . all ( |( at, bt) | at. is_doc_subtype_of ( bt, cache) )
1533+ } )
1534+ . unwrap_or ( true )
1535+ }
14951536 // Other cases, such as primitives, just use recursion.
14961537 ( a, b) => a
14971538 . def_id ( cache)
0 commit comments