mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 20:10:09 +00:00
[red-knot] Fix more redundant-cast
false positives (#17119)
## Summary
There are quite a few places we infer `Todo` types currently, and some
of them are nested somewhat deeply in type expressions. These can cause
spurious issues for the new `redundant-cast` diagnostics. We fixed all
the false positives we saw in the mypy_primer report before merging
https://github.com/astral-sh/ruff/pull/17100, but I think there are
still lots of places where we'd emit false positives due to this check
-- we currently don't run on that many projects at all in our
mypy_primer check:
d0c8eaa092/.github/workflows/mypy_primer.yaml (L71)
This PR fixes some more false positives from this diagnostic by making
the `Type::contains_todo()` method more expansive.
## Test Plan
I added a regression test which causes us to emit a spurious diagnostic
on `main`, but does not with this PR.
This commit is contained in:
parent
a15404a5c1
commit
c74ba00219
2 changed files with 65 additions and 2 deletions
|
@ -38,3 +38,14 @@ def function_returning_any() -> Any:
|
||||||
# error: [redundant-cast] "Value is already of type `Any`"
|
# error: [redundant-cast] "Value is already of type `Any`"
|
||||||
cast(Any, function_returning_any())
|
cast(Any, function_returning_any())
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Complex type expressions (which may be unsupported) do not lead to spurious `[redundant-cast]`
|
||||||
|
diagnostics.
|
||||||
|
|
||||||
|
```py
|
||||||
|
from typing import Callable
|
||||||
|
|
||||||
|
def f(x: Callable[[dict[str, int]], None], y: tuple[dict[str, int]]):
|
||||||
|
a = cast(Callable[[list[bytes]], None], x)
|
||||||
|
b = cast(tuple[list[bytes]], y)
|
||||||
|
```
|
||||||
|
|
|
@ -321,8 +321,60 @@ impl<'db> Type<'db> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn contains_todo(&self, db: &'db dyn Db) -> bool {
|
pub fn contains_todo(&self, db: &'db dyn Db) -> bool {
|
||||||
self.is_todo()
|
match self {
|
||||||
|| matches!(self, Type::Union(union) if union.elements(db).iter().any(Type::is_todo))
|
Self::Dynamic(DynamicType::Todo(_) | DynamicType::TodoProtocol) => true,
|
||||||
|
|
||||||
|
Self::AlwaysFalsy
|
||||||
|
| Self::AlwaysTruthy
|
||||||
|
| Self::Never
|
||||||
|
| Self::BooleanLiteral(_)
|
||||||
|
| Self::BytesLiteral(_)
|
||||||
|
| Self::FunctionLiteral(_)
|
||||||
|
| Self::Instance(_)
|
||||||
|
| Self::ModuleLiteral(_)
|
||||||
|
| Self::ClassLiteral(_)
|
||||||
|
| Self::KnownInstance(_)
|
||||||
|
| Self::StringLiteral(_)
|
||||||
|
| Self::IntLiteral(_)
|
||||||
|
| Self::LiteralString
|
||||||
|
| Self::SliceLiteral(_)
|
||||||
|
| Self::Dynamic(DynamicType::Unknown | DynamicType::Any)
|
||||||
|
| Self::Callable(
|
||||||
|
CallableType::BoundMethod(_)
|
||||||
|
| CallableType::WrapperDescriptorDunderGet
|
||||||
|
| CallableType::MethodWrapperDunderGet(_),
|
||||||
|
) => false,
|
||||||
|
|
||||||
|
Self::Callable(CallableType::General(callable)) => {
|
||||||
|
let signature = callable.signature(db);
|
||||||
|
signature.parameters().iter().any(|param| {
|
||||||
|
param
|
||||||
|
.annotated_type()
|
||||||
|
.is_some_and(|ty| ty.contains_todo(db))
|
||||||
|
}) || signature.return_ty.is_some_and(|ty| ty.contains_todo(db))
|
||||||
|
}
|
||||||
|
|
||||||
|
Self::SubclassOf(subclass_of) => match subclass_of.subclass_of() {
|
||||||
|
ClassBase::Dynamic(DynamicType::Todo(_) | DynamicType::TodoProtocol) => true,
|
||||||
|
ClassBase::Dynamic(DynamicType::Unknown | DynamicType::Any) => false,
|
||||||
|
ClassBase::Class(_) => false,
|
||||||
|
},
|
||||||
|
|
||||||
|
Self::Tuple(tuple) => tuple.elements(db).iter().any(|ty| ty.contains_todo(db)),
|
||||||
|
|
||||||
|
Self::Union(union) => union.elements(db).iter().any(|ty| ty.contains_todo(db)),
|
||||||
|
|
||||||
|
Self::Intersection(intersection) => {
|
||||||
|
intersection
|
||||||
|
.positive(db)
|
||||||
|
.iter()
|
||||||
|
.any(|ty| ty.contains_todo(db))
|
||||||
|
|| intersection
|
||||||
|
.negative(db)
|
||||||
|
.iter()
|
||||||
|
.any(|ty| ty.contains_todo(db))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn class_literal(class: Class<'db>) -> Self {
|
pub const fn class_literal(class: Class<'db>) -> Self {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue