@@ -1215,10 +1215,11 @@ impl<'db> Type<'db> {
12151215
12161216 fn has_relation_to ( self , db : & ' db dyn Db , target : Type < ' db > , relation : TypeRelation ) -> bool {
12171217 // Subtyping implies assignability, so if subtyping is reflexive and the two types are
1218- // equivalent, it is both a subtype and assignable. Assignability is always reflexive.
1219- if ( relation. is_assignability ( ) || self . subtyping_is_always_reflexive ( ) )
1220- && self . is_equivalent_to ( db, target)
1221- {
1218+ // equal, it is both a subtype and assignable. Assignability is always reflexive.
1219+ //
1220+ // Note that we could do a full equivalence check here, but that would be both expensive
1221+ // and unnecessary. This early return is only an optimisation.
1222+ if ( relation. is_assignability ( ) || self . subtyping_is_always_reflexive ( ) ) && self == target {
12221223 return true ;
12231224 }
12241225
@@ -1256,6 +1257,9 @@ impl<'db> Type<'db> {
12561257
12571258 // Two identical typevars must always solve to the same type, so they are always
12581259 // subtypes of each other and assignable to each other.
1260+ //
1261+ // Note that this is not handled by the early return at the beginning of this method,
1262+ // since subtyping between a TypeVar and an arbitrary other type cannot be guaranteed to be reflexive.
12591263 ( Type :: TypeVar ( lhs_typevar) , Type :: TypeVar ( rhs_typevar) )
12601264 if lhs_typevar == rhs_typevar =>
12611265 {
@@ -7906,17 +7910,17 @@ impl<'db> UnionType<'db> {
79067910
79077911 /// Return `true` if `self` represents the exact same sets of possible runtime objects as `other`
79087912 pub ( crate ) fn is_equivalent_to ( self , db : & ' db dyn Db , other : Self ) -> bool {
7913+ if self == other {
7914+ return true ;
7915+ }
7916+
79097917 let self_elements = self . elements ( db) ;
79107918 let other_elements = other. elements ( db) ;
79117919
79127920 if self_elements. len ( ) != other_elements. len ( ) {
79137921 return false ;
79147922 }
79157923
7916- if self == other {
7917- return true ;
7918- }
7919-
79207924 let sorted_self = self . normalized ( db) ;
79217925
79227926 if sorted_self == other {
@@ -7997,26 +8001,24 @@ impl<'db> IntersectionType<'db> {
79978001
79988002 /// Return `true` if `self` represents exactly the same set of possible runtime objects as `other`
79998003 pub ( crate ) fn is_equivalent_to ( self , db : & ' db dyn Db , other : Self ) -> bool {
8000- let self_positive = self . positive ( db) ;
8004+ if self == other {
8005+ return true ;
8006+ }
80018007
8008+ let self_positive = self . positive ( db) ;
80028009 let other_positive = other. positive ( db) ;
80038010
80048011 if self_positive. len ( ) != other_positive. len ( ) {
80058012 return false ;
80068013 }
80078014
80088015 let self_negative = self . negative ( db) ;
8009-
80108016 let other_negative = other. negative ( db) ;
80118017
80128018 if self_negative. len ( ) != other_negative. len ( ) {
80138019 return false ;
80148020 }
80158021
8016- if self == other {
8017- return true ;
8018- }
8019-
80208022 let sorted_self = self . normalized ( db) ;
80218023
80228024 if sorted_self == other {
0 commit comments