mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-29 13:25:17 +00:00
[red-knot] remove CallOutcome::Cast variant (#15461)
## Summary Simplification follow-up to #15413. There's no need to have a dedicated `CallOutcome` variant for every known function, it's only necessary if the special-cased behavior of the known function includes emitting extra diagnostics. For `typing.cast`, there's no such need; we can use the regular `Callable` outcome variant, and update the return type according to the cast. (This is the same way we already handle `len`.) One reason to avoid proliferating unnecessary `CallOutcome` variants is that currently we have to explicitly add emitting call-binding diagnostics, for each outcome variant. So we were previously wrongly silencing any binding diagnostics on calls to `typing.cast`. Fixing this revealed a separate bug, that we were emitting a bogus error anytime more than one keyword argument mapped to a `**kwargs` parameter. So this PR also adds test and fix for that bug. ## Test Plan Existing `cast` tests pass unchanged, added new test for `**kwargs` bug.
This commit is contained in:
parent
5ad546f187
commit
d54c19b983
4 changed files with 14 additions and 23 deletions
|
@ -2021,11 +2021,11 @@ impl<'db> Type<'db> {
|
|||
return CallOutcome::callable(binding);
|
||||
};
|
||||
|
||||
let Some(casted_ty) = arguments.first_argument() else {
|
||||
return CallOutcome::callable(binding);
|
||||
if let Some(casted_ty) = arguments.first_argument() {
|
||||
binding.set_return_ty(casted_ty);
|
||||
};
|
||||
|
||||
CallOutcome::casted(binding, casted_ty)
|
||||
CallOutcome::callable(binding)
|
||||
}
|
||||
|
||||
_ => CallOutcome::callable(binding),
|
||||
|
@ -3877,7 +3877,6 @@ impl<'db> Class<'db> {
|
|||
| CallOutcome::RevealType { binding, .. }
|
||||
| CallOutcome::StaticAssertionError { binding, .. }
|
||||
| CallOutcome::AssertType { binding, .. } => Ok(binding.return_ty()),
|
||||
CallOutcome::Cast { casted_ty, .. } => Ok(casted_ty),
|
||||
};
|
||||
|
||||
return return_ty_result.map(|ty| ty.to_meta_type(db));
|
||||
|
|
|
@ -48,14 +48,10 @@ pub(super) enum CallOutcome<'db> {
|
|||
binding: CallBinding<'db>,
|
||||
asserted_ty: Type<'db>,
|
||||
},
|
||||
Cast {
|
||||
binding: CallBinding<'db>,
|
||||
casted_ty: Type<'db>,
|
||||
},
|
||||
}
|
||||
|
||||
impl<'db> CallOutcome<'db> {
|
||||
/// Create a new `CallOutcome::Callable` with given return type.
|
||||
/// Create a new `CallOutcome::Callable` with given binding.
|
||||
pub(super) fn callable(binding: CallBinding<'db>) -> CallOutcome<'db> {
|
||||
CallOutcome::Callable { binding }
|
||||
}
|
||||
|
@ -92,11 +88,6 @@ impl<'db> CallOutcome<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Create a new `CallOutcome::Casted` with given casted and return types.
|
||||
pub(super) fn casted(binding: CallBinding<'db>, casted_ty: Type<'db>) -> CallOutcome<'db> {
|
||||
CallOutcome::Cast { binding, casted_ty }
|
||||
}
|
||||
|
||||
/// Get the return type of the call, or `None` if not callable.
|
||||
pub(super) fn return_ty(&self, db: &'db dyn Db) -> Option<Type<'db>> {
|
||||
match self {
|
||||
|
@ -128,10 +119,6 @@ impl<'db> CallOutcome<'db> {
|
|||
binding,
|
||||
asserted_ty: _,
|
||||
} => Some(binding.return_ty()),
|
||||
Self::Cast {
|
||||
binding: _,
|
||||
casted_ty,
|
||||
} => Some(*casted_ty),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -360,10 +347,6 @@ impl<'db> CallOutcome<'db> {
|
|||
|
||||
Ok(binding.return_ty())
|
||||
}
|
||||
Self::Cast {
|
||||
binding: _,
|
||||
casted_ty,
|
||||
} => Ok(*casted_ty),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -84,7 +84,7 @@ pub(crate) fn bind_call<'db>(
|
|||
}
|
||||
}
|
||||
if let Some(existing) = parameter_tys[index].replace(*argument_ty) {
|
||||
if parameter.is_variadic() {
|
||||
if parameter.is_variadic() || parameter.is_keyword_variadic() {
|
||||
let union = UnionType::from_elements(db, [existing, *argument_ty]);
|
||||
parameter_tys[index].replace(union);
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue