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 a0f1c3fd8b..167fe4025d 100644 --- a/crates/ty_python_semantic/resources/mdtest/pep695_type_aliases.md +++ b/crates/ty_python_semantic/resources/mdtest/pep695_type_aliases.md @@ -313,6 +313,23 @@ static_assert(is_subtype_of(Bottom[JsonDict], Bottom[JsonDict])) static_assert(is_subtype_of(Bottom[JsonDict], Top[JsonDict])) ``` +### Cyclic defaults + +```py +from typing_extensions import Protocol, TypeVar + +T = TypeVar("T", default="C", covariant=True) + +class P(Protocol[T]): + pass + +class C(P[T]): + pass + +reveal_type(C[int]()) # revealed: C[int] +reveal_type(C()) # revealed: C[Divergent] +``` + ### Union inside generic #### With old-style union diff --git a/crates/ty_python_semantic/resources/primer/bad.txt b/crates/ty_python_semantic/resources/primer/bad.txt index 1a4f3eed3e..45414db491 100644 --- a/crates/ty_python_semantic/resources/primer/bad.txt +++ b/crates/ty_python_semantic/resources/primer/bad.txt @@ -1,2 +1,2 @@ spark # too many iterations (in `exported_names` query), `should not be able to access instance member `spark` of type variable IndexOpsLike@astype in inferable position` -steam.py # dependency graph cycle when querying TypeVarInstance < 'db >::lazy_default_(Id(2e007)), set cycle_fn/cycle_initial to fixpoint iterate. +steam.py # too many iterations diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index 1c0355862d..91c51c5e83 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -8344,7 +8344,7 @@ impl<'db> TypeVarInstance<'db> { Some(TypeVarBoundOrConstraints::Constraints(ty)) } - #[salsa::tracked(heap_size=ruff_memory_usage::heap_size)] + #[salsa::tracked(cycle_initial=lazy_default_cycle_initial, heap_size=ruff_memory_usage::heap_size)] fn lazy_default(self, db: &'db dyn Db) -> Option> { let definition = self.definition(db)?; let module = parsed_module(db, definition.file(db)).load(db); @@ -8391,6 +8391,13 @@ fn lazy_bound_or_constraints_cycle_initial<'db>( None } +fn lazy_default_cycle_initial<'db>( + _db: &'db dyn Db, + _self: TypeVarInstance<'db>, +) -> Option> { + None +} + /// Where a type variable is bound and usable. #[derive( Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd, salsa::Update, get_size2::GetSize,