mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-27 02:16:54 +00:00
[ty] Treat Callable dunder members as bound method descriptors (#20860)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / ty completion evaluation (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks instrumented (ruff) (push) Blocked by required conditions
CI / benchmarks instrumented (ty) (push) Blocked by required conditions
CI / benchmarks walltime (medium|multithreaded) (push) Blocked by required conditions
CI / benchmarks walltime (small|large) (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (linux, release) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Waiting to run
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz build (push) Blocked by required conditions
CI / fuzz parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / Fuzz for new ty panics (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / ty completion evaluation (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / check playground (push) Blocked by required conditions
CI / benchmarks instrumented (ruff) (push) Blocked by required conditions
CI / benchmarks instrumented (ty) (push) Blocked by required conditions
CI / benchmarks walltime (medium|multithreaded) (push) Blocked by required conditions
CI / benchmarks walltime (small|large) (push) Blocked by required conditions
[ty Playground] Release / publish (push) Waiting to run
## Summary Dunder methods (at least the ones defined in the standard library) always take an instance of the class as the first parameter. So it seems reasonable to generally treat them as bound method descriptors if they are defined via a `Callable` type. This removes just a few false positives from the ecosystem, but solves three user-reported issues: closes https://github.com/astral-sh/ty/issues/908 closes https://github.com/astral-sh/ty/issues/1143 closes https://github.com/astral-sh/ty/issues/1209 In addition to the change here, I also considered [making `ClassVar`s bound method descriptors](https://github.com/astral-sh/ruff/pull/20861). However, there was zero ecosystem impact. So I think we can also close https://github.com/astral-sh/ty/issues/491 with this PR. closes https://github.com/astral-sh/ty/issues/491 ## Test Plan Added regression test
This commit is contained in:
parent
ac2c530377
commit
6341bb7403
5 changed files with 82 additions and 11 deletions
|
|
@ -11116,6 +11116,23 @@ impl<'db> IntersectionType<'db> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Map a type transformation over all positive elements of the intersection. Leave the
|
||||
/// negative elements unchanged.
|
||||
pub(crate) fn map_positive(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
mut transform_fn: impl FnMut(&Type<'db>) -> Type<'db>,
|
||||
) -> Type<'db> {
|
||||
let mut builder = IntersectionBuilder::new(db);
|
||||
for ty in self.positive(db) {
|
||||
builder = builder.add_positive(transform_fn(ty));
|
||||
}
|
||||
for ty in self.negative(db) {
|
||||
builder = builder.add_negative(*ty);
|
||||
}
|
||||
builder.build()
|
||||
}
|
||||
|
||||
pub(crate) fn map_with_boundness(
|
||||
self,
|
||||
db: &'db dyn Db,
|
||||
|
|
|
|||
|
|
@ -2014,7 +2014,29 @@ impl<'db> ClassLiteral<'db> {
|
|||
name: &str,
|
||||
policy: MemberLookupPolicy,
|
||||
) -> PlaceAndQualifiers<'db> {
|
||||
self.class_member_inner(db, None, name, policy)
|
||||
fn into_function_like_callable<'d>(db: &'d dyn Db, ty: Type<'d>) -> Type<'d> {
|
||||
match ty {
|
||||
Type::Callable(callable_ty) => {
|
||||
Type::Callable(CallableType::new(db, callable_ty.signatures(db), true))
|
||||
}
|
||||
Type::Union(union) => {
|
||||
union.map(db, |element| into_function_like_callable(db, *element))
|
||||
}
|
||||
Type::Intersection(intersection) => intersection
|
||||
.map_positive(db, |element| into_function_like_callable(db, *element)),
|
||||
_ => ty,
|
||||
}
|
||||
}
|
||||
|
||||
let mut member = self.class_member_inner(db, None, name, policy);
|
||||
|
||||
// We generally treat dunder attributes with `Callable` types as function-like callables.
|
||||
// See `callables_as_descriptors.md` for more details.
|
||||
if name.starts_with("__") && name.ends_with("__") {
|
||||
member = member.map_type(|ty| into_function_like_callable(db, ty));
|
||||
}
|
||||
|
||||
member
|
||||
}
|
||||
|
||||
fn class_member_inner(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue