@@ -1215,10 +1215,11 @@ impl<'db> Type<'db> {
1215
1215
1216
1216
fn has_relation_to ( self , db : & ' db dyn Db , target : Type < ' db > , relation : TypeRelation ) -> bool {
1217
1217
// 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 {
1222
1223
return true ;
1223
1224
}
1224
1225
@@ -1256,6 +1257,9 @@ impl<'db> Type<'db> {
1256
1257
1257
1258
// Two identical typevars must always solve to the same type, so they are always
1258
1259
// 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.
1259
1263
( Type :: TypeVar ( lhs_typevar) , Type :: TypeVar ( rhs_typevar) )
1260
1264
if lhs_typevar == rhs_typevar =>
1261
1265
{
@@ -7906,17 +7910,17 @@ impl<'db> UnionType<'db> {
7906
7910
7907
7911
/// Return `true` if `self` represents the exact same sets of possible runtime objects as `other`
7908
7912
pub ( crate ) fn is_equivalent_to ( self , db : & ' db dyn Db , other : Self ) -> bool {
7913
+ if self == other {
7914
+ return true ;
7915
+ }
7916
+
7909
7917
let self_elements = self . elements ( db) ;
7910
7918
let other_elements = other. elements ( db) ;
7911
7919
7912
7920
if self_elements. len ( ) != other_elements. len ( ) {
7913
7921
return false ;
7914
7922
}
7915
7923
7916
- if self == other {
7917
- return true ;
7918
- }
7919
-
7920
7924
let sorted_self = self . normalized ( db) ;
7921
7925
7922
7926
if sorted_self == other {
@@ -7997,26 +8001,24 @@ impl<'db> IntersectionType<'db> {
7997
8001
7998
8002
/// Return `true` if `self` represents exactly the same set of possible runtime objects as `other`
7999
8003
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
+ }
8001
8007
8008
+ let self_positive = self . positive ( db) ;
8002
8009
let other_positive = other. positive ( db) ;
8003
8010
8004
8011
if self_positive. len ( ) != other_positive. len ( ) {
8005
8012
return false ;
8006
8013
}
8007
8014
8008
8015
let self_negative = self . negative ( db) ;
8009
-
8010
8016
let other_negative = other. negative ( db) ;
8011
8017
8012
8018
if self_negative. len ( ) != other_negative. len ( ) {
8013
8019
return false ;
8014
8020
}
8015
8021
8016
- if self == other {
8017
- return true ;
8018
- }
8019
-
8020
8022
let sorted_self = self . normalized ( db) ;
8021
8023
8022
8024
if sorted_self == other {
0 commit comments