mirror of https://github.com/astral-sh/ruff
test fixes from codex
This commit is contained in:
parent
290868b71d
commit
2d301b63bb
|
|
@ -1756,6 +1756,24 @@ impl<'db> Type<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
match (self, target) {
|
match (self, target) {
|
||||||
|
// Pretend that instances of `dataclasses.Field` are assignable to their default type.
|
||||||
|
// This allows field definitions like `name: str = field(default="")` in dataclasses
|
||||||
|
// to pass the assignability check of the inferred type to the declared type.
|
||||||
|
(Type::KnownInstance(KnownInstanceType::Field(field)), right)
|
||||||
|
if relation.is_assignability() =>
|
||||||
|
{
|
||||||
|
field.default_type(db).when_none_or(|default_type| {
|
||||||
|
default_type.has_relation_to_impl(
|
||||||
|
db,
|
||||||
|
right,
|
||||||
|
inferable,
|
||||||
|
relation,
|
||||||
|
relation_visitor,
|
||||||
|
disjointness_visitor,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Two identical typevars must always solve to the same type, so they are always
|
// Two identical typevars must always solve to the same type, so they are always
|
||||||
// subtypes of each other and assignable to each other.
|
// subtypes of each other and assignable to each other.
|
||||||
//
|
//
|
||||||
|
|
@ -1766,6 +1784,30 @@ impl<'db> Type<'db> {
|
||||||
{
|
{
|
||||||
ConstraintSet::from(true)
|
ConstraintSet::from(true)
|
||||||
}
|
}
|
||||||
|
(Type::TypeVar(lhs_bound_typevar), Type::TypeVar(rhs_bound_typevar))
|
||||||
|
if relation.is_assignability()
|
||||||
|
&& lhs_bound_typevar.typevar(db).identity(db)
|
||||||
|
== rhs_bound_typevar.typevar(db).identity(db) =>
|
||||||
|
{
|
||||||
|
ConstraintSet::from(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Typevars with non-fully-static bounds or constraints do not participate in
|
||||||
|
// subtyping while they are in a non-inferable position.
|
||||||
|
(Type::TypeVar(bound_typevar), _)
|
||||||
|
if relation.is_subtyping()
|
||||||
|
&& !bound_typevar.is_inferable(db, inferable)
|
||||||
|
&& !bound_typevar.has_fully_static_bound_or_constraints(db) =>
|
||||||
|
{
|
||||||
|
ConstraintSet::from(false)
|
||||||
|
}
|
||||||
|
(_, Type::TypeVar(bound_typevar))
|
||||||
|
if relation.is_subtyping()
|
||||||
|
&& !bound_typevar.is_inferable(db, inferable)
|
||||||
|
&& !bound_typevar.has_fully_static_bound_or_constraints(db) =>
|
||||||
|
{
|
||||||
|
ConstraintSet::from(false)
|
||||||
|
}
|
||||||
|
|
||||||
// A typevar satisfies a relation when...it satisfies the relation. Yes that's a
|
// A typevar satisfies a relation when...it satisfies the relation. Yes that's a
|
||||||
// tautology! We're moving the caller's subtyping/assignability requirement into a
|
// tautology! We're moving the caller's subtyping/assignability requirement into a
|
||||||
|
|
@ -1825,24 +1867,6 @@ impl<'db> Type<'db> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pretend that instances of `dataclasses.Field` are assignable to their default type.
|
|
||||||
// This allows field definitions like `name: str = field(default="")` in dataclasses
|
|
||||||
// to pass the assignability check of the inferred type to the declared type.
|
|
||||||
(Type::KnownInstance(KnownInstanceType::Field(field)), right)
|
|
||||||
if relation.is_assignability() =>
|
|
||||||
{
|
|
||||||
field.default_type(db).when_none_or(|default_type| {
|
|
||||||
default_type.has_relation_to_impl(
|
|
||||||
db,
|
|
||||||
right,
|
|
||||||
inferable,
|
|
||||||
relation,
|
|
||||||
relation_visitor,
|
|
||||||
disjointness_visitor,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dynamic is only a subtype of `object` and only a supertype of `Never`; both were
|
// Dynamic is only a subtype of `object` and only a supertype of `Never`; both were
|
||||||
// handled above. It's always assignable, though.
|
// handled above. It's always assignable, though.
|
||||||
//
|
//
|
||||||
|
|
@ -1991,12 +2015,12 @@ impl<'db> Type<'db> {
|
||||||
self_function.has_relation_to_impl(
|
self_function.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
target_function,
|
target_function,
|
||||||
inferable,
|
inferable,
|
||||||
relation,
|
relation,
|
||||||
relation_visitor,
|
relation_visitor,
|
||||||
disjointness_visitor,
|
disjointness_visitor,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
(Type::BoundMethod(self_method), Type::BoundMethod(target_method)) => self_method
|
(Type::BoundMethod(self_method), Type::BoundMethod(target_method)) => self_method
|
||||||
.has_relation_to_impl(
|
.has_relation_to_impl(
|
||||||
db,
|
db,
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,25 @@ impl<'db> BoundTypeVarInstance<'db> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns `true` if all bounds or constraints on this typevar are fully static.
|
||||||
|
///
|
||||||
|
/// A type is fully static if its top and bottom materializations are the same; dynamic types
|
||||||
|
/// (like `Any`) will have different materializations.
|
||||||
|
pub(crate) fn has_fully_static_bound_or_constraints(self, db: &'db dyn Db) -> bool {
|
||||||
|
match self.typevar(db).bound_or_constraints(db) {
|
||||||
|
None => true,
|
||||||
|
Some(TypeVarBoundOrConstraints::UpperBound(bound)) => {
|
||||||
|
bound.top_materialization(db) == bound.bottom_materialization(db)
|
||||||
|
}
|
||||||
|
Some(TypeVarBoundOrConstraints::Constraints(constraints)) => constraints
|
||||||
|
.elements(db)
|
||||||
|
.iter()
|
||||||
|
.all(|constraint| {
|
||||||
|
constraint.top_materialization(db) == constraint.bottom_materialization(db)
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'db> InferableTypeVars<'a, 'db> {
|
impl<'a, 'db> InferableTypeVars<'a, 'db> {
|
||||||
|
|
@ -1521,6 +1540,20 @@ impl<'db> SpecializationBuilder<'db> {
|
||||||
let bound_typevars =
|
let bound_typevars =
|
||||||
(formal.elements(self.db).iter()).filter_map(|ty| ty.as_typevar());
|
(formal.elements(self.db).iter()).filter_map(|ty| ty.as_typevar());
|
||||||
if let Ok(bound_typevar) = bound_typevars.exactly_one() {
|
if let Ok(bound_typevar) = bound_typevars.exactly_one() {
|
||||||
|
// If the actual argument can be satisfied by a non-typevar element of the
|
||||||
|
// union, then prefer that element and avoid inferring a mapping for the
|
||||||
|
// typevar. This lets other occurrences of the typevar (if any) drive the
|
||||||
|
// specialization instead of opportunistically binding it here.
|
||||||
|
let matches_non_typevar = formal.elements(self.db).iter().any(|ty| {
|
||||||
|
!ty.has_typevar(self.db)
|
||||||
|
&& actual
|
||||||
|
.when_subtype_of(self.db, *ty, self.inferable)
|
||||||
|
.satisfied_by_all_typevars(self.db, self.inferable)
|
||||||
|
});
|
||||||
|
if matches_non_typevar {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
self.add_type_mapping(bound_typevar, actual, polarity, f);
|
self.add_type_mapping(bound_typevar, actual, polarity, f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue