@@ -463,11 +463,10 @@ impl<'db> UnionBuilder<'db> {
463463 None
464464 } ;
465465
466- // If an alias gets here, it means we aren't unpacking aliases, and we also shouldn't try
467- // to simplify aliases out of the union, because that will require unpacking them.
468- // `TypedDict`s also run into trouble here when their fields refer to a recursive union, so
469- // and we need to skip simplification to break cycles.
470- let should_simplify_full = !matches ! ( ty, Type :: TypeAlias ( _) | Type :: TypedDict ( _) ) ;
466+ // If an alias gets here, it means we aren't unpacking aliases, and we also
467+ // shouldn't try to simplify aliases out of the union, because that will require
468+ // unpacking them.
469+ let should_simplify_full = !matches ! ( ty, Type :: TypeAlias ( _) ) ;
471470
472471 let mut to_remove = SmallVec :: < [ usize ; 2 ] > :: new ( ) ;
473472 let ty_negated = if should_simplify_full {
@@ -503,6 +502,18 @@ impl<'db> UnionBuilder<'db> {
503502 return ;
504503 }
505504
505+ // Comparing `TypedDict`s for redundancy requires iterating over their fields, which is
506+ // problematic if some of those fields point to recursive `Union`s. To avoid cycles,
507+ // compare `TypedDict`s by name/identity instead of using the `has_relation_to`
508+ // machinery.
509+ if let ( Type :: TypedDict ( element_td) , Type :: TypedDict ( ty_td) ) = ( element_type, ty) {
510+ if element_td == ty_td {
511+ return ;
512+ } else {
513+ continue ;
514+ }
515+ }
516+
506517 if should_simplify_full && !matches ! ( element_type, Type :: TypeAlias ( _) ) {
507518 if ty. is_redundant_with ( self . db , element_type) {
508519 return ;
0 commit comments