@@ -1471,11 +1471,37 @@ impl Type {
1471
1471
result
1472
1472
}
1473
1473
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
+ ///
1475
1480
/// This is different from `Eq`, because it knows that things like
1476
1481
/// `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`.
1477
1498
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) {
1479
1505
// Recursive cases.
1480
1506
( Type :: Tuple ( a) , Type :: Tuple ( b) ) => {
1481
1507
a. len ( ) == b. len ( ) && a. iter ( ) . zip ( b) . all ( |( a, b) | a. is_same ( b, cache) )
@@ -1489,9 +1515,21 @@ impl Type {
1489
1515
Type :: BorrowedRef { mutability, type_, .. } ,
1490
1516
Type :: BorrowedRef { mutability : b_mutability, type_ : b_type_, .. } ,
1491
1517
) => 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.
1493
1519
( 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
+ }
1495
1533
// Other cases, such as primitives, just use recursion.
1496
1534
( a, b) => a
1497
1535
. def_id ( cache)
0 commit comments