@@ -1372,31 +1372,6 @@ impl<'db> SpecializationBuilder<'db> {
13721372 return Ok ( ( ) ) ;
13731373 }
13741374
1375- // If the actual type is a subtype of the formal type, then return without adding any new
1376- // type mappings. (Note that if the formal type contains any typevars, this check will
1377- // fail, since no non-typevar types are assignable to a typevar. Also note that we are
1378- // checking _subtyping_, not _assignability_, so that we do specialize typevars to dynamic
1379- // argument types; and we have a special case for `Never`, which is a subtype of all types,
1380- // but which we also do want as a specialization candidate.)
1381- //
1382- // In particular, this handles a case like
1383- //
1384- // ```py
1385- // def f[T](t: T | None): ...
1386- //
1387- // f(None)
1388- // ```
1389- //
1390- // without specializing `T` to `None`.
1391- if !matches ! ( formal, Type :: ProtocolInstance ( _) )
1392- && !actual. is_never ( )
1393- && actual
1394- . when_subtype_of ( self . db , formal, self . inferable )
1395- . is_always_satisfied ( self . db )
1396- {
1397- return Ok ( ( ) ) ;
1398- }
1399-
14001375 // Remove the union elements from `actual` that are not related to `formal`, and vice
14011376 // versa.
14021377 //
@@ -1452,10 +1427,30 @@ impl<'db> SpecializationBuilder<'db> {
14521427 self . add_type_mapping ( * formal_bound_typevar, remaining_actual) ;
14531428 }
14541429 ( Type :: Union ( formal) , _) => {
1455- // Second, if the formal is a union, and precisely one union element _is_ a typevar (not
1456- // _contains_ a typevar), then we add a mapping between that typevar and the actual
1457- // type. (Note that we've already handled above the case where the actual is
1458- // assignable to any _non-typevar_ union element.)
1430+ // Second, if the formal is a union, and precisely one union element is assignable
1431+ // from the actual type, then we don't add any type mapping. This handles a case like
1432+ //
1433+ // ```py
1434+ // def f[T](t: T | None): ...
1435+ //
1436+ // f(None)
1437+ // ```
1438+ //
1439+ // without specializing `T` to `None`.
1440+ //
1441+ // Otherwise, if precisely one union element _is_ a typevar (not _contains_ a
1442+ // typevar), then we add a mapping between that typevar and the actual type.
1443+ if !actual. is_never ( ) {
1444+ let assignable_elements = ( formal. elements ( self . db ) . iter ( ) ) . filter ( |ty| {
1445+ actual
1446+ . when_subtype_of ( self . db , * * ty, self . inferable )
1447+ . is_always_satisfied ( self . db )
1448+ } ) ;
1449+ if assignable_elements. exactly_one ( ) . is_ok ( ) {
1450+ return Ok ( ( ) ) ;
1451+ }
1452+ }
1453+
14591454 let bound_typevars =
14601455 ( formal. elements ( self . db ) . iter ( ) ) . filter_map ( |ty| ty. as_typevar ( ) ) ;
14611456 if let Ok ( bound_typevar) = bound_typevars. exactly_one ( ) {
0 commit comments