mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-21 15:52:34 +00:00
[ty] Fix panic on recursive class definitions in a stub that use constrained type variables (#20955)
This commit is contained in:
parent
7532155c9b
commit
16efe53a72
3 changed files with 55 additions and 4 deletions
|
@ -753,5 +753,29 @@ class C(C, Generic[T]): ...
|
|||
class D(D[int], Generic[T]): ...
|
||||
```
|
||||
|
||||
### Cyclic inheritance in a stub file combined with constrained type variables
|
||||
|
||||
This is a regression test for <https://github.com/astral-sh/ty/issues/1390>; we used to panic on
|
||||
this:
|
||||
|
||||
`stub.pyi`:
|
||||
|
||||
```pyi
|
||||
from typing import Generic, TypeVar
|
||||
|
||||
class A(B): ...
|
||||
class G: ...
|
||||
|
||||
T = TypeVar("T", G, A)
|
||||
|
||||
class C(Generic[T]): ...
|
||||
class B(C[A]): ...
|
||||
class D(C[G]): ...
|
||||
|
||||
def func(x: D): ...
|
||||
|
||||
func(G()) # error: [invalid-argument-type]
|
||||
```
|
||||
|
||||
[crtp]: https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern
|
||||
[f-bound]: https://en.wikipedia.org/wiki/Bounded_quantification#F-bounded_quantification
|
||||
|
|
|
@ -638,6 +638,25 @@ class C[T](C): ...
|
|||
class D[T](D[int]): ...
|
||||
```
|
||||
|
||||
### Cyclic inheritance in a stub file combined with constrained type variables
|
||||
|
||||
This is a regression test for <https://github.com/astral-sh/ty/issues/1390>; we used to panic on
|
||||
this:
|
||||
|
||||
`stub.pyi`:
|
||||
|
||||
```pyi
|
||||
class A(B): ...
|
||||
class G: ...
|
||||
class C[T: (G, A)]: ...
|
||||
class B(C[A]): ...
|
||||
class D(C[G]): ...
|
||||
|
||||
def func(x: D): ...
|
||||
|
||||
func(G()) # error: [invalid-argument-type]
|
||||
```
|
||||
|
||||
## Tuple as a PEP-695 generic class
|
||||
|
||||
Our special handling for `tuple` does not break if `tuple` is defined as a PEP-695 generic class in
|
||||
|
|
|
@ -8303,7 +8303,11 @@ impl<'db> TypeVarInstance<'db> {
|
|||
))
|
||||
}
|
||||
|
||||
#[salsa::tracked(cycle_fn=lazy_bound_cycle_recover, cycle_initial=lazy_bound_cycle_initial, heap_size=ruff_memory_usage::heap_size)]
|
||||
#[salsa::tracked(
|
||||
cycle_fn=lazy_bound_or_constraints_cycle_recover,
|
||||
cycle_initial=lazy_bound_or_constraints_cycle_initial,
|
||||
heap_size=ruff_memory_usage::heap_size
|
||||
)]
|
||||
fn lazy_bound(self, db: &'db dyn Db) -> Option<TypeVarBoundOrConstraints<'db>> {
|
||||
let definition = self.definition(db)?;
|
||||
let module = parsed_module(db, definition.file(db)).load(db);
|
||||
|
@ -8324,7 +8328,11 @@ impl<'db> TypeVarInstance<'db> {
|
|||
Some(TypeVarBoundOrConstraints::UpperBound(ty))
|
||||
}
|
||||
|
||||
#[salsa::tracked(heap_size=ruff_memory_usage::heap_size)]
|
||||
#[salsa::tracked(
|
||||
cycle_fn=lazy_bound_or_constraints_cycle_recover,
|
||||
cycle_initial=lazy_bound_or_constraints_cycle_initial,
|
||||
heap_size=ruff_memory_usage::heap_size
|
||||
)]
|
||||
fn lazy_constraints(self, db: &'db dyn Db) -> Option<TypeVarBoundOrConstraints<'db>> {
|
||||
let definition = self.definition(db)?;
|
||||
let module = parsed_module(db, definition.file(db)).load(db);
|
||||
|
@ -8385,7 +8393,7 @@ impl<'db> TypeVarInstance<'db> {
|
|||
}
|
||||
|
||||
#[allow(clippy::ref_option)]
|
||||
fn lazy_bound_cycle_recover<'db>(
|
||||
fn lazy_bound_or_constraints_cycle_recover<'db>(
|
||||
_db: &'db dyn Db,
|
||||
_value: &Option<TypeVarBoundOrConstraints<'db>>,
|
||||
_count: u32,
|
||||
|
@ -8394,7 +8402,7 @@ fn lazy_bound_cycle_recover<'db>(
|
|||
salsa::CycleRecoveryAction::Iterate
|
||||
}
|
||||
|
||||
fn lazy_bound_cycle_initial<'db>(
|
||||
fn lazy_bound_or_constraints_cycle_initial<'db>(
|
||||
_db: &'db dyn Db,
|
||||
_self: TypeVarInstance<'db>,
|
||||
) -> Option<TypeVarBoundOrConstraints<'db>> {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue