diff --git a/crates/ty_python_semantic/resources/mdtest/attributes.md b/crates/ty_python_semantic/resources/mdtest/attributes.md index 5c40647c88184d..0a42a69406efd3 100644 --- a/crates/ty_python_semantic/resources/mdtest/attributes.md +++ b/crates/ty_python_semantic/resources/mdtest/attributes.md @@ -2741,8 +2741,7 @@ class ManyCycles2: self.x3 = [1] def f1(self: "ManyCycles2"): - # TODO: should be Unknown | list[int] | list[Divergent] - reveal_type(self.x3) # revealed: Unknown | list[int] | list[Divergent] | list[Unknown] + reveal_type(self.x3) # revealed: Unknown | list[int] | list[Divergent] self.x1 = [self.x2] + [self.x3] self.x2 = [self.x1] + [self.x3] diff --git a/crates/ty_python_semantic/resources/mdtest/pep695_type_aliases.md b/crates/ty_python_semantic/resources/mdtest/pep695_type_aliases.md index 6cc94fca6d7d5d..cdcdc7560a6a04 100644 --- a/crates/ty_python_semantic/resources/mdtest/pep695_type_aliases.md +++ b/crates/ty_python_semantic/resources/mdtest/pep695_type_aliases.md @@ -583,10 +583,17 @@ def foo(a: int, b: int) -> RecursiveT: ```py from typing_extensions import TypeGuard, TypeIs +from collections.abc import Callable type RecursiveIs = TypeIs[RecursiveIs] # error: [cyclic-type-alias-definition] type RecursiveGuard = TypeGuard[RecursiveGuard] type AliasIs = RecursiveIs # error: [cyclic-type-alias-definition] type AliasGuard = RecursiveGuard + +type CallableIs = TypeIs[Callable[[], CallableIs]] +type CallableGuard = TypeGuard[Callable[[], CallableGuard]] + +reveal_type(CallableIs) # revealed: TypeAliasType +reveal_type(CallableGuard) # revealed: TypeAliasType ``` diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 7c4b4df370459c..32db314e75cf98 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -5586,9 +5586,17 @@ impl<'db> Type<'db> { TypeMapping::ReplaceParameterDefaults | TypeMapping::EagerExpansion | TypeMapping::RescopeReturnCallables(_) => self, - TypeMapping::Materialize(materialization_kind) => match materialization_kind { - MaterializationKind::Top => Type::object(), - MaterializationKind::Bottom => Type::Never, + TypeMapping::Materialize(materialization_kind) => match self { + // `Divergent` is an internal cycle marker rather than a gradual type like + // `Any` or `Unknown`. Materializing it away would destroy the marker we rely + // on for recursive alias convergence. + // TODO: We elsewhere treat `Divergent` as a dynamic type, so failing to + // materialize it away here could lead to odd behavior. + Type::Dynamic(DynamicType::Divergent(_)) => self, + _ => match materialization_kind { + MaterializationKind::Top => Type::object(), + MaterializationKind::Bottom => Type::Never, + }, } }