mirror of https://github.com/astral-sh/ruff
cs assignability for paramspecs
This commit is contained in:
parent
db488e3cf7
commit
056258c767
|
|
@ -392,15 +392,13 @@ def f3(x: int, y: str) -> int:
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
# TODO: This should reveal `(x: int, y: str) -> bool` but there's a cycle: https://github.com/astral-sh/ty/issues/1729
|
# TODO: This should reveal `(x: int, y: str) -> bool` but there's a cycle: https://github.com/astral-sh/ty/issues/1729
|
||||||
reveal_type(f3) # revealed: ((x: int, y: str) -> bool) | ((x: Divergent, y: Divergent) -> bool)
|
reveal_type(f3) # revealed: ((x: int, y: str) -> bool) | ((...) -> bool)
|
||||||
|
|
||||||
reveal_type(f3(1, "a")) # revealed: bool
|
reveal_type(f3(1, "a")) # revealed: bool
|
||||||
reveal_type(f3(x=1, y="a")) # revealed: bool
|
reveal_type(f3(x=1, y="a")) # revealed: bool
|
||||||
reveal_type(f3(1, y="a")) # revealed: bool
|
reveal_type(f3(1, y="a")) # revealed: bool
|
||||||
reveal_type(f3(y="a", x=1)) # revealed: bool
|
reveal_type(f3(y="a", x=1)) # revealed: bool
|
||||||
|
|
||||||
# TODO: There should only be one error but the type of `f3` is a union: https://github.com/astral-sh/ty/issues/1729
|
|
||||||
# error: [missing-argument] "No argument provided for required parameter `y`"
|
|
||||||
# error: [missing-argument] "No argument provided for required parameter `y`"
|
# error: [missing-argument] "No argument provided for required parameter `y`"
|
||||||
f3(1)
|
f3(1)
|
||||||
# error: [invalid-argument-type] "Argument is incorrect: Expected `int`, found `Literal["a"]`"
|
# error: [invalid-argument-type] "Argument is incorrect: Expected `int`, found `Literal["a"]`"
|
||||||
|
|
|
||||||
|
|
@ -29,10 +29,10 @@ use crate::types::generics::{
|
||||||
};
|
};
|
||||||
use crate::types::infer::nearest_enclosing_class;
|
use crate::types::infer::nearest_enclosing_class;
|
||||||
use crate::types::{
|
use crate::types::{
|
||||||
ApplyTypeMappingVisitor, BindingContext, BoundTypeVarInstance, CallableTypeKind, ClassLiteral,
|
ApplyTypeMappingVisitor, BindingContext, BoundTypeVarInstance, CallableType, CallableTypeKind,
|
||||||
FindLegacyTypeVarsVisitor, HasRelationToVisitor, IsDisjointVisitor, IsEquivalentVisitor,
|
ClassLiteral, FindLegacyTypeVarsVisitor, HasRelationToVisitor, IsDisjointVisitor,
|
||||||
KnownClass, MaterializationKind, NormalizedVisitor, ParamSpecAttrKind, TypeContext,
|
IsEquivalentVisitor, KnownClass, MaterializationKind, NormalizedVisitor, ParamSpecAttrKind,
|
||||||
TypeMapping, TypeRelation, VarianceInferable, todo_type,
|
TypeContext, TypeMapping, TypeRelation, VarianceInferable, todo_type,
|
||||||
};
|
};
|
||||||
use crate::{Db, FxOrderSet};
|
use crate::{Db, FxOrderSet};
|
||||||
use ruff_python_ast::{self as ast, name::Name};
|
use ruff_python_ast::{self as ast, name::Name};
|
||||||
|
|
@ -1145,6 +1145,57 @@ impl<'db> Signature<'db> {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If either parameter list is a ParamSpec, then we can create a constraint set that holds
|
||||||
|
// when the ParamSpec is assignable to the other parameter list.
|
||||||
|
if relation.is_constraint_set_assignability() {
|
||||||
|
match (
|
||||||
|
self.parameters.as_paramspec(),
|
||||||
|
other.parameters.as_paramspec(),
|
||||||
|
) {
|
||||||
|
(Some(self_bound_typevar), Some(other_bound_typevar)) => {
|
||||||
|
return ConstraintSet::constrain_typevar(
|
||||||
|
db,
|
||||||
|
self_bound_typevar,
|
||||||
|
Type::TypeVar(other_bound_typevar),
|
||||||
|
Type::TypeVar(other_bound_typevar),
|
||||||
|
relation,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
(Some(self_bound_typevar), None) => {
|
||||||
|
let upper = Type::Callable(CallableType::new(
|
||||||
|
db,
|
||||||
|
CallableSignature::single(Signature::new(other.parameters.clone(), None)),
|
||||||
|
CallableTypeKind::ParamSpecValue,
|
||||||
|
));
|
||||||
|
return ConstraintSet::constrain_typevar(
|
||||||
|
db,
|
||||||
|
self_bound_typevar,
|
||||||
|
Type::Never,
|
||||||
|
upper,
|
||||||
|
relation,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
(None, Some(other_bound_typevar)) => {
|
||||||
|
let lower = Type::Callable(CallableType::new(
|
||||||
|
db,
|
||||||
|
CallableSignature::single(Signature::new(self.parameters.clone(), None)),
|
||||||
|
CallableTypeKind::ParamSpecValue,
|
||||||
|
));
|
||||||
|
return ConstraintSet::constrain_typevar(
|
||||||
|
db,
|
||||||
|
other_bound_typevar,
|
||||||
|
lower,
|
||||||
|
Type::object(),
|
||||||
|
relation,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
(None, None) => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut parameters = ParametersZip {
|
let mut parameters = ParametersZip {
|
||||||
current_self: None,
|
current_self: None,
|
||||||
current_other: None,
|
current_other: None,
|
||||||
|
|
@ -1562,6 +1613,13 @@ impl<'db> Parameters<'db> {
|
||||||
matches!(self.kind, ParametersKind::Gradual)
|
matches!(self.kind, ParametersKind::Gradual)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) const fn as_paramspec(&self) -> Option<BoundTypeVarInstance<'db>> {
|
||||||
|
match self.kind {
|
||||||
|
ParametersKind::ParamSpec(bound_typevar) => Some(bound_typevar),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return todo parameters: (*args: Todo, **kwargs: Todo)
|
/// Return todo parameters: (*args: Todo, **kwargs: Todo)
|
||||||
pub(crate) fn todo() -> Self {
|
pub(crate) fn todo() -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue