mirror of
https://github.com/astral-sh/ruff.git
synced 2025-11-19 20:24:27 +00:00
[ty] Prefer exact matches when solving constrained type variables (#21165)
## Summary The solver is currently order-dependent, and will choose a supertype over the exact type if it appears earlier in the list of constraints. We could be smarter and try to choose the most precise subtype, but I imagine this is something the new constraint solver will fix anyways, and this fixes the issue showing up on https://github.com/astral-sh/ruff/pull/21070.
This commit is contained in:
parent
cf4e82d4b0
commit
1d6ae8596a
2 changed files with 33 additions and 0 deletions
|
|
@ -545,3 +545,28 @@ def f(x: T, y: Not[T]) -> T:
|
|||
y = x # error: [invalid-assignment]
|
||||
return x
|
||||
```
|
||||
|
||||
## Prefer exact matches for constrained typevars
|
||||
|
||||
```py
|
||||
from typing import TypeVar
|
||||
|
||||
class Base: ...
|
||||
class Sub(Base): ...
|
||||
|
||||
# We solve to `Sub`, regardless of the order of constraints.
|
||||
T = TypeVar("T", Base, Sub)
|
||||
T2 = TypeVar("T2", Sub, Base)
|
||||
|
||||
def f(x: T) -> list[T]:
|
||||
return [x]
|
||||
|
||||
def f2(x: T2) -> list[T2]:
|
||||
return [x]
|
||||
|
||||
x: list[Sub] = f(Sub())
|
||||
reveal_type(x) # revealed: list[Sub]
|
||||
|
||||
y: list[Sub] = f2(Sub())
|
||||
reveal_type(y) # revealed: list[Sub]
|
||||
```
|
||||
|
|
|
|||
|
|
@ -1483,6 +1483,14 @@ impl<'db> SpecializationBuilder<'db> {
|
|||
self.add_type_mapping(bound_typevar, ty);
|
||||
}
|
||||
Some(TypeVarBoundOrConstraints::Constraints(constraints)) => {
|
||||
// Prefer an exact match first.
|
||||
for constraint in constraints.elements(self.db) {
|
||||
if ty == *constraint {
|
||||
self.add_type_mapping(bound_typevar, ty);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
for constraint in constraints.elements(self.db) {
|
||||
if ty
|
||||
.when_assignable_to(self.db, *constraint, self.inferable)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue