mirror of https://github.com/astral-sh/ruff
abstract over any mention of a typevar
This commit is contained in:
parent
3cb4b0ecb9
commit
438de79a6b
|
|
@ -348,7 +348,8 @@ from ty_extensions import ConstraintSet, generic_context
|
||||||
def mentions[T, U]():
|
def mentions[T, U]():
|
||||||
# (T@mentions ≤ int) ∧ (U@mentions = list[T@mentions])
|
# (T@mentions ≤ int) ∧ (U@mentions = list[T@mentions])
|
||||||
constraints = ConstraintSet.range(Never, T, int) & ConstraintSet.range(list[T], U, list[T])
|
constraints = ConstraintSet.range(Never, T, int) & ConstraintSet.range(list[T], U, list[T])
|
||||||
# revealed: ty_extensions.Specialization[T@mentions = int, U@mentions = list[int]]
|
# TODO: revealed: ty_extensions.Specialization[T@mentions = int, U@mentions = list[int]]
|
||||||
|
# revealed: ty_extensions.Specialization[T@mentions = int, U@mentions = Unknown]
|
||||||
reveal_type(generic_context(mentions).specialize_constrained(constraints))
|
reveal_type(generic_context(mentions).specialize_constrained(constraints))
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,9 @@ use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use salsa::plumbing::AsId;
|
use salsa::plumbing::AsId;
|
||||||
|
|
||||||
use crate::types::generics::{GenericContext, InferableTypeVars, Specialization};
|
use crate::types::generics::{GenericContext, InferableTypeVars, Specialization};
|
||||||
use crate::types::visitor::{TypeCollector, TypeVisitor, walk_type_with_recursion_guard};
|
use crate::types::visitor::{
|
||||||
|
TypeCollector, TypeVisitor, any_over_type, walk_type_with_recursion_guard,
|
||||||
|
};
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
BoundTypeVarIdentity, BoundTypeVarInstance, IntersectionType, Type, TypeRelation,
|
BoundTypeVarIdentity, BoundTypeVarInstance, IntersectionType, Type, TypeRelation,
|
||||||
TypeVarBoundOrConstraints, UnionType, walk_bound_type_var_type,
|
TypeVarBoundOrConstraints, UnionType, walk_bound_type_var_type,
|
||||||
|
|
@ -1768,22 +1770,27 @@ impl<'db> InteriorNode<'db> {
|
||||||
fn exists_one(self, db: &'db dyn Db, bound_typevar: BoundTypeVarIdentity<'db>) -> Node<'db> {
|
fn exists_one(self, db: &'db dyn Db, bound_typevar: BoundTypeVarIdentity<'db>) -> Node<'db> {
|
||||||
let map = self.sequent_map(db);
|
let map = self.sequent_map(db);
|
||||||
let mut path = PathAssignments::default();
|
let mut path = PathAssignments::default();
|
||||||
|
let mentions_typevar = |ty: Type<'db>| match ty {
|
||||||
|
Type::TypeVar(haystack) => haystack.identity(db) == bound_typevar,
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
self.abstract_one_inner(
|
self.abstract_one_inner(
|
||||||
db,
|
db,
|
||||||
// Remove any node that constrains `bound_typevar`, or that has a lower/upper bound of
|
// Remove any node that constrains `bound_typevar`, or that has a lower/upper bound
|
||||||
// `bound_typevar`.
|
// that mentions `bound_typevar`.
|
||||||
|
// TODO: This will currently remove constraints that mention a typevar, but the sequent
|
||||||
|
// map is not yet propagating all derived facts about those constraints. For instance,
|
||||||
|
// removing `T` from `T ≤ int ∧ U ≤ Sequence[T]` should produce `U ≤ Sequence[int]`.
|
||||||
|
// But that requires `T ≤ int ∧ U ≤ Sequence[T] → U ≤ Sequence[int]` to exist in the
|
||||||
|
// sequent map. It doesn't, and so we currently produce `U ≤ Unknown` in this case.
|
||||||
&mut |constraint| {
|
&mut |constraint| {
|
||||||
if constraint.typevar(db).identity(db) == bound_typevar {
|
if constraint.typevar(db).identity(db) == bound_typevar {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if let Type::TypeVar(lower_bound_typevar) = constraint.lower(db)
|
if any_over_type(db, constraint.lower(db), &mentions_typevar, false) {
|
||||||
&& lower_bound_typevar.identity(db) == bound_typevar
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if let Type::TypeVar(upper_bound_typevar) = constraint.upper(db)
|
if any_over_type(db, constraint.upper(db), &mentions_typevar, false) {
|
||||||
&& upper_bound_typevar.identity(db) == bound_typevar
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
|
@ -1807,9 +1814,7 @@ impl<'db> InteriorNode<'db> {
|
||||||
if constraint.typevar(db).identity(db) != bound_typevar {
|
if constraint.typevar(db).identity(db) != bound_typevar {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if matches!(constraint.lower(db), Type::TypeVar(_))
|
if constraint.lower(db).has_typevar(db) || constraint.upper(db).has_typevar(db) {
|
||||||
|| matches!(constraint.upper(db), Type::TypeVar(_))
|
|
||||||
{
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue