@@ -1471,27 +1471,68 @@ 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.
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) {
1479
1507
// Recursive cases.
1480
1508
( 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) )
1482
1510
}
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) ,
1485
1513
( 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)
1487
1515
}
1488
1516
(
1489
1517
Type :: BorrowedRef { mutability, type_, .. } ,
1490
1518
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.
1493
1521
( 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
+ }
1495
1536
// Other cases, such as primitives, just use recursion.
1496
1537
( a, b) => a
1497
1538
. def_id ( cache)
0 commit comments