@@ -1471,11 +1471,37 @@ 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.
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`.
14771498 pub ( crate ) fn is_same ( & self , other : & Self , cache : & Cache ) -> bool {
1478- match ( self , other) {
1499+ let ( self_cleared, other_cleared) = if !self . is_borrowed_ref ( ) || !other. is_borrowed_ref ( ) {
1500+ ( self . without_borrowed_ref ( ) , other. without_borrowed_ref ( ) )
1501+ } else {
1502+ ( self , other)
1503+ } ;
1504+ match ( self_cleared, other_cleared) {
14791505 // Recursive cases.
14801506 ( Type :: Tuple ( a) , Type :: Tuple ( b) ) => {
14811507 a. len ( ) == b. len ( ) && a. iter ( ) . zip ( b) . all ( |( a, b) | a. is_same ( b, cache) )
@@ -1489,9 +1515,21 @@ impl Type {
14891515 Type :: BorrowedRef { mutability, type_, .. } ,
14901516 Type :: BorrowedRef { mutability : b_mutability, type_ : b_type_, .. } ,
14911517 ) => mutability == b_mutability && type_. is_same ( b_type_, cache) ,
1492- // Placeholders and generics are equal to all other types.
1518+ // Placeholders are equal to all other types.
14931519 ( Type :: Infer , _) | ( _, Type :: Infer ) => true ,
1494- ( Type :: Generic ( _) , _) | ( _, Type :: Generic ( _) ) => true ,
1520+ // Generics match everything on the right, but not on the left.
1521+ ( _, Type :: Generic ( _) ) => true ,
1522+ ( Type :: Generic ( _) , _) => false ,
1523+ // Paths account for both the path itself and its generics.
1524+ ( Type :: Path { path : a } , Type :: Path { path : b } ) => {
1525+ a. def_id ( ) == b. def_id ( )
1526+ && a. generics ( )
1527+ . zip ( b. generics ( ) )
1528+ . map ( |( ag, bg) | {
1529+ ag. iter ( ) . zip ( bg. iter ( ) ) . all ( |( at, bt) | at. is_same ( bt, cache) )
1530+ } )
1531+ . unwrap_or ( true )
1532+ }
14951533 // Other cases, such as primitives, just use recursion.
14961534 ( a, b) => a
14971535 . def_id ( cache)
0 commit comments