mirror of https://github.com/astral-sh/ruff
better predicate for skipping typevars
This commit is contained in:
parent
745f4d95ba
commit
dbab2c43c4
|
|
@ -1903,6 +1903,20 @@ impl<'db> Type<'db> {
|
|||
self.has_relation_to(db, target, inferable, TypeRelation::Assignability)
|
||||
}
|
||||
|
||||
fn when_constraint_set_assignable_to(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
target: Type<'db>,
|
||||
inferable: InferableTypeVars<'_, 'db>,
|
||||
) -> ConstraintSet<'db> {
|
||||
self.has_relation_to(
|
||||
db,
|
||||
target,
|
||||
inferable,
|
||||
TypeRelation::ConstraintSetAssignability,
|
||||
)
|
||||
}
|
||||
|
||||
/// Return `true` if it would be redundant to add `self` to a union that already contains `other`.
|
||||
///
|
||||
/// See [`TypeRelation::Redundancy`] for more details.
|
||||
|
|
|
|||
|
|
@ -3017,7 +3017,7 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
|
|||
FxHashMap::default();
|
||||
|
||||
let parameters = self.signature.parameters();
|
||||
for (argument_index, adjusted_argument_index, argument, argument_type) in
|
||||
for (argument_index, adjusted_argument_index, _, argument_type) in
|
||||
self.enumerate_argument_types()
|
||||
{
|
||||
for (parameter_index, variadic_argument_type) in
|
||||
|
|
@ -3029,28 +3029,25 @@ impl<'a, 'db> ArgumentTypeChecker<'a, 'db> {
|
|||
};
|
||||
|
||||
// Below, we will possibly perform literal promotion on the types that we infer for
|
||||
// each typevar. Whether we do so will depend on the variance of the typevar in the
|
||||
// parameter type that each argument is mapped to.
|
||||
//
|
||||
// Note that we do not track the variance for synthetic `self` arguments. Those
|
||||
// only exist for generic methods of a (possibly generic) class. The class instance
|
||||
// is fixed for any generic method call, and shouldn't affect literal promotion.
|
||||
// (This is true even for the constructors of a generic class: a `self` annotation
|
||||
// on `__init__` limits which specializations the constructor overload applies to,
|
||||
// but we rely on occurrences of a typevar in other parameters to determine whether
|
||||
// to promote literals in the specialized generic class type.)
|
||||
if !matches!(argument, Argument::Synthetic)
|
||||
&& parameter.form == ParameterForm::Value
|
||||
&& expected_type.has_typevar(self.db)
|
||||
{
|
||||
for bound_typevar in generic_context_variables.clone() {
|
||||
let variance = expected_type.variance_of(self.db, bound_typevar);
|
||||
if variance != TypeVarVariance::Bivariant {
|
||||
variance_in_arguments
|
||||
.entry(bound_typevar.identity(self.db))
|
||||
.and_modify(|current| *current = current.join(variance))
|
||||
.or_insert(variance);
|
||||
}
|
||||
// each typevar. Whether we do so will depend on which arguments affect the
|
||||
// specialization of the typevar, and what variance the typevar has in the
|
||||
// corresponding parameter type.
|
||||
let when_assignable = argument_type.when_constraint_set_assignable_to(
|
||||
self.db,
|
||||
expected_type,
|
||||
self.inferable_typevars,
|
||||
);
|
||||
for bound_typevar in generic_context_variables.clone() {
|
||||
let identity = bound_typevar.identity(self.db);
|
||||
if !when_assignable.mentions_typevar(self.db, identity) {
|
||||
continue;
|
||||
}
|
||||
let variance = expected_type.variance_of(self.db, bound_typevar);
|
||||
if variance != TypeVarVariance::Bivariant {
|
||||
variance_in_arguments
|
||||
.entry(identity)
|
||||
.and_modify(|current| *current = current.join(variance))
|
||||
.or_insert(variance);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -322,6 +322,18 @@ impl<'db> ConstraintSet<'db> {
|
|||
false
|
||||
}
|
||||
|
||||
pub(crate) fn mentions_typevar(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
bound_typevar: BoundTypeVarIdentity<'db>,
|
||||
) -> bool {
|
||||
let mut found = false;
|
||||
self.node.for_each_constraint(db, &mut |constraint| {
|
||||
found |= constraint.typevar(db).identity(db) == bound_typevar;
|
||||
});
|
||||
found
|
||||
}
|
||||
|
||||
/// Returns the constraints under which `lhs` is a subtype of `rhs`, assuming that the
|
||||
/// constraints in this constraint set hold. Panics if neither of the types being compared are
|
||||
/// a typevar. (That case is handled by `Type::has_relation_to`.)
|
||||
|
|
|
|||
Loading…
Reference in New Issue