Skip to content

Conversation

@mtshiba
Copy link
Contributor

@mtshiba mtshiba commented Nov 3, 2025

Summary

While investigating the cause of the panics seen since #20962, I found that intersection types containing Divergent types were incorrectly reduced by unioning them with another dynamic types.
This prevents tracking of Divergent types in fixed-point iteration.

This PR fixes the logic of Type::is_redundant_with to prevent the panic from occurring.

(BTW, another panic in pr_20962_comprehension_panics.md has been confirmed to disappear by #20566)

Test Plan

corpus/cyclic_comprehensions.py is added.

@github-actions
Copy link
Contributor

github-actions bot commented Nov 3, 2025

Diagnostic diff on typing conformance tests

No changes detected when running ty on typing conformance tests ✅

@github-actions
Copy link
Contributor

github-actions bot commented Nov 3, 2025

mypy_primer results

No ecosystem changes detected ✅
No memory usage changes detected ✅

@AlexWaygood AlexWaygood added the ty Multi-file analysis & type inference label Nov 3, 2025
@mtshiba mtshiba closed this Nov 3, 2025
@mtshiba mtshiba reopened this Nov 3, 2025
@AlexWaygood
Copy link
Member

Nice, thank you!

I was initially confused about why we didn't need this for the branch above this, but I see that it should be handled by an earlier branch. We could possibly add a debug_assert!() for the benefit of future readers:

diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs
index 6efa8950f2..45a4b2aad5 100644
--- a/crates/ty_python_semantic/src/types.rs
+++ b/crates/ty_python_semantic/src/types.rs
@@ -1699,15 +1699,22 @@ impl<'db> Type<'db> {
             // holds true if `T` is also a dynamic type or a union that contains a dynamic type.
             // Similarly, `T <: Any` only holds true if `T` is a dynamic type or an intersection
             // that contains a dynamic type.
-            (Type::Dynamic(_), _) => ConstraintSet::from(match relation {
-                TypeRelation::Subtyping => false,
-                TypeRelation::Assignability => true,
-                TypeRelation::Redundancy => match target {
-                    Type::Dynamic(_) => true,
-                    Type::Union(union) => union.elements(db).iter().any(Type::is_dynamic),
-                    _ => false,
-                },
-            }),
+            (Type::Dynamic(dynamic), _) => {
+                // If a `Divergent` type is involved, it must not be eliminated.
+                debug_assert!(
+                    !matches!(dynamic, DynamicType::Divergent(_)),
+                    "DynamicType::Divergent should have been handled in an earlier branch"
+                );
+                ConstraintSet::from(match relation {
+                    TypeRelation::Subtyping => false,
+                    TypeRelation::Assignability => true,
+                    TypeRelation::Redundancy => match target {
+                        Type::Dynamic(_) => true,
+                        Type::Union(union) => union.elements(db).iter().any(Type::is_dynamic),
+                        _ => false,
+                    },
+                })
+            }
             (_, Type::Dynamic(_)) => ConstraintSet::from(match relation {
                 TypeRelation::Subtyping => false,
                 TypeRelation::Assignability => true,

@mtshiba mtshiba marked this pull request as ready for review November 3, 2025 15:36
@AlexWaygood AlexWaygood changed the title [ty] Do not simplify intersection types with Divergent types within a union type [ty] Fix panic due to simplifying Divergent types out of intersections types Nov 3, 2025
@AlexWaygood AlexWaygood added the bug Something isn't working label Nov 3, 2025
@AlexWaygood AlexWaygood enabled auto-merge (squash) November 3, 2025 15:38
@AlexWaygood AlexWaygood merged commit b5305b5 into astral-sh:main Nov 3, 2025
41 checks passed
@mtshiba mtshiba deleted the divergent-is-not-redundant branch November 3, 2025 15:41
@carljm
Copy link
Contributor

carljm commented Nov 3, 2025

Especially with the changes in #20566, I start to wonder if Divergent should perhaps not be a variant of Dynamic at all, or if it would be less error-prone to make it a distinct top-level Type so we have to consider its behavior separately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working ty Multi-file analysis & type inference

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants