@@ -4346,32 +4346,52 @@ impl<'db> GeneralCallableType<'db> {
43464346 . is_some_and ( |return_type| return_type. is_fully_static ( db) )
43474347 }
43484348
4349+ /// Return `true` if `self` has exactly the same set of possible static materializations as
4350+ /// `other` (if `self` represents the same set of possible sets of possible runtime objects as
4351+ /// `other`).
4352+ pub ( crate ) fn is_gradual_equivalent_to ( self , db : & ' db dyn Db , other : Self ) -> bool {
4353+ self . is_equivalent_to_impl ( db, other, |self_type, other_type| {
4354+ self_type
4355+ . unwrap_or ( Type :: unknown ( ) )
4356+ . is_gradual_equivalent_to ( db, other_type. unwrap_or ( Type :: unknown ( ) ) )
4357+ } )
4358+ }
4359+
43494360 /// Return `true` if `self` represents the exact same set of possible runtime objects as `other`.
43504361 pub ( crate ) fn is_equivalent_to ( self , db : & ' db dyn Db , other : Self ) -> bool {
4362+ self . is_equivalent_to_impl ( db, other, |self_type, other_type| {
4363+ match ( self_type, other_type) {
4364+ ( Some ( self_type) , Some ( other_type) ) => self_type. is_equivalent_to ( db, other_type) ,
4365+ // We need the catch-all case here because it's not guaranteed that this is a fully
4366+ // static type.
4367+ _ => false ,
4368+ }
4369+ } )
4370+ }
4371+
4372+ /// Implementation for the [`is_equivalent_to`] and [`is_gradual_equivalent_to`] for callable
4373+ /// types.
4374+ ///
4375+ /// [`is_equivalent_to`]: Self::is_equivalent_to
4376+ /// [`is_gradual_equivalent_to`]: Self::is_gradual_equivalent_to
4377+ fn is_equivalent_to_impl < F > ( self , db : & ' db dyn Db , other : Self , check_types : F ) -> bool
4378+ where
4379+ F : Fn ( Option < Type < ' db > > , Option < Type < ' db > > ) -> bool ,
4380+ {
43514381 let self_signature = self . signature ( db) ;
43524382 let other_signature = other. signature ( db) ;
43534383
4384+ // N.B. We don't need to explicitly check for the use of gradual form (`...`) in the
4385+ // parameters because it is internally represented by adding `*Any` and `**Any` to the
4386+ // parameter list.
43544387 let self_parameters = self_signature. parameters ( ) ;
43554388 let other_parameters = other_signature. parameters ( ) ;
43564389
43574390 if self_parameters. len ( ) != other_parameters. len ( ) {
43584391 return false ;
43594392 }
43604393
4361- if self_parameters. is_gradual ( ) || other_parameters. is_gradual ( ) {
4362- return false ;
4363- }
4364-
4365- // Check equivalence relationship between two optional types. If either of them is `None`,
4366- // then it is not a fully static type which means it's not equivalent either.
4367- let is_equivalent = |self_type : Option < Type < ' db > > , other_type : Option < Type < ' db > > | match (
4368- self_type, other_type,
4369- ) {
4370- ( Some ( self_type) , Some ( other_type) ) => self_type. is_equivalent_to ( db, other_type) ,
4371- _ => false ,
4372- } ;
4373-
4374- if !is_equivalent ( self_signature. return_ty , other_signature. return_ty ) {
4394+ if !check_types ( self_signature. return_ty , other_signature. return_ty ) {
43754395 return false ;
43764396 }
43774397
@@ -4419,7 +4439,7 @@ impl<'db> GeneralCallableType<'db> {
44194439 _ => return false ,
44204440 }
44214441
4422- if !is_equivalent (
4442+ if !check_types (
44234443 self_parameter. annotated_type ( ) ,
44244444 other_parameter. annotated_type ( ) ,
44254445 ) {
@@ -4430,48 +4450,6 @@ impl<'db> GeneralCallableType<'db> {
44304450 true
44314451 }
44324452
4433- /// Return `true` if `self` has exactly the same set of possible static materializations as
4434- /// `other` (if `self` represents the same set of possible sets of possible runtime objects as
4435- /// `other`).
4436- pub ( crate ) fn is_gradual_equivalent_to ( self , db : & ' db dyn Db , other : Self ) -> bool {
4437- let self_signature = self . signature ( db) ;
4438- let other_signature = other. signature ( db) ;
4439-
4440- if self_signature. parameters ( ) . len ( ) != other_signature. parameters ( ) . len ( ) {
4441- return false ;
4442- }
4443-
4444- // Check gradual equivalence between the two optional types. In the context of a callable
4445- // type, the `None` type represents an `Unknown` type.
4446- let are_optional_types_gradually_equivalent =
4447- |self_type : Option < Type < ' db > > , other_type : Option < Type < ' db > > | {
4448- self_type
4449- . unwrap_or ( Type :: unknown ( ) )
4450- . is_gradual_equivalent_to ( db, other_type. unwrap_or ( Type :: unknown ( ) ) )
4451- } ;
4452-
4453- if !are_optional_types_gradually_equivalent (
4454- self_signature. return_ty ,
4455- other_signature. return_ty ,
4456- ) {
4457- return false ;
4458- }
4459-
4460- // N.B. We don't need to explicitly check for the use of gradual form (`...`) in the
4461- // parameters because it is internally represented by adding `*Any` and `**Any` to the
4462- // parameter list.
4463- self_signature
4464- . parameters ( )
4465- . iter ( )
4466- . zip ( other_signature. parameters ( ) . iter ( ) )
4467- . all ( |( self_param, other_param) | {
4468- are_optional_types_gradually_equivalent (
4469- self_param. annotated_type ( ) ,
4470- other_param. annotated_type ( ) ,
4471- )
4472- } )
4473- }
4474-
44754453 /// Return `true` if `self` is assignable to `other`.
44764454 pub ( crate ) fn is_assignable_to ( self , db : & ' db dyn Db , other : Self ) -> bool {
44774455 self . is_assignable_to_impl ( db, other, |type1, type2| {
@@ -4483,6 +4461,10 @@ impl<'db> GeneralCallableType<'db> {
44834461 }
44844462
44854463 /// Return `true` if `self` is a subtype of `other`.
4464+ ///
4465+ /// # Panics
4466+ ///
4467+ /// Panics if `self` or `other` is not a fully static type.
44864468 pub ( crate ) fn is_subtype_of ( self , db : & ' db dyn Db , other : Self ) -> bool {
44874469 self . is_assignable_to_impl ( db, other, |type1, type2| {
44884470 // SAFETY: Subtype relation is only checked for fully static types.
0 commit comments