From e1b662bf5d5d38463e5303e30ef65c8d8682aa0c Mon Sep 17 00:00:00 2001 From: David Peter Date: Mon, 26 May 2025 13:20:27 +0200 Subject: [PATCH] [ty] Always pass `NO_INSTANCE_FALLBACK` in `try_call_dunder_with_policy` (#18315) ## Summary The previous `try_call_dunder_with_policy` API was a bit of a footgun since you needed to pass `NO_INSTANCE_FALLBACK` in *addition* to other policies that you wanted for the member lookup. Implicit calls to dunder methods never access instance members though, so we can do this implicitly in `try_call_dunder_with_policy`. No functional changes. --- crates/ty_python_semantic/src/types.rs | 16 ++++++++++++---- crates/ty_python_semantic/src/types/infer.rs | 3 +-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/crates/ty_python_semantic/src/types.rs b/crates/ty_python_semantic/src/types.rs index e1a8f9debb..fcab31b7a7 100644 --- a/crates/ty_python_semantic/src/types.rs +++ b/crates/ty_python_semantic/src/types.rs @@ -3214,8 +3214,7 @@ impl<'db> Type<'db> { &mut CallArgumentTypes::positional([Type::StringLiteral( StringLiteralType::new(db, Box::from(name.as_str())), )]), - MemberLookupPolicy::MRO_NO_OBJECT_FALLBACK - | MemberLookupPolicy::NO_INSTANCE_FALLBACK, + MemberLookupPolicy::MRO_NO_OBJECT_FALLBACK, ) .map(|outcome| Symbol::bound(outcome.return_type(db))) // TODO: Handle call errors here. @@ -4415,7 +4414,7 @@ impl<'db> Type<'db> { db, name, &mut argument_types, - MemberLookupPolicy::NO_INSTANCE_FALLBACK, + MemberLookupPolicy::default(), ) } @@ -4423,6 +4422,9 @@ impl<'db> Type<'db> { /// particular, this allows to specify `MemberLookupPolicy::MRO_NO_OBJECT_FALLBACK` to avoid /// looking up dunder methods on `object`, which is needed for functions like `__init__`, /// `__new__`, or `__setattr__`. + /// + /// Note that `NO_INSTANCE_FALLBACK` is always added to the policy, since implicit calls to + /// dunder methods never access instance members. fn try_call_dunder_with_policy( self, db: &'db dyn Db, @@ -4430,8 +4432,14 @@ impl<'db> Type<'db> { argument_types: &mut CallArgumentTypes<'_, 'db>, policy: MemberLookupPolicy, ) -> Result, CallDunderError<'db>> { + // Implicit calls to dunder methods never access instance members, so we pass + // `NO_INSTANCE_FALLBACK` here in addition to other policies: match self - .member_lookup_with_policy(db, name.into(), policy) + .member_lookup_with_policy( + db, + name.into(), + policy | MemberLookupPolicy::NO_INSTANCE_FALLBACK, + ) .symbol { Symbol::Type(dunder_callable, boundness) => { diff --git a/crates/ty_python_semantic/src/types/infer.rs b/crates/ty_python_semantic/src/types/infer.rs index 614bfbb540..bddbe9f836 100644 --- a/crates/ty_python_semantic/src/types/infer.rs +++ b/crates/ty_python_semantic/src/types/infer.rs @@ -3231,8 +3231,7 @@ impl<'db> TypeInferenceBuilder<'db> { )), value_ty, ]), - MemberLookupPolicy::NO_INSTANCE_FALLBACK - | MemberLookupPolicy::MRO_NO_OBJECT_FALLBACK, + MemberLookupPolicy::MRO_NO_OBJECT_FALLBACK, ); match result {