@@ -195,6 +195,17 @@ impl TypeRelation<'_> {
195195 pub ( crate ) const fn is_subtyping ( self ) -> bool {
196196 matches ! ( self , TypeRelation :: Subtyping )
197197 }
198+
199+ pub ( crate ) const fn can_safely_assume_reflexivity ( self , ty : Type ) -> bool {
200+ match self {
201+ TypeRelation :: Assignability
202+ | TypeRelation :: ConstraintSetAssignability
203+ | TypeRelation :: Redundancy => true ,
204+ TypeRelation :: Subtyping | TypeRelation :: SubtypingAssuming ( _) => {
205+ ty. subtyping_is_always_reflexive ( )
206+ }
207+ }
208+ }
198209}
199210
200211#[ salsa:: tracked]
@@ -329,7 +340,7 @@ impl<'db> Type<'db> {
329340 //
330341 // Note that we could do a full equivalence check here, but that would be both expensive
331342 // and unnecessary. This early return is only an optimisation.
332- if ( ! relation. is_subtyping ( ) || self . subtyping_is_always_reflexive ( ) ) && self == target {
343+ if relation. can_safely_assume_reflexivity ( self ) && self == target {
333344 return ConstraintSet :: from ( true ) ;
334345 }
335346
@@ -460,44 +471,41 @@ impl<'db> Type<'db> {
460471 } ,
461472 } ) ,
462473
463- // In general, a TypeVar `T` is not a subtype of a type `S` unless one of the two conditions is satisfied:
474+ // In general, a TypeVar `T` is not redundant with a type `S` unless one of the two conditions is satisfied:
464475 // 1. `T` is a bound TypeVar and `T`'s upper bound is a subtype of `S`.
465476 // TypeVars without an explicit upper bound are treated as having an implicit upper bound of `object`.
466477 // 2. `T` is a constrained TypeVar and all of `T`'s constraints are subtypes of `S`.
467478 //
468479 // However, there is one exception to this general rule: for any given typevar `T`,
469480 // `T` will always be a subtype of any union containing `T`.
470- ( Type :: TypeVar ( bound_typevar ) , Type :: Union ( union) )
471- if !bound_typevar . is_inferable ( db , inferable )
481+ ( _ , Type :: Union ( union) )
482+ if relation . can_safely_assume_reflexivity ( self )
472483 && union. elements ( db) . contains ( & self ) =>
473484 {
474485 ConstraintSet :: from ( true )
475486 }
476487
477488 // A similar rule applies in reverse to intersection types.
478- ( Type :: Intersection ( intersection) , Type :: TypeVar ( bound_typevar ) )
479- if !bound_typevar . is_inferable ( db , inferable )
489+ ( Type :: Intersection ( intersection) , _ )
490+ if relation . can_safely_assume_reflexivity ( target )
480491 && intersection. positive ( db) . contains ( & target) =>
481492 {
482493 ConstraintSet :: from ( true )
483494 }
484- ( Type :: Intersection ( intersection) , Type :: TypeVar ( bound_typevar ) )
485- if !bound_typevar . is_inferable ( db , inferable )
486- && intersection. negative ( db) . contains ( & target ) =>
495+ ( Type :: Intersection ( intersection) , _ )
496+ if relation . is_assignability ( )
497+ && intersection. positive ( db) . iter ( ) . any ( Type :: is_dynamic ) =>
487498 {
488- ConstraintSet :: from ( false )
499+ // If the intersection contains `Any`/`Unknown`/`@Todo`, it is assignable to any type.
500+ // `Any` could materialize to `Never`, `Never & T & ~S` simplifies to `Never` for any
501+ // `T` and any `S`, and `Never` is a subtype of all types.
502+ ConstraintSet :: from ( true )
489503 }
490-
491- // Two identical typevars must always solve to the same type, so they are always
492- // subtypes of each other and assignable to each other.
493- //
494- // Note that this is not handled by the early return at the beginning of this method,
495- // since subtyping between a TypeVar and an arbitrary other type cannot be guaranteed to be reflexive.
496- ( Type :: TypeVar ( lhs_bound_typevar) , Type :: TypeVar ( rhs_bound_typevar) )
497- if !lhs_bound_typevar. is_inferable ( db, inferable)
498- && lhs_bound_typevar. is_same_typevar_as ( db, rhs_bound_typevar) =>
504+ ( Type :: Intersection ( intersection) , _)
505+ if relation. can_safely_assume_reflexivity ( target)
506+ && intersection. negative ( db) . contains ( & target) =>
499507 {
500- ConstraintSet :: from ( true )
508+ ConstraintSet :: from ( false )
501509 }
502510
503511 // `type[T]` is a subtype of the class object `A` if every instance of `T` is a subtype of an instance
0 commit comments